| 147 |
void execute_emul_op_idle_time_1(); |
void execute_emul_op_idle_time_1(); |
| 148 |
void execute_emul_op_idle_time_2(); |
void execute_emul_op_idle_time_2(); |
| 149 |
|
|
| 150 |
|
// CPU context to preserve on interrupt |
| 151 |
|
class interrupt_context { |
| 152 |
|
uint32 gpr[32]; |
| 153 |
|
uint32 pc; |
| 154 |
|
uint32 lr; |
| 155 |
|
uint32 ctr; |
| 156 |
|
uint32 cr; |
| 157 |
|
uint32 xer; |
| 158 |
|
sheepshaver_cpu *cpu; |
| 159 |
|
const char *where; |
| 160 |
|
public: |
| 161 |
|
interrupt_context(sheepshaver_cpu *_cpu, const char *_where); |
| 162 |
|
~interrupt_context(); |
| 163 |
|
}; |
| 164 |
|
|
| 165 |
public: |
public: |
| 166 |
|
|
| 167 |
// Constructor |
// Constructor |
| 548 |
return COMPILE_FAILURE; |
return COMPILE_FAILURE; |
| 549 |
} |
} |
| 550 |
|
|
| 551 |
|
// CPU context to preserve on interrupt |
| 552 |
|
sheepshaver_cpu::interrupt_context::interrupt_context(sheepshaver_cpu *_cpu, const char *_where) |
| 553 |
|
{ |
| 554 |
|
#if SAFE_INTERRUPT_PPC >= 2 |
| 555 |
|
cpu = _cpu; |
| 556 |
|
where = _where; |
| 557 |
|
|
| 558 |
|
// Save interrupt context |
| 559 |
|
memcpy(&gpr[0], &cpu->gpr(0), sizeof(gpr)); |
| 560 |
|
pc = cpu->pc(); |
| 561 |
|
lr = cpu->lr(); |
| 562 |
|
ctr = cpu->ctr(); |
| 563 |
|
cr = cpu->get_cr(); |
| 564 |
|
xer = cpu->get_xer(); |
| 565 |
|
#endif |
| 566 |
|
} |
| 567 |
|
|
| 568 |
|
sheepshaver_cpu::interrupt_context::~interrupt_context() |
| 569 |
|
{ |
| 570 |
|
#if SAFE_INTERRUPT_PPC >= 2 |
| 571 |
|
// Check whether CPU context was preserved by interrupt |
| 572 |
|
if (memcmp(&gpr[0], &cpu->gpr(0), sizeof(gpr)) != 0) { |
| 573 |
|
printf("FATAL: %s: interrupt clobbers registers\n", where); |
| 574 |
|
for (int i = 0; i < 32; i++) |
| 575 |
|
if (gpr[i] != cpu->gpr(i)) |
| 576 |
|
printf(" r%d: %08x -> %08x\n", i, gpr[i], cpu->gpr(i)); |
| 577 |
|
} |
| 578 |
|
if (pc != cpu->pc()) |
| 579 |
|
printf("FATAL: %s: interrupt clobbers PC\n", where); |
| 580 |
|
if (lr != cpu->lr()) |
| 581 |
|
printf("FATAL: %s: interrupt clobbers LR\n", where); |
| 582 |
|
if (ctr != cpu->ctr()) |
| 583 |
|
printf("FATAL: %s: interrupt clobbers CTR\n", where); |
| 584 |
|
if (cr != cpu->get_cr()) |
| 585 |
|
printf("FATAL: %s: interrupt clobbers CR\n", where); |
| 586 |
|
if (xer != cpu->get_xer()) |
| 587 |
|
printf("FATAL: %s: interrupt clobbers XER\n", where); |
| 588 |
|
#endif |
| 589 |
|
} |
| 590 |
|
|
| 591 |
// Handle MacOS interrupt |
// Handle MacOS interrupt |
| 592 |
void sheepshaver_cpu::interrupt(uint32 entry) |
void sheepshaver_cpu::interrupt(uint32 entry) |
| 593 |
{ |
{ |
| 602 |
printf("FATAL: sheepshaver_cpu::interrupt() called more than once: %d\n", depth); |
printf("FATAL: sheepshaver_cpu::interrupt() called more than once: %d\n", depth); |
| 603 |
depth++; |
depth++; |
| 604 |
#endif |
#endif |
|
#if SAFE_INTERRUPT_PPC >= 2 |
|
|
uint32 saved_regs[32]; |
|
|
memcpy(&saved_regs[0], &gpr(0), sizeof(saved_regs)); |
|
|
#endif |
|
| 605 |
|
|
| 606 |
#if !MULTICORE_CPU |
#if !MULTICORE_CPU |
| 607 |
// Save program counters and branch registers |
// Save program counters and branch registers |
| 661 |
interrupt_time += (clock() - interrupt_start); |
interrupt_time += (clock() - interrupt_start); |
| 662 |
#endif |
#endif |
| 663 |
|
|
|
#if SAFE_INTERRUPT_PPC >= 2 |
|
|
if (memcmp(&saved_regs[0], &gpr(0), sizeof(saved_regs)) != 0) |
|
|
printf("FATAL: dirty PowerPC registers\n"); |
|
|
#endif |
|
| 664 |
#if SAFE_INTERRUPT_PPC |
#if SAFE_INTERRUPT_PPC |
| 665 |
depth--; |
depth--; |
| 666 |
#endif |
#endif |
| 1117 |
// 68k emulator inactive, in nanokernel? |
// 68k emulator inactive, in nanokernel? |
| 1118 |
assert(current_cpu == main_cpu); |
assert(current_cpu == main_cpu); |
| 1119 |
if (gpr(1) != KernelDataAddr) { |
if (gpr(1) != KernelDataAddr) { |
| 1120 |
|
interrupt_context ctx(this, "PowerPC mode"); |
| 1121 |
|
|
| 1122 |
// Prepare for 68k interrupt level 1 |
// Prepare for 68k interrupt level 1 |
| 1123 |
WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1); |
WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1); |
| 1124 |
WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc, |
WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc, |
| 1141 |
case MODE_EMUL_OP: |
case MODE_EMUL_OP: |
| 1142 |
// 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0 |
// 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0 |
| 1143 |
if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) { |
if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) { |
| 1144 |
|
interrupt_context ctx(this, "68k mode"); |
| 1145 |
#if 1 |
#if 1 |
| 1146 |
// Execute full 68k interrupt routine |
// Execute full 68k interrupt routine |
| 1147 |
M68kRegisters r; |
M68kRegisters r; |