30 |
|
#include "sigsegv.h" |
31 |
|
#include "cpu/ppc/ppc-cpu.hpp" |
32 |
|
#include "cpu/ppc/ppc-operations.hpp" |
33 |
+ |
#include "cpu/ppc/ppc-instructions.hpp" |
34 |
|
|
35 |
|
// Used for NativeOp trampolines |
36 |
|
#include "video.h" |
90 |
|
// Pointer to Kernel Data |
91 |
|
static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE; |
92 |
|
|
93 |
+ |
// SIGSEGV handler |
94 |
+ |
static sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t); |
95 |
+ |
|
96 |
+ |
// JIT Compiler enabled? |
97 |
+ |
static inline bool enable_jit_p() |
98 |
+ |
{ |
99 |
+ |
return PrefsFindBool("jit"); |
100 |
+ |
} |
101 |
+ |
|
102 |
|
|
103 |
|
/** |
104 |
|
* PowerPC emulator glue with special 'sheep' opcodes |
105 |
|
**/ |
106 |
|
|
107 |
+ |
enum { |
108 |
+ |
PPC_I(SHEEP) = PPC_I(MAX), |
109 |
+ |
PPC_I(SHEEP_MAX) |
110 |
+ |
}; |
111 |
+ |
|
112 |
|
class sheepshaver_cpu |
113 |
|
: public powerpc_cpu |
114 |
|
{ |
124 |
|
uint32 get_cr() const { return cr().get(); } |
125 |
|
void set_cr(uint32 v) { cr().set(v); } |
126 |
|
|
112 |
– |
// Execution loop |
113 |
– |
void execute(uint32 entry, bool enable_cache = false); |
114 |
– |
|
127 |
|
// Execute 68k routine |
128 |
|
void execute_68k(uint32 entry, M68kRegisters *r); |
129 |
|
|
148 |
|
// FIXME: really make surre array allocation fail at link time? |
149 |
|
void *operator new[](size_t); |
150 |
|
void operator delete[](void *p); |
151 |
+ |
|
152 |
+ |
// Make sure the SIGSEGV handler can access CPU registers |
153 |
+ |
friend sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t); |
154 |
|
}; |
155 |
|
|
156 |
|
lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator; |
157 |
|
|
158 |
|
sheepshaver_cpu::sheepshaver_cpu() |
159 |
< |
: powerpc_cpu() |
159 |
> |
: powerpc_cpu(enable_jit_p()) |
160 |
|
{ |
161 |
|
init_decoder(); |
162 |
|
} |
174 |
|
{ "sheep", |
175 |
|
(execute_pmf)&sheepshaver_cpu::execute_sheep, |
176 |
|
NULL, |
177 |
+ |
PPC_I(SHEEP), |
178 |
|
D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP |
179 |
|
} |
180 |
|
}; |
247 |
|
} |
248 |
|
} |
249 |
|
|
234 |
– |
// Execution loop |
235 |
– |
void sheepshaver_cpu::execute(uint32 entry, bool enable_cache) |
236 |
– |
{ |
237 |
– |
powerpc_cpu::execute(entry, enable_cache); |
238 |
– |
} |
239 |
– |
|
250 |
|
// Handle MacOS interrupt |
251 |
|
void sheepshaver_cpu::interrupt(uint32 entry) |
252 |
|
{ |
564 |
|
if ((addr - ROM_BASE) < ROM_SIZE) |
565 |
|
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
566 |
|
|
567 |
< |
// Ignore all other faults, if requested |
568 |
< |
if (PrefsFindBool("ignoresegv")) |
569 |
< |
return SIGSEGV_RETURN_FAILURE; |
567 |
> |
// Get program counter of target CPU |
568 |
> |
sheepshaver_cpu * const cpu = current_cpu; |
569 |
> |
const uint32 pc = cpu->pc(); |
570 |
> |
|
571 |
> |
// Fault in Mac ROM or RAM? |
572 |
> |
bool mac_fault = (pc >= ROM_BASE) && (pc < (ROM_BASE + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize)); |
573 |
> |
if (mac_fault) { |
574 |
> |
|
575 |
> |
// "VM settings" during MacOS 8 installation |
576 |
> |
if (pc == ROM_BASE + 0x488160 && cpu->gpr(20) == 0xf8000000) |
577 |
> |
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
578 |
> |
|
579 |
> |
// MacOS 8.5 installation |
580 |
> |
else if (pc == ROM_BASE + 0x488140 && cpu->gpr(16) == 0xf8000000) |
581 |
> |
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
582 |
> |
|
583 |
> |
// MacOS 8 serial drivers on startup |
584 |
> |
else if (pc == ROM_BASE + 0x48e080 && (cpu->gpr(8) == 0xf3012002 || cpu->gpr(8) == 0xf3012000)) |
585 |
> |
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
586 |
> |
|
587 |
> |
// MacOS 8.1 serial drivers on startup |
588 |
> |
else if (pc == ROM_BASE + 0x48c5e0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000)) |
589 |
> |
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
590 |
> |
else if (pc == ROM_BASE + 0x4a10a0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000)) |
591 |
> |
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
592 |
> |
|
593 |
> |
// Ignore all other faults, if requested |
594 |
> |
if (PrefsFindBool("ignoresegv")) |
595 |
> |
return SIGSEGV_RETURN_SKIP_INSTRUCTION; |
596 |
> |
} |
597 |
|
#else |
598 |
|
#error "FIXME: You don't have the capability to skip instruction within signal handlers" |
599 |
|
#endif |
683 |
|
current_cpu->start_log(); |
684 |
|
#endif |
685 |
|
// start emulation loop and enable code translation or caching |
686 |
< |
current_cpu->execute(entry, true); |
686 |
> |
current_cpu->execute(entry); |
687 |
|
} |
688 |
|
|
689 |
|
/* |