mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-25 17:29:19 +00:00
Fix native Linux/ppc with recent enough glibc that supports TLS; r2 is used
in that case. Tell me if I broke other arches, e.g. r13 is no longer saved in Video and Ethernet stubs, though it seems to be OK. Colateral feature: SheepShaver should now run on Linux/ppc64 with relevant 32-bit runtime. Native Linux/ppc64 support is harder as low mem globals are 32-bit in mind and e.g. the TLS register there is %r13, %r2 is the TOC (PowerOpen/AIX ABI)
This commit is contained in:
parent
f29eb7dd1d
commit
663facbf97
@ -36,6 +36,7 @@
|
|||||||
#ifdef __POWERPC__
|
#ifdef __POWERPC__
|
||||||
#define EMULATED_PPC 0
|
#define EMULATED_PPC 0
|
||||||
#define WORDS_BIGENDIAN 1
|
#define WORDS_BIGENDIAN 1
|
||||||
|
#define SYSTEM_CLOBBERS_R2 1
|
||||||
#else
|
#else
|
||||||
#define EMULATED_PPC 1
|
#define EMULATED_PPC 1
|
||||||
#undef WORDS_BIGENDIAN
|
#undef WORDS_BIGENDIAN
|
||||||
|
@ -42,7 +42,9 @@ const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack
|
|||||||
|
|
||||||
// Prototypes
|
// Prototypes
|
||||||
extern "C" void *get_sp(void);
|
extern "C" void *get_sp(void);
|
||||||
extern "C" void set_r2(uint32 val);
|
extern "C" void *get_r2(void);
|
||||||
|
extern "C" void set_r2(void *);
|
||||||
|
extern "C" void *get_r13(void);
|
||||||
extern void paranoia_check(void);
|
extern void paranoia_check(void);
|
||||||
static void sigusr2_handler(int sig, sigcontext_struct *sc);
|
static void sigusr2_handler(int sig, sigcontext_struct *sc);
|
||||||
|
|
||||||
@ -57,6 +59,12 @@ static void *sig_sc_regs = NULL;
|
|||||||
static uint32 sig_r2 = 0;
|
static uint32 sig_r2 = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int raise(int sig)
|
||||||
|
{
|
||||||
|
// Reimplement to get rid of access to r2 (TLS pointer)
|
||||||
|
return kill(getpid(), sig);
|
||||||
|
}
|
||||||
|
|
||||||
void paranoia_check(void)
|
void paranoia_check(void)
|
||||||
{
|
{
|
||||||
char str[256];
|
char str[256];
|
||||||
@ -95,8 +103,14 @@ void paranoia_check(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Raise SIGUSR2
|
// Raise SIGUSR2
|
||||||
set_r2(0xaffebad5);
|
TOC = get_r2();
|
||||||
|
R13 = get_r13();
|
||||||
|
set_r2((void *)0xaffebad5);
|
||||||
raise(SIGUSR2);
|
raise(SIGUSR2);
|
||||||
|
if (TOC != get_r2())
|
||||||
|
err = 6;
|
||||||
|
if (R13 != get_r13())
|
||||||
|
err = 7;
|
||||||
|
|
||||||
// Check error code
|
// Check error code
|
||||||
switch (err) {
|
switch (err) {
|
||||||
@ -115,6 +129,11 @@ void paranoia_check(void)
|
|||||||
case 5:
|
case 5:
|
||||||
printf("FATAL: sc->regs->gpr[2] in signal handler (%08lx) doesn't have expected value (%08x)\n", (uint32)sig_r2, 0xaffebad5);
|
printf("FATAL: sc->regs->gpr[2] in signal handler (%08lx) doesn't have expected value (%08x)\n", (uint32)sig_r2, 0xaffebad5);
|
||||||
break;
|
break;
|
||||||
|
case 6:
|
||||||
|
printf("FATAL: signal handler failed to restore initial r2 value (%08x, was %08x)\n", (uint32)get_r2(), (uint32)TOC);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
printf("FATAL: signal handler failed to restore initial r13 value (%08x, was %08x)\n", get_r13(), (uint32)R13);
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
printf("Maybe you need a different kernel?\n");
|
printf("Maybe you need a different kernel?\n");
|
||||||
@ -135,34 +154,40 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc)
|
|||||||
sig_sp = get_sp();
|
sig_sp = get_sp();
|
||||||
if (sig_sp < sig_stack || sig_sp >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
|
if (sig_sp < sig_stack || sig_sp >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
|
||||||
err = 1;
|
err = 1;
|
||||||
return;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether r4 points to info on the stack
|
// Check whether r4 points to info on the stack
|
||||||
sig_r4 = sc;
|
sig_r4 = sc;
|
||||||
if (sig_r4 < sig_stack || sig_r4 >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
|
if (sig_r4 < sig_stack || sig_r4 >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
|
||||||
err = 2;
|
err = 2;
|
||||||
return;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether r4 looks like a sigcontext
|
// Check whether r4 looks like a sigcontext
|
||||||
sig_sc_signal = sc->signal;
|
sig_sc_signal = sc->signal;
|
||||||
if (sig_sc_signal != SIGUSR2) {
|
if (sig_sc_signal != SIGUSR2) {
|
||||||
err = 3;
|
err = 3;
|
||||||
return;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether sc->regs points to info on the stack
|
// Check whether sc->regs points to info on the stack
|
||||||
sig_sc_regs = sc->regs;
|
sig_sc_regs = sc->regs;
|
||||||
if (sig_sc_regs < sig_stack || sig_sc_regs >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
|
if (sig_sc_regs < sig_stack || sig_sc_regs >= ((uint8 *)sig_stack + SIG_STACK_SIZE)) {
|
||||||
err = 4;
|
err = 4;
|
||||||
return;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether r2 still holds the value we set it to
|
// Check whether r2 still holds the value we set it to
|
||||||
sig_r2 = sc->regs->gpr[2];
|
sig_r2 = sc->regs->gpr[2];
|
||||||
if (sig_r2 != 0xaffebad5) {
|
if (sig_r2 != 0xaffebad5) {
|
||||||
err = 5;
|
err = 5;
|
||||||
return;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore pointer to Thread Local Storage
|
||||||
|
ret:
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R2
|
||||||
|
sc->regs->gpr[2] = (unsigned long)TOC;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,14 @@
|
|||||||
* is slightly different from the SysV ABI used by Linux:
|
* is slightly different from the SysV ABI used by Linux:
|
||||||
* - Stack frames are different (e.g. LR is stored in 8(r1) under
|
* - Stack frames are different (e.g. LR is stored in 8(r1) under
|
||||||
* MacOS, but in 4(r1) under Linux)
|
* MacOS, but in 4(r1) under Linux)
|
||||||
* - There is no TOC under Linux; r2 is free for the user
|
* - There is a pointer to Thread Local Storage (TLS) under Linux with
|
||||||
|
* recent enough glibc. This is r2 in 32-bit mode and r13 in
|
||||||
|
* 64-bit mode (PowerOpen/AIX ABI)
|
||||||
* - r13 is used as a small data pointer under Linux (but appearently
|
* - r13 is used as a small data pointer under Linux (but appearently
|
||||||
* it is not used this way? To be sure, we specify -msdata=none
|
* it is not used this way? To be sure, we specify -msdata=none
|
||||||
* in the Makefile)
|
* in the Makefile)
|
||||||
* - As there is no TOC, there are also no TVECTs under Linux;
|
* - There are no TVECTs under Linux; function pointers point
|
||||||
* function pointers point directly to the function code
|
* directly to the function code
|
||||||
* The Execute*() functions have to account for this. Additionally, we
|
* The Execute*() functions have to account for this. Additionally, we
|
||||||
* cannot simply call MacOS functions by getting their TVECT and jumping
|
* cannot simply call MacOS functions by getting their TVECT and jumping
|
||||||
* to it. Such calls are done via the call_macos*() functions in
|
* to it. Such calls are done via the call_macos*() functions in
|
||||||
@ -284,7 +286,8 @@ static inline void sig_stack_release(void)
|
|||||||
|
|
||||||
// Global variables (exported)
|
// Global variables (exported)
|
||||||
#if !EMULATED_PPC
|
#if !EMULATED_PPC
|
||||||
void *TOC; // Small data pointer (r13)
|
void *TOC; // Pointer to Thread Local Storage (r2)
|
||||||
|
void *R13; // Pointer to .sdata section (r13 under Linux)
|
||||||
#endif
|
#endif
|
||||||
uint32 RAMBase; // Base address of Mac RAM
|
uint32 RAMBase; // Base address of Mac RAM
|
||||||
uint32 RAMSize; // Size of Mac RAM
|
uint32 RAMSize; // Size of Mac RAM
|
||||||
@ -370,8 +373,11 @@ static void sigill_handler(int sig, siginfo_t *sip, void *scp);
|
|||||||
|
|
||||||
// From asm_linux.S
|
// From asm_linux.S
|
||||||
#if !EMULATED_PPC
|
#if !EMULATED_PPC
|
||||||
extern "C" void *get_toc(void);
|
|
||||||
extern "C" void *get_sp(void);
|
extern "C" void *get_sp(void);
|
||||||
|
extern "C" void *get_r2(void);
|
||||||
|
extern "C" void set_r2(void *);
|
||||||
|
extern "C" void *get_r13(void);
|
||||||
|
extern "C" void set_r13(void *);
|
||||||
extern "C" void flush_icache_range(uint32 start, uint32 end);
|
extern "C" void flush_icache_range(uint32 start, uint32 end);
|
||||||
extern "C" void jump_to_rom(uint32 entry, uint32 context);
|
extern "C" void jump_to_rom(uint32 entry, uint32 context);
|
||||||
extern "C" void quit_emulator(void);
|
extern "C" void quit_emulator(void);
|
||||||
@ -482,8 +488,14 @@ int main(int argc, char **argv)
|
|||||||
printf(" %s\n", GetString(STR_ABOUT_TEXT2));
|
printf(" %s\n", GetString(STR_ABOUT_TEXT2));
|
||||||
|
|
||||||
#if !EMULATED_PPC
|
#if !EMULATED_PPC
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R2
|
||||||
// Get TOC pointer
|
// Get TOC pointer
|
||||||
TOC = get_toc();
|
TOC = get_r2();
|
||||||
|
#endif
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R13
|
||||||
|
// Get r13 register
|
||||||
|
R13 = get_r13();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_GTK
|
#ifdef ENABLE_GTK
|
||||||
@ -1607,6 +1619,15 @@ static void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
|
|||||||
if (*(int32 *)XLM_IRQ_NEST > 0)
|
if (*(int32 *)XLM_IRQ_NEST > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R2
|
||||||
|
// Restore pointer to Thread Local Storage
|
||||||
|
set_r2(TOC);
|
||||||
|
#endif
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R13
|
||||||
|
// Restore pointer to .sdata section
|
||||||
|
set_r13(R13);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Disable MacOS stack sniffer
|
// Disable MacOS stack sniffer
|
||||||
WriteMacInt32(0x110, 0);
|
WriteMacInt32(0x110, 0);
|
||||||
|
|
||||||
@ -1697,6 +1718,15 @@ static void sigsegv_handler(int sig, siginfo_t *sip, void *scp)
|
|||||||
// Get effective address
|
// Get effective address
|
||||||
uint32 addr = r->dar();
|
uint32 addr = r->dar();
|
||||||
|
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R2
|
||||||
|
// Restore pointer to Thread Local Storage
|
||||||
|
set_r2(TOC);
|
||||||
|
#endif
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R13
|
||||||
|
// Restore pointer to .sdata section
|
||||||
|
set_r13(R13);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_VOSF
|
#if ENABLE_VOSF
|
||||||
// Handle screen fault.
|
// Handle screen fault.
|
||||||
extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
|
extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
|
||||||
@ -1946,6 +1976,15 @@ static void sigill_handler(int sig, siginfo_t *sip, void *scp)
|
|||||||
machine_regs *r = MACHINE_REGISTERS(scp);
|
machine_regs *r = MACHINE_REGISTERS(scp);
|
||||||
char str[256];
|
char str[256];
|
||||||
|
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R2
|
||||||
|
// Restore pointer to Thread Local Storage
|
||||||
|
set_r2(TOC);
|
||||||
|
#endif
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R13
|
||||||
|
// Restore pointer to .sdata section
|
||||||
|
set_r13(R13);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fault in Mac ROM or RAM?
|
// Fault in Mac ROM or RAM?
|
||||||
bool mac_fault = (r->pc() >= ROM_BASE) && (r->pc() < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize));
|
bool mac_fault = (r->pc() >= ROM_BASE) && (r->pc() < (ROM_BASE + ROM_AREA_SIZE)) || (r->pc() >= RAMBase) && (r->pc() < (RAMBase + RAMSize));
|
||||||
if (mac_fault) {
|
if (mac_fault) {
|
||||||
|
@ -24,16 +24,6 @@
|
|||||||
#define SAVE_FP_EXEC_68K 1
|
#define SAVE_FP_EXEC_68K 1
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* void *get_toc(void) - Get TOC pointer (small data pointer r13 under Linux)
|
|
||||||
*/
|
|
||||||
|
|
||||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_toc)
|
|
||||||
C_SYMBOL_NAME(get_toc):
|
|
||||||
mr r3,r13
|
|
||||||
blr
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void *get_sp(void) - Get stack pointer
|
* void *get_sp(void) - Get stack pointer
|
||||||
*/
|
*/
|
||||||
@ -45,7 +35,17 @@ C_SYMBOL_NAME(get_sp):
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void set_r2(uint32 val {r3}) - Set r2
|
* void *get_r2(void) - Get r2
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r2)
|
||||||
|
C_SYMBOL_NAME(get_r2):
|
||||||
|
mr r3,r2
|
||||||
|
blr
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void set_r2(void *val {r3}) - Set r2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r2)
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r2)
|
||||||
@ -54,6 +54,25 @@ C_SYMBOL_NAME(set_r2):
|
|||||||
blr
|
blr
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void *get_r13(void) - Get r13 (small data pointer under Linux)
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r13)
|
||||||
|
C_SYMBOL_NAME(get_r13):
|
||||||
|
mr r3,r13
|
||||||
|
blr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void set_r13(void *val {r3}) - Set r13 (small data pointer under Linux)
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r13)
|
||||||
|
C_SYMBOL_NAME(set_r13):
|
||||||
|
mr r13,r3
|
||||||
|
blr
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void flush_icache_range(void *start {r3}, void *end {r3}) - Flush D and I cache
|
* void flush_icache_range(void *start {r3}, void *end {r3}) - Flush D and I cache
|
||||||
*/
|
*/
|
||||||
@ -225,6 +244,7 @@ C_SYMBOL_NAME(jump_to_rom):
|
|||||||
|
|
||||||
// Restore PowerPC registers
|
// Restore PowerPC registers
|
||||||
lwz r1,XLM_EMUL_RETURN_STACK(0)
|
lwz r1,XLM_EMUL_RETURN_STACK(0)
|
||||||
|
RESTORE_SYSTEM_R2
|
||||||
lmw r13,20(r1)
|
lmw r13,20(r1)
|
||||||
lfd f14,20+19*4+0*8(r1)
|
lfd f14,20+19*4+0*8(r1)
|
||||||
lfd f15,20+19*4+1*8(r1)
|
lfd f15,20+19*4+1*8(r1)
|
||||||
@ -361,6 +381,7 @@ C_SYMBOL_NAME(jump_to_rom):
|
|||||||
stw r0,16(r1)
|
stw r0,16(r1)
|
||||||
stw r2,12(r1)
|
stw r2,12(r1)
|
||||||
stwu r1,-(24+16*4+15*8)(r1)
|
stwu r1,-(24+16*4+15*8)(r1)
|
||||||
|
RESTORE_SYSTEM_R2
|
||||||
|
|
||||||
// Save 68k registers (M68kRegisters)
|
// Save 68k registers (M68kRegisters)
|
||||||
stw r8,24+0*4(r1) // d[0]..d[7]
|
stw r8,24+0*4(r1) // d[0]..d[7]
|
||||||
@ -397,7 +418,8 @@ C_SYMBOL_NAME(jump_to_rom):
|
|||||||
stfd f0,24+16*4+14*8(r1)
|
stfd f0,24+16*4+14*8(r1)
|
||||||
|
|
||||||
// Execute native routine
|
// Execute native routine
|
||||||
lwz r13,XLM_TOC(0)
|
RESTORE_SYSTEM_R2
|
||||||
|
RESTORE_SYSTEM_R13
|
||||||
addi r3,r1,24
|
addi r3,r1,24
|
||||||
mr r4,r24
|
mr r4,r24
|
||||||
bl C_SYMBOL_NAME(EmulOp)
|
bl C_SYMBOL_NAME(EmulOp)
|
||||||
@ -573,7 +595,8 @@ ASM_MACRO_START prolog
|
|||||||
ASM_MACRO_END
|
ASM_MACRO_END
|
||||||
|
|
||||||
ASM_MACRO_START epilog
|
ASM_MACRO_START epilog
|
||||||
lwz r13,XLM_TOC(0)
|
RESTORE_SYSTEM_R2
|
||||||
|
RESTORE_SYSTEM_R13
|
||||||
lwz r0,64+4(r1)
|
lwz r0,64+4(r1)
|
||||||
mtlr r0
|
mtlr r0
|
||||||
addi r1,r1,64
|
addi r1,r1,64
|
||||||
@ -701,6 +724,7 @@ C_SYMBOL_NAME(get_resource):
|
|||||||
lwz r2,XLM_RES_LIB_TOC(0)
|
lwz r2,XLM_RES_LIB_TOC(0)
|
||||||
mtctr r0
|
mtctr r0
|
||||||
bctrl
|
bctrl
|
||||||
|
RESTORE_SYSTEM_R2
|
||||||
stw r3,56+8(r1) // Save handle
|
stw r3,56+8(r1) // Save handle
|
||||||
|
|
||||||
// Call CheckLoad
|
// Call CheckLoad
|
||||||
@ -732,6 +756,7 @@ C_SYMBOL_NAME(get_1_resource):
|
|||||||
lwz r2,XLM_RES_LIB_TOC(0)
|
lwz r2,XLM_RES_LIB_TOC(0)
|
||||||
mtctr r0
|
mtctr r0
|
||||||
bctrl
|
bctrl
|
||||||
|
RESTORE_SYSTEM_R2
|
||||||
stw r3,56+8(r1) // Save handle
|
stw r3,56+8(r1) // Save handle
|
||||||
|
|
||||||
// Call CheckLoad
|
// Call CheckLoad
|
||||||
@ -763,6 +788,7 @@ C_SYMBOL_NAME(get_ind_resource):
|
|||||||
lwz r2,XLM_RES_LIB_TOC(0)
|
lwz r2,XLM_RES_LIB_TOC(0)
|
||||||
mtctr r0
|
mtctr r0
|
||||||
bctrl
|
bctrl
|
||||||
|
RESTORE_SYSTEM_R2
|
||||||
stw r3,56+8(r1) // Save handle
|
stw r3,56+8(r1) // Save handle
|
||||||
|
|
||||||
// Call CheckLoad
|
// Call CheckLoad
|
||||||
@ -794,6 +820,7 @@ C_SYMBOL_NAME(get_1_ind_resource):
|
|||||||
lwz r2,XLM_RES_LIB_TOC(0)
|
lwz r2,XLM_RES_LIB_TOC(0)
|
||||||
mtctr r0
|
mtctr r0
|
||||||
bctrl
|
bctrl
|
||||||
|
RESTORE_SYSTEM_R2
|
||||||
stw r3,56+8(r1) // Save handle
|
stw r3,56+8(r1) // Save handle
|
||||||
|
|
||||||
// Call CheckLoad
|
// Call CheckLoad
|
||||||
@ -825,6 +852,7 @@ C_SYMBOL_NAME(r_get_resource):
|
|||||||
lwz r2,XLM_RES_LIB_TOC(0)
|
lwz r2,XLM_RES_LIB_TOC(0)
|
||||||
mtctr r0
|
mtctr r0
|
||||||
bctrl
|
bctrl
|
||||||
|
RESTORE_SYSTEM_R2
|
||||||
stw r3,56+8(r1) // Save handle
|
stw r3,56+8(r1) // Save handle
|
||||||
|
|
||||||
// Call CheckLoad
|
// Call CheckLoad
|
||||||
@ -888,3 +916,57 @@ C_SYMBOL_NAME(ppc_interrupt):
|
|||||||
// Enter nanokernel
|
// Enter nanokernel
|
||||||
mtlr r3
|
mtlr r3
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Glue for glibc with TLS support which clobbers r2
|
||||||
|
*
|
||||||
|
* The following is derived from dietlibc and only provides
|
||||||
|
* pass-through to kernel syscalls. You also lose asynchronous
|
||||||
|
* cancellation support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
#define __NR_getpid 20
|
||||||
|
#define __NR__newselect 142
|
||||||
|
|
||||||
|
#define syscall_weak(name,wsym,sym) \
|
||||||
|
.text; \
|
||||||
|
.type wsym,@function; \
|
||||||
|
.weak wsym; \
|
||||||
|
wsym: ; \
|
||||||
|
.type sym,@function; \
|
||||||
|
.global sym; \
|
||||||
|
sym: \
|
||||||
|
li 0,__NR_##name; \
|
||||||
|
b __unified_syscall
|
||||||
|
|
||||||
|
#define syscall(name,sym) \
|
||||||
|
.text; \
|
||||||
|
.type sym,@function; \
|
||||||
|
.global sym; \
|
||||||
|
sym: \
|
||||||
|
li 0,__NR_##name; \
|
||||||
|
b __unified_syscall
|
||||||
|
|
||||||
|
|
||||||
|
.type __unified_syscall,@function
|
||||||
|
__unified_syscall:
|
||||||
|
sc
|
||||||
|
bnslr+
|
||||||
|
stwu 1,-16(1)
|
||||||
|
mflr 0
|
||||||
|
stw 0,20(1)
|
||||||
|
stw 3,12(1)
|
||||||
|
bl __errno_location
|
||||||
|
lwz 0,12(1)
|
||||||
|
stw 0,0(3)
|
||||||
|
lwz 0,20(1)
|
||||||
|
mtlr 0
|
||||||
|
addi 1,1,16
|
||||||
|
blr
|
||||||
|
|
||||||
|
/* name weak symbol symbol */
|
||||||
|
syscall( getpid, getpid)
|
||||||
|
syscall_weak( _newselect, select, __select)
|
||||||
|
#endif
|
||||||
|
@ -1,3 +1,27 @@
|
|||||||
|
/* Define usage of "reserved" registers */
|
||||||
|
#if defined(__linux__)
|
||||||
|
#define SYSTEM_CLOBBERS_R2 1 /* Pointer to Thread Local Storage */
|
||||||
|
#define SYSTEM_CLOBBERS_R13 1 /* Pointer to .sdata section */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
|
/* Helper macros */
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R2
|
||||||
|
#define RESTORE_SYSTEM_R2 lwz r2,XLM_TOC(0)
|
||||||
|
#define SAVE_SYSTEM_R2 stw r2,XLM_TOC(0)
|
||||||
|
#else
|
||||||
|
#define RESTORE_SYSTEM_R2
|
||||||
|
#define SAVE_SYSTEM_R2
|
||||||
|
#endif
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R13
|
||||||
|
#define RESTORE_SYSTEM_R13 lwz r13,XLM_R13(0)
|
||||||
|
#define SAVE_SYSTEM_R13 stw r13,XLM_R13(0)
|
||||||
|
#else
|
||||||
|
#define RESTORE_SYSTEM_R13
|
||||||
|
#define SAVE_SYSTEM_R13
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Apple assembler perticularities */
|
||||||
#if (defined(__APPLE__) && defined(__MACH__))
|
#if (defined(__APPLE__) && defined(__MACH__))
|
||||||
#define C_SYMBOL_NAME(NAME) _ ## NAME
|
#define C_SYMBOL_NAME(NAME) _ ## NAME
|
||||||
#define ASM_MACRO_END .endmacro
|
#define ASM_MACRO_END .endmacro
|
||||||
@ -87,3 +111,4 @@
|
|||||||
#define f30 30
|
#define f30 30
|
||||||
#define f31 31
|
#define f31 31
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
@ -82,6 +82,7 @@
|
|||||||
// Otherwise, use Direct Addressing mode if NATMEM_OFFSET is set
|
// Otherwise, use Direct Addressing mode if NATMEM_OFFSET is set
|
||||||
#if !defined(EMULATED_PPC)
|
#if !defined(EMULATED_PPC)
|
||||||
#define REAL_ADDRESSING 1
|
#define REAL_ADDRESSING 1
|
||||||
|
#include "ppc_asm.tmpl"
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
#define DIRECT_ADDRESSING 1
|
#define DIRECT_ADDRESSING 1
|
||||||
#define DIRECT_ADDRESSING_HACK 1
|
#define DIRECT_ADDRESSING_HACK 1
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
extern void *TOC; // TOC pointer
|
extern void *TOC; // TOC pointer
|
||||||
|
extern void *R13; // r13 register
|
||||||
extern uint32 KernelDataAddr; // Address of Kernel Data
|
extern uint32 KernelDataAddr; // Address of Kernel Data
|
||||||
extern uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
|
extern uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM
|
||||||
extern uint32 PVR; // Theoretical PVR
|
extern uint32 PVR; // Theoretical PVR
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#define XLM_R_GET_RESOURCE 0x2848 // Pointer to native RGetResource() routine
|
#define XLM_R_GET_RESOURCE 0x2848 // Pointer to native RGetResource() routine
|
||||||
#define XLM_EXEC_RETURN_OPCODE 0x284c // EXEC_RETURN opcode for Execute68k()
|
#define XLM_EXEC_RETURN_OPCODE 0x284c // EXEC_RETURN opcode for Execute68k()
|
||||||
#define XLM_ZERO_PAGE 0x2850 // Pointer to read-only page with all bits set to 0
|
#define XLM_ZERO_PAGE 0x2850 // Pointer to read-only page with all bits set to 0
|
||||||
|
#define XLM_R13 0x2854 // Pointer to .sdata section (Linux)
|
||||||
|
|
||||||
#define XLM_ETHER_INIT 0x28c0 // Pointer to ethernet InitStreamModule() function
|
#define XLM_ETHER_INIT 0x28c0 // Pointer to ethernet InitStreamModule() function
|
||||||
#define XLM_ETHER_TERM 0x28c4 // Pointer to ethernet TerminateStreamModule() function
|
#define XLM_ETHER_TERM 0x28c4 // Pointer to ethernet TerminateStreamModule() function
|
||||||
|
@ -232,7 +232,12 @@ bool InitAll(void)
|
|||||||
WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
|
WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN); // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
|
||||||
WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0
|
WriteMacInt32(XLM_ZERO_PAGE, SheepMem::ZeroPage()); // Pointer to read-only page with all bits set to 0
|
||||||
#if !EMULATED_PPC
|
#if !EMULATED_PPC
|
||||||
WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator
|
#ifdef SYSTEM_CLOBBERS_R2
|
||||||
|
WriteMacInt32(XLM_TOC, (uint32)TOC); // TOC pointer of emulator
|
||||||
|
#endif
|
||||||
|
#ifdef SYSTEM_CLOBBERS_R13
|
||||||
|
WriteMacInt32(XLM_R13, (uint32)R13); // TLS register
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT)); // DLPI ethernet driver functions
|
WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT)); // DLPI ethernet driver functions
|
||||||
WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM));
|
WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM));
|
||||||
|
Loading…
Reference in New Issue
Block a user