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