1/*
2** Copyright 2003-2004, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3** Distributed under the terms of the MIT License.
4*/
5#ifndef _KERNEL_ARCH_M68K_CPU_H
6#define _KERNEL_ARCH_M68K_CPU_H
7
8#ifndef _ASSEMBLER
9
10#include <arch/m68k/arch_thread_types.h>
11#include <kernel.h>
12
13#endif	// !_ASSEMBLER
14
15
16#define CPU_MAX_CACHE_LEVEL	8
17
18#define CACHE_LINE_SIZE		16
19
20
21#define set_ac()
22#define clear_ac()
23
24
25#define SR_IP_MASK 0x0700
26#define SR_S 0x2000
27#define M68K_SR_S 13
28#define M68K_SR_T_MASK 0xC000
29#define M68K_SR_T0 14
30#define M68K_SR_T1 15
31
32#ifndef _ASSEMBLER
33
34/* 68k has many different possible stack frames, differentiated by a 4 bit number,
35 * but they also depend on the cpu type.
36 * cf. mint/sys/arch/check_exc.h
37 */
38
39/* definitions for special status word */
40
41// 020 as well
42struct mc68030_ssw {
43	uint16 fc:1;
44	uint16 fb:1;
45	uint16 rc:1;
46	uint16 rb:1;
47	uint16 :3;
48	uint16 df:1;
49	uint16 rm:1;
50	uint16 rw:1;
51	uint16 size:2;
52	uint16 :1;
53	uint16 as:3;
54} _PACKED;
55
56struct mc68040_ssw {
57	uint16 cp:1;
58	uint16 cu:1;
59	uint16 ct:1;
60	uint16 cm:1;
61	uint16 ma:1;
62	uint16 atc:1;
63	uint16 lk:1;
64	uint16 rw:1;
65	uint16 :1;
66	uint16 size:2;
67	uint16 tt:2;
68	uint16 tm:3;
69} _PACKED;
70
71struct mc68060_fslw {
72	uint32 :4;
73	uint32 ma:1;
74	uint32 :1;
75	uint32 lk:1;
76	uint32 rw:2; //XXX ??
77	uint32 size:2;
78	uint32 tt:2;
79	uint32 tm:2;
80	uint32 io:1;
81	uint32 pbe:1;
82	uint32 sbe:1;
83	uint32 pta:1;
84	uint32 ptb:1;
85	uint32 il:1;
86	uint32 pf:1;
87	uint32 sb:1;
88	uint32 wp:1;
89	uint32 twe:1;
90	uint32 re:1;
91	uint32 we:1;
92	uint32 ttr:1;
93	uint32 bpe:1;
94	uint32 :1;
95	uint32 see:1;
96} _PACKED;
97
98/* raw exception frames */
99
100struct mc680x0_type_0_frame {
101	uint16 sr;
102	addr_t pc;
103	uint16 type:4;
104	uint16 vector:12;
105};
106
107struct mc680x0_type_1_frame {
108	uint16 sr;
109	addr_t pc;
110	uint16 type:4;
111	uint16 vector:12;
112};
113
114struct mc680x0_type_2_frame {
115	uint16 sr;
116	addr_t pc;
117	uint16 type:4;
118	uint16 vector:12;
119	addr_t instruction_address;
120};
121
122struct mc680x0_type_3_frame {
123	uint16 sr;
124	addr_t pc;
125	uint16 type:4;
126	uint16 vector:12;
127	addr_t effective_address;
128};
129
130struct mc68040_type_7_frame {
131	uint16 sr;
132	addr_t pc;
133	uint16 type:4;
134	uint16 vector:12;
135	addr_t effective_address;
136	struct mc68040_ssw ssw;
137	// write-back status
138	uint16 wb3s;
139	uint16 wb2s;
140	uint16 wb1s;
141	addr_t fault_address;
142	addr_t wb3a;
143	uint32 wb3d;
144	addr_t wb2a;
145	uint32 wb2d;
146	addr_t wb1a;
147	uint32 wb1d; // also pd0
148	uint32 pd1;
149	uint32 pd2;
150	uint32 pd3;
151};
152
153struct mc680x0_type_9_frame {
154	uint16 sr;
155	addr_t pc;
156	uint16 type:4;
157	uint16 vector:12;
158	addr_t instruction_address;
159	uint16 intregs[4];
160};
161
162struct mc68030_type_a_frame {
163	uint16 sr;
164	addr_t pc;
165	uint16 type:4;
166	uint16 vector:12;
167	uint16 intreg1;
168	struct mc68030_ssw ssw;
169	uint16 instpipe_c;
170	uint16 instpipe_b;
171	addr_t fault_address;
172	uint16 intregs2[2];
173	uint32 dataout;
174	uint16 intregs3[2];
175};
176
177struct mc68030_type_b_frame {
178	uint16 sr;
179	addr_t pc;
180	uint16 type:4;
181	uint16 vector:12;
182	uint16 intreg1;
183	struct mc68030_ssw ssw;
184	uint16 instpipe_c;
185	uint16 instpipe_b;
186	addr_t fault_address;
187	uint16 intregs2[2];
188	uint32 dataout;
189	uint16 intregs3[4];
190	uint32 stbaddr;
191	uint16 intregs4[2];
192	uint32 datain;
193	uint16 intregs5[3];
194	uint16 intinfo;
195	uint16 intregs6[18];
196};
197
198//XXX: add 060 frames
199
200struct mc680x0_frame {
201	union {
202		struct {
203			uint16 sr;
204			addr_t pc;
205			uint16 type:4;
206			uint16 vector:12;
207		};
208		struct mc680x0_type_0_frame type_0;
209		struct mc680x0_type_1_frame type_1;
210		struct mc680x0_type_3_frame type_3;
211		struct mc680x0_type_2_frame type_2;
212		struct mc68040_type_7_frame type_7;
213		struct mc680x0_type_9_frame type_9;
214		struct mc68030_type_a_frame type_a;
215		struct mc68030_type_b_frame type_b;
216		// XXX: add 060 frames
217	};
218};
219
220struct mc680x0_null_fpu_state {
221	uint8 version; // 0
222	uint8 type; // undefined
223	uint16 dummy;
224};
225
226struct mc680x0_type_00_fpu_state {
227	uint8 version;
228	uint8 type; // 0
229	uint16 dummy;
230};
231
232struct mc680x0_type_28_fpu_state {
233	uint8 version;
234	uint8 type; // 0x28
235	uint16 dummy;
236	// XXX: replace dummies
237	uint32 dummies[0x28/4];
238};
239
240struct mc680x0_type_60_fpu_state {
241	uint8 version;
242	uint8 type; // 0x60
243	uint16 dummy;
244	// XXX: replace dummies
245	uint32 dummies[0x60/4];
246};
247
248//XXX: those are 040, add others
249// biggest known:
250struct mc68882_type_d4_fpu_state {
251	uint8 version;
252	uint8 type; // 0xd4
253	uint16 dummy;
254	// XXX: replace dummies
255	uint32 dummies[0xd4/4];
256};
257
258struct mc680x0_fpu_state {
259	union {
260		struct {
261			uint8 version;
262			uint8 type; // 0x60
263			uint16 dummy;
264		};
265		struct mc680x0_null_fpu_state null;
266		struct mc680x0_type_00_fpu_state type_00;
267		struct mc680x0_type_28_fpu_state type_28;
268		struct mc680x0_type_60_fpu_state type_60;
269		struct mc68882_type_d4_fpu_state type_d4;
270	};
271};
272
273// 96-bit format
274struct mc680x0_fp_data_reg {
275	uint8 data[12];
276};
277
278struct mc680x0_fp_control_regs {
279	uint32 fpcr;
280	uint32 fpsr;
281	uint32 fpiar;
282};
283
284
285
286#warning M68K: check for missing regs/movem
287struct iframe {
288	/* fpu data registers */
289#warning M68K: sizeof(fp*)
290	struct mc680x0_fp_data_reg fp[8];
291	/* fpu control registers */
292	struct mc680x0_fp_control_regs fpc;
293	/* fpu state */
294	struct mc680x0_fpu_state fpu;
295
296	/* data and address registers */
297	uint32 d[8];
298	uint32 a[7];
299	/* cpu exception frame, including sr, pc, format and vector */
300	struct mc680x0_frame cpu;
301
302/*	uint32 vector;
303	uint32 srr0;
304	uint32 srr1;
305	uint32 dar;
306	uint32 dsisr;
307	uint32 lr;
308	uint32 cr;
309	uint32 xer;
310	uint32 ctr;
311	uint32 fpscr;
312	uint32 r31;
313	uint32 r30;
314	uint32 r29;
315	uint32 r28;
316	uint32 r27;
317	uint32 r26;
318	uint32 r25;
319	uint32 r24;
320	uint32 r23;
321	uint32 r22;
322	uint32 r21;
323	uint32 r20;
324	uint32 r19;
325	uint32 r18;
326	uint32 r17;
327	uint32 r16;
328	uint32 r15;
329	uint32 r14;
330	uint32 r13;
331	uint32 r12;
332	uint32 r11;
333	uint32 r10;
334	uint32 r9;
335	uint32 r8;
336	uint32 r7;
337	uint32 r6;
338	uint32 r5;
339	uint32 r4;
340	uint32 r3;
341	uint32 r2;
342	uint32 r1;
343	uint32 r0;
344	double f31;
345	double f30;
346	double f29;
347	double f28;
348	double f27;
349	double f26;
350	double f25;
351	double f24;
352	double f23;
353	double f22;
354	double f21;
355	double f20;
356	double f19;
357	double f18;
358	double f17;
359	double f16;
360	double f15;
361	double f14;
362	double f13;
363	double f12;
364	double f11;
365	double f10;
366	double f9;
367	double f8;
368	double f7;
369	double f6;
370	double f5;
371	double f4;
372	double f3;
373	double f2;
374	double f1;
375	double f0;*/
376} _PACKED;
377
378#if 0 /* ppc */
379enum machine_state {
380	MSR_EXCEPTIONS_ENABLED			= 1L << 15,		// EE
381	MSR_PRIVILEGE_LEVEL				= 1L << 14,		// PR
382	MSR_FP_AVAILABLE				= 1L << 13,		// FP
383	MSR_MACHINE_CHECK_ENABLED		= 1L << 12,		// ME
384	MSR_EXCEPTION_PREFIX			= 1L << 6,		// IP
385	MSR_INST_ADDRESS_TRANSLATION	= 1L << 5,		// IR
386	MSR_DATA_ADDRESS_TRANSLATION	= 1L << 4,		// DR
387};
388
389//struct block_address_translation;
390#endif
391
392typedef struct arch_cpu_info {
393	int null;
394} arch_cpu_info;
395
396
397#ifdef __cplusplus
398extern "C" {
399#endif
400
401#if 0
402//PPC stuff
403extern uint32 get_sdr1(void);
404extern void set_sdr1(uint32 value);
405extern uint32 get_sr(void *virtualAddress);
406extern void set_sr(void *virtualAddress, uint32 value);
407extern uint32 get_msr(void);
408extern uint32 set_msr(uint32 value);
409extern uint32 get_pvr(void);
410
411extern void set_ibat0(struct block_address_translation *bat);
412extern void set_ibat1(struct block_address_translation *bat);
413extern void set_ibat2(struct block_address_translation *bat);
414extern void set_ibat3(struct block_address_translation *bat);
415extern void set_dbat0(struct block_address_translation *bat);
416extern void set_dbat1(struct block_address_translation *bat);
417extern void set_dbat2(struct block_address_translation *bat);
418extern void set_dbat3(struct block_address_translation *bat);
419
420extern void get_ibat0(struct block_address_translation *bat);
421extern void get_ibat1(struct block_address_translation *bat);
422extern void get_ibat2(struct block_address_translation *bat);
423extern void get_ibat3(struct block_address_translation *bat);
424extern void get_dbat0(struct block_address_translation *bat);
425extern void get_dbat1(struct block_address_translation *bat);
426extern void get_dbat2(struct block_address_translation *bat);
427extern void get_dbat3(struct block_address_translation *bat);
428
429extern void reset_ibats(void);
430extern void reset_dbats(void);
431#endif
432
433//extern void sethid0(unsigned int val);
434//extern unsigned int getl2cr(void);
435//extern void setl2cr(unsigned int val);
436extern long long get_time_base(void);
437
438void __m68k_setup_system_time(vint32 *cvFactor);
439	// defined in libroot: os/arch/system_time.c
440int64 __m68k_get_time_base(void);
441	// defined in libroot: os/arch/system_time_asm.S
442
443extern void m68k_context_switch(void **_oldStackPointer, void *newStackPointer);
444
445extern bool m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler)
446	__attribute__((noinline));
447
448extern bool m68k_is_hw_register_readable(addr_t address);
449extern bool m68k_is_hw_register_writable(addr_t address, uint16 value);
450	// defined in kernel: arch/m68k/cpu_asm.S
451
452
453static inline void
454arch_cpu_idle(void)
455{
456	// TODO: M68K CPU idle call
457	// there isn't really any insn for this. Maybe NOP/FNOP?
458	// TODO: make a 060 module using LPSTOP
459	//asm volatile ("lpstop");
460}
461
462
463static inline void
464arch_cpu_pause(void)
465{
466	// TODO: M68K STOP call
467	// the problem is STOP wants an immediate to put into SR
468	// but we don't want to overwrite it.
469	//asm volatile("stop #0" : : : "memory");
470}
471
472#ifdef __cplusplus
473}
474#endif
475
476struct m68k_cpu_ops {
477	void (*flush_insn_pipeline)(void);
478	void (*flush_atc_all)(void);
479	void (*flush_atc_user)(void);
480	void (*flush_atc_addr)(addr_t addr);
481	void (*flush_dcache)(addr_t address, size_t len);
482	void (*flush_icache)(addr_t address, size_t len);
483	void (*idle)(void);
484};
485
486extern struct m68k_cpu_ops cpu_ops;
487
488//#define
489
490#if 0
491#define eieio()	asm volatile("eieio")
492#define isync() asm volatile("isync")
493#define tlbsync() asm volatile("tlbsync")
494#define ppc_sync() asm volatile("sync")
495#define tlbia() asm volatile("tlbia")
496#define tlbie(addr) asm volatile("tlbie %0" :: "r" (addr))
497#endif
498
499#if 0
500
501// XXX: not used: we just use decimal chip number, like 68030
502
503// m68k processor version.
504enum m68k_processor_version {
505	/* those two we don't support */
506	CPU_68000		= 0x0000,
507	CPU_68010		= 0x0001,
508	/* maybe with a pmmu and fpu */
509	CPU_68020		= 0x0002,
510	/* should work */
511	CPU_68030		= 0x0003,
512	CPU_68040		= 0x0004,
513	CPU_68060		= 0x0006,
514	/* mask */
515	CPU_MASK		= 0x000F
516};
517
518enum m68k_fpu_version {
519	/* we don't support */
520	FPU_NONE		= 0x0000,
521	FPU_68881		= 0x0010,
522	FPU_68882		= 0x0020,
523	FPU_030			= 0x0030,
524	FPU_040			= 0x0040,
525	FPU_060			= 0x0060,
526	FPU_MASK		= 0x00F0
527};
528
529enum m68k_mmu_version {
530	MMU_NONE		= 0x0000,
531	MMU_68551		= 0x0100,
532	MMU_68030		= 0x0300,
533	MMU_68040		= 0x0400,
534	MMU_68060		= 0x0600,
535	MMU_MASK		= 0x0F00
536};
537#endif
538
539extern int arch_cpu_type;
540extern int arch_fpu_type;
541extern int arch_mmu_type;
542extern int arch_platform;
543extern int arch_machine;
544
545/*
546	Use of (some) special purpose registers.
547	XXX: those regs aren't implemented/accessed the same way on different cpus...
548
549	SRP[63-32]: current Thread*
550	SRP[31-0] :
551	CAAR      : can we use it ??
552	MSP       :
553
554	PPC:
555	SPRG0: per CPU physical address pointer to an ppc_cpu_exception_context
556	       structure
557	SPRG1: scratch
558	SPRG2: current Thread*
559	SPRG3: TLS base pointer (only for userland threads)
560*/
561
562#endif	// !_ASSEMBLER
563
564#endif	/* _KERNEL_ARCH_PPC_CPU_H */
565