From b8b139faf263a3bb935259cd47b27539bcd08a13 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Mon, 29 Sep 2003 15:46:09 +0000 Subject: [PATCH] - Share EmulatorData & KernelData struct definitions - Introduce new SheepShaver data area for alternate stacks, thunks, etc. - Experimental asynchronous interrupts handling. This improves performance by 30% but some (rare) lockups may occur. To be debugged! --- SheepShaver/src/BeOS/main_beos.cpp | 19 ------ SheepShaver/src/Unix/main_unix.cpp | 71 +++++++++++--------- SheepShaver/src/Unix/sysdeps.h | 2 + SheepShaver/src/Unix/user_strings_unix.cpp | 1 + SheepShaver/src/Unix/user_strings_unix.h | 1 + SheepShaver/src/include/cpu_emulation.h | 22 ++++++ SheepShaver/src/include/main.h | 3 + SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp | 45 +++++-------- 8 files changed, 83 insertions(+), 81 deletions(-) diff --git a/SheepShaver/src/BeOS/main_beos.cpp b/SheepShaver/src/BeOS/main_beos.cpp index 7abc6c03..2b17c6dd 100644 --- a/SheepShaver/src/BeOS/main_beos.cpp +++ b/SheepShaver/src/BeOS/main_beos.cpp @@ -117,30 +117,11 @@ const char RAM_AREA_NAME[] = "Macintosh RAM"; const char ROM_AREA_NAME[] = "Macintosh ROM"; const char DR_CACHE_AREA_NAME[] = "Macintosh DR Cache"; -const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area - -const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data -const uint32 KERNEL_DATA2_BASE = 0x5fffe000;// Alternate address of Kernel Data -const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area - const uint32 SIG_STACK_SIZE = 8192; // Size of signal stack const uint32 MSG_START = 'strt'; // Emulator start message -// Emulator Data -struct EmulatorData { - uint32 v[0x400]; -}; - - -// Kernel Data -struct KernelData { - uint32 v[0x400]; - EmulatorData ed; -}; - - // Application object class SheepShaver : public BApplication { public: diff --git a/SheepShaver/src/Unix/main_unix.cpp b/SheepShaver/src/Unix/main_unix.cpp index 446c5c40..7ff5e2bf 100644 --- a/SheepShaver/src/Unix/main_unix.cpp +++ b/SheepShaver/src/Unix/main_unix.cpp @@ -145,29 +145,10 @@ const char ROM_FILE_NAME[] = "ROM"; const char ROM_FILE_NAME2[] = "Mac OS ROM"; -const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area -const uint32 ROM_END = ROM_BASE + ROM_SIZE; // End of ROM - -const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data -const uint32 KERNEL_DATA2_BASE = 0x5fffe000; // Alternate address of Kernel Data -const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area - +const uint32 RAM_BASE = 0x20000000; // Base address of RAM const uint32 SIG_STACK_SIZE = 0x10000; // Size of signal stack -// 68k Emulator Data -struct EmulatorData { - uint32 v[0x400]; -}; - - -// Kernel Data -struct KernelData { - uint32 v[0x400]; - EmulatorData ed; -}; - - #if !EMULATED_PPC // Structure in which registers are saved in a signal handler; // sigcontext->regs points to it @@ -191,6 +172,9 @@ void *TOC; // Small data pointer (r13) #endif uint32 RAMBase; // Base address of Mac RAM uint32 RAMSize; // Size of Mac RAM +uint32 SheepStack1Base; // SheepShaver first alternate stack base +uint32 SheepStack2Base; // SheepShaver second alternate stack base +uint32 SheepThunksBase; // SheepShaver thunks base uint32 KernelDataAddr; // Address of Kernel Data uint32 BootGlobsAddr; // Address of BootGlobs structure at top of Mac RAM uint32 PVR; // Theoretical PVR @@ -203,11 +187,11 @@ static char *x_display_name = NULL; // X11 display name Display *x_display = NULL; // X11 display handle static int zero_fd = 0; // FD of /dev/zero +static bool sheep_area_mapped = false; // Flag: SheepShaver data area mmap()ed static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped static int kernel_area = -1; // SHM ID of Kernel Data area static bool rom_area_mapped = false; // Flag: Mac ROM mmap()ped static bool ram_area_mapped = false; // Flag: Mac RAM mmap()ped -static void *mmap_RAMBase = NULL; // Base address of mmap()ed RAM area static KernelData *kernel_data; // Pointer to Kernel Data static EmulatorData *emulator_data; @@ -238,7 +222,9 @@ static void Quit(void); static void *emul_func(void *arg); static void *nvram_func(void *arg); static void *tick_func(void *arg); -#if !EMULATED_PPC +#if EMULATED_PPC +static void sigusr2_handler(int sig); +#else static void sigusr2_handler(int sig, sigcontext_struct *sc); static void sigsegv_handler(int sig, sigcontext_struct *sc); static void sigill_handler(int sig, sigcontext_struct *sc); @@ -293,7 +279,6 @@ int main(int argc, char **argv) // Initialize variables RAMBase = 0; - mmap_RAMBase = NULL; tzset(); // Print some info @@ -451,6 +436,17 @@ int main(int argc, char **argv) KernelDataAddr = (uint32)kernel_data; D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data)); + // Create area for SheepShaver data + if (vm_acquire_fixed((char *)SHEEP_BASE, SHEEP_SIZE) < 0) { + sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno)); + ErrorAlert(str); + goto quit; + } + SheepStack1Base = SHEEP_BASE + 0x10000; + SheepStack2Base = SheepStack1Base + 0x10000; + SheepThunksBase = SheepStack2Base + 0x1000; + sheep_area_mapped = true; + // Create area for Mac ROM if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) { sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); @@ -474,20 +470,19 @@ int main(int argc, char **argv) RAMSize = 8*1024*1024; } - mmap_RAMBase = (void *)0x20000000; - if (vm_acquire_fixed(mmap_RAMBase, RAMSize) < 0) { + if (vm_acquire_fixed((char *)RAM_BASE, RAMSize) < 0) { sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } #if !EMULATED_PPC - if (vm_protect(mmap_RAMBase, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { + if (vm_protect((char *)RAM_BASE, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } #endif - RAMBase = (uint32)mmap_RAMBase; + RAMBase = RAM_BASE; ram_area_mapped = true; D(bug("RAM area at %08x\n", RAMBase)); @@ -717,18 +712,19 @@ int main(int argc, char **argv) } #endif -#if !EMULATED_PPC // Install interrupt signal handler sigemptyset(&sigusr2_action.sa_mask); sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler; + sigusr2_action.sa_flags = 0; +#if !EMULATED_PPC sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART; +#endif sigusr2_action.sa_restorer = NULL; if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) { sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno)); ErrorAlert(str); goto quit; } -#endif // Get my thread ID and execute MacOS thread function emul_thread = pthread_self(); @@ -805,7 +801,7 @@ static void Quit(void) // Delete RAM area if (ram_area_mapped) - vm_release(mmap_RAMBase, RAMSize); + vm_release((char *)RAM_BASE, RAMSize); // Delete ROM area if (rom_area_mapped) @@ -1199,7 +1195,7 @@ void B2_delete_mutex(B2_mutex *mutex) * Trigger signal USR2 from another thread */ -#if !EMULATED_PPC +#if !EMULATED_PPC || ASYNC_IRQ void TriggerInterrupt(void) { if (ready_for_signals) @@ -1245,11 +1241,19 @@ void EnableInterrupt(void) } -#if !EMULATED_PPC /* * USR2 handler */ +#if EMULATED_PPC +static void sigusr2_handler(int sig) +{ +#if ASYNC_IRQ + extern void HandleInterrupt(void); + HandleInterrupt(); +#endif +} +#else static void sigusr2_handler(int sig, sigcontext_struct *sc) { pt_regs *r = sc->regs; @@ -1331,15 +1335,16 @@ static void sigusr2_handler(int sig, sigcontext_struct *sc) } break; #endif - } } +#endif /* * SIGSEGV handler */ +#if !EMULATED_PPC static void sigsegv_handler(int sig, sigcontext_struct *sc) { pt_regs *r = sc->regs; diff --git a/SheepShaver/src/Unix/sysdeps.h b/SheepShaver/src/Unix/sysdeps.h index f1f8e0c6..3ee48f95 100644 --- a/SheepShaver/src/Unix/sysdeps.h +++ b/SheepShaver/src/Unix/sysdeps.h @@ -68,6 +68,8 @@ #define POWERPC_ROM 1 #if EMULATED_PPC +// Handle interrupts asynchronously? +#define ASYNC_IRQ 0 // Mac ROM is write protected when banked memory is used #if REAL_ADDRESSING || DIRECT_ADDRESSING # define ROM_IS_WRITE_PROTECTED 0 diff --git a/SheepShaver/src/Unix/user_strings_unix.cpp b/SheepShaver/src/Unix/user_strings_unix.cpp index 660b4847..3cd508a5 100644 --- a/SheepShaver/src/Unix/user_strings_unix.cpp +++ b/SheepShaver/src/Unix/user_strings_unix.cpp @@ -38,6 +38,7 @@ user_string_def platform_strings[] = { {STR_KD2_SHMAT_ERR, "Cannot map second Kernel Data area: %s."}, {STR_ROM_MMAP_ERR, "Cannot map ROM: %s."}, {STR_RAM_MMAP_ERR, "Cannot map RAM: %s."}, + {STR_SHEEP_MEM_MMAP_ERR, "Cannot map SheepShaver Data area: %s."}, {STR_SIGALTSTACK_ERR, "Cannot install alternate signal stack (%s). It seems that you need a newer kernel."}, {STR_SIGSEGV_INSTALL_ERR, "Cannot install SIGSEGV handler: %s."}, {STR_SIGILL_INSTALL_ERR, "Cannot install SIGILL handler: %s."}, diff --git a/SheepShaver/src/Unix/user_strings_unix.h b/SheepShaver/src/Unix/user_strings_unix.h index 9e8d1864..afab987b 100644 --- a/SheepShaver/src/Unix/user_strings_unix.h +++ b/SheepShaver/src/Unix/user_strings_unix.h @@ -29,6 +29,7 @@ enum { STR_KD2_SHMAT_ERR, STR_ROM_MMAP_ERR, STR_RAM_MMAP_ERR, + STR_SHEEP_MEM_MMAP_ERR, STR_SIGALTSTACK_ERR, STR_SIGSEGV_INSTALL_ERR, STR_SIGILL_INSTALL_ERR, diff --git a/SheepShaver/src/include/cpu_emulation.h b/SheepShaver/src/include/cpu_emulation.h index c3233152..ce9a4939 100644 --- a/SheepShaver/src/include/cpu_emulation.h +++ b/SheepShaver/src/include/cpu_emulation.h @@ -29,12 +29,34 @@ // Constants const uint32 ROM_BASE = 0x40800000; // Base address of ROM const uint32 ROM_SIZE = 0x00400000; // Size of ROM file +const uint32 ROM_AREA_SIZE = 0x500000; // Size of ROM area +const uint32 ROM_END = ROM_BASE + ROM_SIZE; // End of ROM const uint32 DR_CACHE_BASE = 0x69000000; // Address of DR cache const uint32 DR_CACHE_SIZE = 0x80000; // Size of DR Cache +const uint32 SHEEP_BASE = 0x60000000; // Address of SheepShaver data +const uint32 SHEEP_SIZE = 0x40000; // Size of SheepShaver data + +const uint32 KERNEL_DATA_BASE = 0x68ffe000; // Address of Kernel Data +const uint32 KERNEL_DATA2_BASE = 0x5fffe000;// Alternate address of Kernel Data +const uint32 KERNEL_AREA_SIZE = 0x2000; // Size of Kernel Data area + +// MacOS 68k Emulator Data +struct EmulatorData { + uint32 v[0x400]; +}; + +// MacOS Kernel Data +struct KernelData { + uint32 v[0x400]; + EmulatorData ed; +}; // RAM and ROM pointers (allocated and set by main_*.cpp) extern uint32 RAMBase; // Base address of Mac RAM extern uint32 RAMSize; // Size address of Mac RAM +extern uint32 SheepStack1Base; // SheepShaver first alternate stack base +extern uint32 SheepStack2Base; // SheepShaver second alternate stack base +extern uint32 SheepThunksBase; // SheepShaver thunks base // Mac memory access functions static inline uint32 ReadMacInt8(uint32 addr) {return *(uint8 *)addr;} diff --git a/SheepShaver/src/include/main.h b/SheepShaver/src/include/main.h index 4a595524..4c325dc0 100644 --- a/SheepShaver/src/include/main.h +++ b/SheepShaver/src/include/main.h @@ -69,6 +69,9 @@ enum { extern volatile uint32 InterruptFlags; // Currently pending interrupts extern void SetInterruptFlag(uint32); extern void ClearInterruptFlag(uint32); +#if EMULATED_PPC +extern void HandleInterrupt(void); // Handle SIGUSR1 interrupt in emulator thread +#endif extern void TriggerInterrupt(void); // Trigger SIGUSR1 interrupt in emulator thread extern void DisableInterrupt(void); // Disable SIGUSR1 interrupt (can be nested) extern void EnableInterrupt(void); // Enable SIGUSR1 interrupt (can be nested) diff --git a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp index 8df0e48a..e04c2997 100644 --- a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp +++ b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp @@ -71,19 +71,8 @@ static void enter_mon(void) // Interrupts in native mode? #define INTERRUPTS_IN_NATIVE_MODE 1 -// 68k Emulator Data -struct EmulatorData { - uint32 v[0x400]; -}; - -// Kernel Data -struct KernelData { - uint32 v[0x400]; - EmulatorData ed; -}; - // Pointer to Kernel Data -static KernelData * const kernel_data = (KernelData *)0x68ffe000; +static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE; /** @@ -124,7 +113,7 @@ public: void get_resource(uint32 old_get_resource); // Handle MacOS interrupt - void interrupt(uint32 entry, sheepshaver_cpu *cpu); + void interrupt(uint32 entry); // spcflags for interrupts handling static uint32 spcflags; @@ -232,10 +221,9 @@ struct execute_nothing { static inline void execute(powerpc_cpu *) { } }; -static void HandleInterrupt(void); - struct execute_spcflags_check { static inline void execute(powerpc_cpu *cpu) { +#if !ASYNC_IRQ if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { if (SPCFLAGS_TEST( SPCFLAG_ENTER_MON )) { SPCFLAGS_CLEAR( SPCFLAG_ENTER_MON ); @@ -250,6 +238,7 @@ struct execute_spcflags_check { SPCFLAGS_SET( SPCFLAG_DOINT ); } } +#endif } }; @@ -270,20 +259,18 @@ void sheepshaver_cpu::execute(uint32 entry) } // Handle MacOS interrupt -void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu) +void sheepshaver_cpu::interrupt(uint32 entry) { -#if MULTICORE_CPU - // Initialize stack pointer from previous CPU running - gpr(1) = cpu->gpr(1); -#else +#if !MULTICORE_CPU // Save program counters and branch registers uint32 saved_pc = pc(); uint32 saved_lr = lr(); uint32 saved_ctr= ctr(); + uint32 saved_sp = gpr(1); #endif - // Create stack frame - gpr(1) -= 64; + // Initialize stack pointer to SheepShaver alternate stack base + gpr(1) = SheepStack1Base - 64; // Build trampoline to return from interrupt uint32 trampoline[] = { POWERPC_EMUL_OP | 1 }; @@ -320,14 +307,12 @@ void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu) // Enter nanokernel execute(entry); - // Cleanup stack - gpr(1) += 64; - #if !MULTICORE_CPU // Restore program counters and branch registers pc() = saved_pc; lr() = saved_lr; ctr()= saved_ctr; + gpr(1) = saved_sp; #endif } @@ -585,7 +570,7 @@ void init_emul_ppc(void) // Install the handler for SIGSEGV sigsegv_install_handler(sigsegv_handler); - + #if ENABLE_MON // Install "regs" command in cxmon mon_add_command("regs", dump_registers, "regs Dump PowerPC registers\n"); @@ -613,6 +598,7 @@ extern int atomic_add(int *var, int v); extern int atomic_and(int *var, int v); extern int atomic_or(int *var, int v); +#if !ASYNC_IRQ void TriggerInterrupt(void) { #if 0 @@ -621,8 +607,9 @@ void TriggerInterrupt(void) SPCFLAGS_SET( SPCFLAG_INT ); #endif } +#endif -static void HandleInterrupt(void) +void HandleInterrupt(void) { // Do nothing if interrupts are disabled if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0) @@ -659,9 +646,9 @@ static void HandleInterrupt(void) DisableInterrupt(); cpu_push(interrupt_cpu); if (ROMType == ROMTYPE_NEWWORLD) - current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu); + current_cpu->interrupt(ROM_BASE + 0x312b1c); else - current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu); + current_cpu->interrupt(ROM_BASE + 0x312a3c); cpu_pop(); } break;