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 42 struct 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 56 struct 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 71 struct 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 100 struct mc680x0_type_0_frame { 101 uint16 sr; 102 addr_t pc; 103 uint16 type:4; 104 uint16 vector:12; 105 }; 106 107 struct mc680x0_type_1_frame { 108 uint16 sr; 109 addr_t pc; 110 uint16 type:4; 111 uint16 vector:12; 112 }; 113 114 struct 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 122 struct 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 130 struct 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 153 struct 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 162 struct 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 177 struct 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 200 struct 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 220 struct mc680x0_null_fpu_state { 221 uint8 version; // 0 222 uint8 type; // undefined 223 uint16 dummy; 224 }; 225 226 struct mc680x0_type_00_fpu_state { 227 uint8 version; 228 uint8 type; // 0 229 uint16 dummy; 230 }; 231 232 struct 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 240 struct 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: 250 struct 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 258 struct 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 274 struct mc680x0_fp_data_reg { 275 uint8 data[12]; 276 }; 277 278 struct 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 287 struct 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 */ 379 enum 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 392 typedef struct arch_cpu_info { 393 int null; 394 } arch_cpu_info; 395 396 397 #ifdef __cplusplus 398 extern "C" { 399 #endif 400 401 #if 0 402 //PPC stuff 403 extern uint32 get_sdr1(void); 404 extern void set_sdr1(uint32 value); 405 extern uint32 get_sr(void *virtualAddress); 406 extern void set_sr(void *virtualAddress, uint32 value); 407 extern uint32 get_msr(void); 408 extern uint32 set_msr(uint32 value); 409 extern uint32 get_pvr(void); 410 411 extern void set_ibat0(struct block_address_translation *bat); 412 extern void set_ibat1(struct block_address_translation *bat); 413 extern void set_ibat2(struct block_address_translation *bat); 414 extern void set_ibat3(struct block_address_translation *bat); 415 extern void set_dbat0(struct block_address_translation *bat); 416 extern void set_dbat1(struct block_address_translation *bat); 417 extern void set_dbat2(struct block_address_translation *bat); 418 extern void set_dbat3(struct block_address_translation *bat); 419 420 extern void get_ibat0(struct block_address_translation *bat); 421 extern void get_ibat1(struct block_address_translation *bat); 422 extern void get_ibat2(struct block_address_translation *bat); 423 extern void get_ibat3(struct block_address_translation *bat); 424 extern void get_dbat0(struct block_address_translation *bat); 425 extern void get_dbat1(struct block_address_translation *bat); 426 extern void get_dbat2(struct block_address_translation *bat); 427 extern void get_dbat3(struct block_address_translation *bat); 428 429 extern void reset_ibats(void); 430 extern 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); 436 extern long long get_time_base(void); 437 438 void __m68k_setup_system_time(vint32 *cvFactor); 439 // defined in libroot: os/arch/system_time.c 440 int64 __m68k_get_time_base(void); 441 // defined in libroot: os/arch/system_time_asm.S 442 443 extern void m68k_context_switch(void **_oldStackPointer, void *newStackPointer); 444 445 extern bool m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler) 446 __attribute__((noinline)); 447 448 extern bool m68k_is_hw_register_readable(addr_t address); 449 extern bool m68k_is_hw_register_writable(addr_t address, uint16 value); 450 // defined in kernel: arch/m68k/cpu_asm.S 451 452 453 static inline void 454 arch_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 463 static inline void 464 arch_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 476 struct 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 486 extern 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. 504 enum 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 518 enum 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 529 enum 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 539 extern int arch_cpu_type; 540 extern int arch_fpu_type; 541 extern int arch_mmu_type; 542 extern int arch_platform; 543 extern 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