--- SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp 2003/09/29 22:50:31 1.5 +++ SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp 2003/12/25 23:54:36 1.24 @@ -28,14 +28,16 @@ #include "macos_util.h" #include "block-alloc.hpp" #include "sigsegv.h" -#include "spcflags.h" #include "cpu/ppc/ppc-cpu.hpp" #include "cpu/ppc/ppc-operations.hpp" +#include "cpu/ppc/ppc-instructions.hpp" +#include "thunks.h" // Used for NativeOp trampolines #include "video.h" #include "name_registry.h" #include "serial.h" +#include "ether.h" #include @@ -44,9 +46,24 @@ #include "mon_disass.h" #endif -#define DEBUG 1 +#define DEBUG 0 #include "debug.h" +// Emulation time statistics +#define EMUL_TIME_STATS 1 + +#if EMUL_TIME_STATS +static clock_t emul_start_time; +static uint32 interrupt_count = 0; +static clock_t interrupt_time = 0; +static uint32 exec68k_count = 0; +static clock_t exec68k_time = 0; +static uint32 native_exec_count = 0; +static clock_t native_exec_time = 0; +static uint32 macos_exec_count = 0; +static clock_t macos_exec_time = 0; +#endif + static void enter_mon(void) { // Start up mon in real-mode @@ -56,8 +73,14 @@ static void enter_mon(void) #endif } +// From main_*.cpp +extern uintptr SignalStackBase(); + +// PowerPC EmulOp to exit from emulation looop +const uint32 POWERPC_EXEC_RETURN = POWERPC_EMUL_OP | 1; + // Enable multicore (main/interrupts) cpu emulation? -#define MULTICORE_CPU 0 +#define MULTICORE_CPU (ASYNC_IRQ ? 1 : 0) // Enable Execute68k() safety checks? #define SAFE_EXEC_68K 1 @@ -74,12 +97,24 @@ static void enter_mon(void) // Pointer to Kernel Data static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE; +// SIGSEGV handler +static sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t); + +// JIT Compiler enabled? +static inline bool enable_jit_p() +{ + return PrefsFindBool("jit"); +} + /** * PowerPC emulator glue with special 'sheep' opcodes **/ -struct sheepshaver_exec_return { }; +enum { + PPC_I(SHEEP) = PPC_I(MAX), + PPC_I(SHEEP_MAX) +}; class sheepshaver_cpu : public powerpc_cpu @@ -89,16 +124,14 @@ class sheepshaver_cpu public: - sheepshaver_cpu() - : powerpc_cpu() - { init_decoder(); } + // Constructor + sheepshaver_cpu(); - // Condition Register accessors + // CR & XER accessors uint32 get_cr() const { return cr().get(); } void set_cr(uint32 v) { cr().set(v); } - - // Execution loop - void execute(uint32 pc); + uint32 get_xer() const { return xer().get(); } + void set_xer(uint32 v) { xer().set(v); } // Execute 68k routine void execute_68k(uint32 entry, M68kRegisters *r); @@ -114,9 +147,7 @@ public: // Handle MacOS interrupt void interrupt(uint32 entry); - - // spcflags for interrupts handling - static uint32 spcflags; + void handle_interrupt(); // Lazy memory allocator (one item at a time) void *operator new(size_t size) @@ -126,11 +157,19 @@ public: // FIXME: really make surre array allocation fail at link time? void *operator new[](size_t); void operator delete[](void *p); + + // Make sure the SIGSEGV handler can access CPU registers + friend sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t); }; -uint32 sheepshaver_cpu::spcflags = 0; lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator; +sheepshaver_cpu::sheepshaver_cpu() + : powerpc_cpu(enable_jit_p()) +{ + init_decoder(); +} + void sheepshaver_cpu::init_decoder() { #ifndef PPC_NO_STATIC_II_INDEX_TABLE @@ -142,9 +181,10 @@ void sheepshaver_cpu::init_decoder() static const instr_info_t sheep_ii_table[] = { { "sheep", - (execute_fn)&sheepshaver_cpu::execute_sheep, + (execute_pmf)&sheepshaver_cpu::execute_sheep, NULL, - D_form, 6, 0, CFLOW_TRAP + PPC_I(SHEEP), + D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP } }; @@ -181,9 +221,9 @@ void sheepshaver_cpu::execute_sheep(uint case 0: // EMUL_RETURN QuitEmulator(); break; - + case 1: // EXEC_RETURN - throw sheepshaver_exec_return(); + spcflags().set(SPCFLAG_CPU_EXEC_RETURN); break; case 2: // EXEC_NATIVE @@ -203,7 +243,11 @@ void sheepshaver_cpu::execute_sheep(uint for (int i = 0; i < 7; i++) r68.a[i] = gpr(16 + i); r68.a[7] = gpr(1); + uint32 saved_cr = get_cr() & CR_field<2>::mask(); + uint32 saved_xer = get_xer(); EmulOp(&r68, gpr(24), EMUL_OP_field::extract(opcode) - 3); + set_cr(saved_cr); + set_xer(saved_xer); for (int i = 0; i < 8; i++) gpr(8 + i) = r68.d[i]; for (int i = 0; i < 7; i++) @@ -216,51 +260,14 @@ void sheepshaver_cpu::execute_sheep(uint } } -// Checks for pending interrupts -struct execute_nothing { - static inline void execute(powerpc_cpu *) { } -}; - -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 ); - enter_mon(); - } - if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { - SPCFLAGS_CLEAR( SPCFLAG_DOINT ); - HandleInterrupt(); - } - if (SPCFLAGS_TEST( SPCFLAG_INT )) { - SPCFLAGS_CLEAR( SPCFLAG_INT ); - SPCFLAGS_SET( SPCFLAG_DOINT ); - } - } -#endif - } -}; - -// Execution loop -void sheepshaver_cpu::execute(uint32 entry) -{ - try { - pc() = entry; - powerpc_cpu::do_execute(); - } - catch (sheepshaver_exec_return const &) { - // Nothing, simply return - } - catch (...) { - printf("ERROR: execute() received an unknown exception!\n"); - QuitEmulator(); - } -} - // Handle MacOS interrupt void sheepshaver_cpu::interrupt(uint32 entry) { +#if EMUL_TIME_STATS + interrupt_count++; + const clock_t interrupt_start = clock(); +#endif + #if !MULTICORE_CPU // Save program counters and branch registers uint32 saved_pc = pc(); @@ -270,10 +277,10 @@ void sheepshaver_cpu::interrupt(uint32 e #endif // Initialize stack pointer to SheepShaver alternate stack base - gpr(1) = SheepStack1Base - 64; + gpr(1) = SignalStackBase() - 64; // Build trampoline to return from interrupt - uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) }; + SheepVar32 trampoline = POWERPC_EXEC_RETURN; // Prepare registers for nanokernel interrupt routine kernel_data->v[0x004 >> 2] = htonl(gpr(1)); @@ -292,9 +299,9 @@ void sheepshaver_cpu::interrupt(uint32 e gpr(1) = KernelDataAddr; gpr(7) = ntohl(kernel_data->v[0x660 >> 2]); gpr(8) = 0; - gpr(10) = (uint32)trampoline; - gpr(12) = (uint32)trampoline; - gpr(13) = cr().get(); + gpr(10) = trampoline.addr(); + gpr(12) = trampoline.addr(); + gpr(13) = get_cr(); // rlwimi. r7,r7,8,0,0 uint32 result = op_ppc_rlwimi::apply(gpr(7), 8, 0x80000000, gpr(7)); @@ -302,7 +309,7 @@ void sheepshaver_cpu::interrupt(uint32 e gpr(7) = result; gpr(11) = 0xf072; // MSR (SRR1) - cr().set((gpr(11) & 0x0fff0000) | (cr().get() & ~0x0fff0000)); + cr().set((gpr(11) & 0x0fff0000) | (get_cr() & ~0x0fff0000)); // Enter nanokernel execute(entry); @@ -314,11 +321,20 @@ void sheepshaver_cpu::interrupt(uint32 e ctr()= saved_ctr; gpr(1) = saved_sp; #endif + +#if EMUL_TIME_STATS + interrupt_time += (clock() - interrupt_start); +#endif } // Execute 68k routine void sheepshaver_cpu::execute_68k(uint32 entry, M68kRegisters *r) { +#if EMUL_TIME_STATS + exec68k_count++; + const clock_t exec68k_start = clock(); +#endif + #if SAFE_EXEC_68K if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP) printf("FATAL: Execute68k() not called from EMUL_OP mode\n"); @@ -328,17 +344,20 @@ void sheepshaver_cpu::execute_68k(uint32 uint32 saved_pc = pc(); uint32 saved_lr = lr(); uint32 saved_ctr= ctr(); + uint32 saved_cr = get_cr(); // Create MacOS stack frame + // FIXME: make sure MacOS doesn't expect PPC registers to live on top uint32 sp = gpr(1); - gpr(1) -= 56 + 19*4 + 18*8; + gpr(1) -= 56; WriteMacInt32(gpr(1), sp); // Save PowerPC registers - for (int i = 13; i < 32; i++) - WriteMacInt32(gpr(1) + 56 + i*4, gpr(i)); + uint32 saved_GPRs[19]; + memcpy(&saved_GPRs[0], &gpr(13), sizeof(uint32)*(32-13)); #if SAVE_FP_EXEC_68K - memcpy(Mac2HostAddr(gpr(1)+56+19*4), &fpr(14), sizeof(double)*(32-14)); + double saved_FPRs[18]; + memcpy(&saved_FPRs[0], &fpr(14), sizeof(double)*(32-14)); #endif // Setup registers for 68k emulator @@ -385,32 +404,41 @@ void sheepshaver_cpu::execute_68k(uint32 r->a[i] = gpr(16 + i); // Restore PowerPC registers - for (int i = 13; i < 32; i++) - gpr(i) = ReadMacInt32(gpr(1) + 56 + i*4); + memcpy(&gpr(13), &saved_GPRs[0], sizeof(uint32)*(32-13)); #if SAVE_FP_EXEC_68K - memcpy(&fpr(14), Mac2HostAddr(gpr(1)+56+19*4), sizeof(double)*(32-14)); + memcpy(&fpr(14), &saved_FPRs[0], sizeof(double)*(32-14)); #endif // Cleanup stack - gpr(1) += 56 + 19*4 + 18*8; + gpr(1) += 56; // Restore program counters and branch registers pc() = saved_pc; lr() = saved_lr; ctr()= saved_ctr; + set_cr(saved_cr); + +#if EMUL_TIME_STATS + exec68k_time += (clock() - exec68k_start); +#endif } // Call MacOS PPC code uint32 sheepshaver_cpu::execute_macos_code(uint32 tvect, int nargs, uint32 const *args) { +#if EMUL_TIME_STATS + macos_exec_count++; + const clock_t macos_exec_start = clock(); +#endif + // Save program counters and branch registers uint32 saved_pc = pc(); uint32 saved_lr = lr(); uint32 saved_ctr= ctr(); // Build trampoline with EXEC_RETURN - uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) }; - lr() = (uint32)trampoline; + SheepVar32 trampoline = POWERPC_EXEC_RETURN; + lr() = trampoline.addr(); gpr(1) -= 64; // Create stack frame uint32 proc = ReadMacInt32(tvect); // Get routine address @@ -441,6 +469,10 @@ uint32 sheepshaver_cpu::execute_macos_co lr() = saved_lr; ctr()= saved_ctr; +#if EMUL_TIME_STATS + macos_exec_time += (clock() - macos_exec_start); +#endif + return retval; } @@ -449,17 +481,15 @@ inline void sheepshaver_cpu::execute_ppc { // Save branch registers uint32 saved_lr = lr(); - uint32 saved_ctr= ctr(); - const uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) }; + SheepVar32 trampoline = POWERPC_EXEC_RETURN; + WriteMacInt32(trampoline.addr(), POWERPC_EXEC_RETURN); + lr() = trampoline.addr(); - lr() = (uint32)trampoline; - ctr()= entry; execute(entry); // Restore branch registers lr() = saved_lr; - ctr()= saved_ctr; } // Resource Manager thunk @@ -494,6 +524,15 @@ static sheepshaver_cpu *main_cpu = NULL; static sheepshaver_cpu *interrupt_cpu = NULL; // CPU emulator to handle interrupts static sheepshaver_cpu *current_cpu = NULL; // Current CPU emulator context +void FlushCodeCache(uintptr start, uintptr end) +{ + D(bug("FlushCodeCache(%08x, %08x)\n", start, end)); + main_cpu->invalidate_cache_range(start, end); +#if MULTICORE_CPU + interrupt_cpu->invalidate_cache_range(start, end); +#endif +} + static inline void cpu_push(sheepshaver_cpu *new_cpu) { #if MULTICORE_CPU @@ -539,9 +578,36 @@ static sigsegv_return_t sigsegv_handler( if ((addr - ROM_BASE) < ROM_SIZE) return SIGSEGV_RETURN_SKIP_INSTRUCTION; - // Ignore all other faults, if requested - if (PrefsFindBool("ignoresegv")) - return SIGSEGV_RETURN_FAILURE; + // Get program counter of target CPU + sheepshaver_cpu * const cpu = current_cpu; + const uint32 pc = cpu->pc(); + + // Fault in Mac ROM or RAM? + bool mac_fault = (pc >= ROM_BASE) && (pc < (ROM_BASE + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize)); + if (mac_fault) { + + // "VM settings" during MacOS 8 installation + if (pc == ROM_BASE + 0x488160 && cpu->gpr(20) == 0xf8000000) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; + + // MacOS 8.5 installation + else if (pc == ROM_BASE + 0x488140 && cpu->gpr(16) == 0xf8000000) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; + + // MacOS 8 serial drivers on startup + else if (pc == ROM_BASE + 0x48e080 && (cpu->gpr(8) == 0xf3012002 || cpu->gpr(8) == 0xf3012000)) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; + + // MacOS 8.1 serial drivers on startup + else if (pc == ROM_BASE + 0x48c5e0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000)) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; + else if (pc == ROM_BASE + 0x4a10a0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000)) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; + + // Ignore all other faults, if requested + if (PrefsFindBool("ignoresegv")) + return SIGSEGV_RETURN_SKIP_INSTRUCTION; + } #else #error "FIXME: You don't have the capability to skip instruction within signal handlers" #endif @@ -563,6 +629,7 @@ void init_emul_ppc(void) // Initialize main CPU emulator main_cpu = new sheepshaver_cpu(); main_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROM_BASE + 0x30d000)); + main_cpu->set_register(powerpc_registers::GPR(4), any_register(KernelDataAddr + 0x1000)); WriteMacInt32(XLM_RUN_MODE, MODE_68K); #if MULTICORE_CPU @@ -578,6 +645,46 @@ void init_emul_ppc(void) mon_add_command("regs", dump_registers, "regs Dump PowerPC registers\n"); mon_add_command("log", dump_log, "log Dump PowerPC emulation log\n"); #endif + +#if EMUL_TIME_STATS + emul_start_time = clock(); +#endif +} + +/* + * Deinitialize emulation + */ + +void exit_emul_ppc(void) +{ +#if EMUL_TIME_STATS + clock_t emul_end_time = clock(); + + printf("### Statistics for SheepShaver emulation parts\n"); + const clock_t emul_time = emul_end_time - emul_start_time; + printf("Total emulation time : %.1f sec\n", double(emul_time) / double(CLOCKS_PER_SEC)); + printf("Total interrupt count: %d (%2.1f Hz)\n", interrupt_count, + (double(interrupt_count) * CLOCKS_PER_SEC) / double(emul_time)); + +#define PRINT_STATS(LABEL, VAR_PREFIX) do { \ + printf("Total " LABEL " count : %d\n", VAR_PREFIX##_count); \ + printf("Total " LABEL " time : %.1f sec (%.1f%%)\n", \ + double(VAR_PREFIX##_time) / double(CLOCKS_PER_SEC), \ + 100.0 * double(VAR_PREFIX##_time) / double(emul_time)); \ + } while (0) + + PRINT_STATS("Execute68k[Trap] execution", exec68k); + PRINT_STATS("NativeOp execution", native_exec); + PRINT_STATS("MacOS routine execution", macos_exec); + +#undef PRINT_STATS + printf("\n"); +#endif + + delete main_cpu; +#if MULTICORE_CPU + delete interrupt_cpu; +#endif } /* @@ -587,7 +694,10 @@ void init_emul_ppc(void) void emul_ppc(uint32 entry) { current_cpu = main_cpu; +#if 0 current_cpu->start_log(); +#endif + // start emulation loop and enable code translation or caching current_cpu->execute(entry); } @@ -595,26 +705,28 @@ void emul_ppc(uint32 entry) * Handle PowerPC interrupt */ -// Atomic operations -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 +#if ASYNC_IRQ +void HandleInterrupt(void) +{ + main_cpu->handle_interrupt(); +} +#else void TriggerInterrupt(void) { #if 0 WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); #else - SPCFLAGS_SET( SPCFLAG_INT ); + // Trigger interrupt to main cpu only + if (main_cpu) + main_cpu->trigger_interrupt(); #endif } #endif -void HandleInterrupt(void) +void sheepshaver_cpu::handle_interrupt(void) { // Do nothing if interrupts are disabled - if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0) + if (*(int32 *)XLM_IRQ_NEST > 0) return; // Do nothing if there is no interrupt pending @@ -630,14 +742,14 @@ void HandleInterrupt(void) // 68k emulator active, trigger 68k interrupt level 1 assert(current_cpu == main_cpu); WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1); - main_cpu->set_cr(main_cpu->get_cr() | tswap32(kernel_data->v[0x674 >> 2])); + set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2])); break; #if INTERRUPTS_IN_NATIVE_MODE case MODE_NATIVE: // 68k emulator inactive, in nanokernel? assert(current_cpu == main_cpu); - if (main_cpu->gpr(1) != KernelDataAddr) { + if (gpr(1) != KernelDataAddr) { // Prepare for 68k interrupt level 1 WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1); WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc, @@ -681,7 +793,7 @@ void HandleInterrupt(void) if (InterruptFlags & INTFLAG_VIA) { ClearInterruptFlag(INTFLAG_VIA); ADBInterrupt(); - ExecutePPC(VideoVBL); + ExecuteNative(NATIVE_VIDEO_VBL); } } #endif @@ -691,42 +803,6 @@ void HandleInterrupt(void) } } -/* - * Execute NATIVE_OP opcode (called by PowerPC emulator) - */ - -#define POWERPC_NATIVE_OP_INIT(LR, OP) \ - tswap32(POWERPC_EMUL_OP | ((LR) << 11) | (((uint32)OP) << 6) | 2) - -// FIXME: Make sure 32-bit relocations are used -const uint32 NativeOpTable[NATIVE_OP_MAX] = { - POWERPC_NATIVE_OP_INIT(1, NATIVE_PATCH_NAME_REGISTRY), - POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_INSTALL_ACCEL), - POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_VBL), - POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_DO_DRIVER_IO), - POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_IRQ), - POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_INIT), - POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_TERM), - POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_OPEN), - POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_CLOSE), - POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_WPUT), - POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_RSRV), - POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_NOTHING), - POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_OPEN), - POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_PRIME_IN), - POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_PRIME_OUT), - POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_CONTROL), - POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_STATUS), - POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_CLOSE), - POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_RESOURCE), - POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_1_RESOURCE), - POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_IND_RESOURCE), - POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_1_IND_RESOURCE), - POWERPC_NATIVE_OP_INIT(1, NATIVE_R_GET_RESOURCE), - POWERPC_NATIVE_OP_INIT(0, NATIVE_DISABLE_INTERRUPT), - POWERPC_NATIVE_OP_INIT(0, NATIVE_ENABLE_INTERRUPT), -}; - static void get_resource(void); static void get_1_resource(void); static void get_ind_resource(void); @@ -737,6 +813,11 @@ static void r_get_resource(void); static void NativeOp(int selector) { +#if EMUL_TIME_STATS + native_exec_count++; + const clock_t native_exec_start = clock(); +#endif + switch (selector) { case NATIVE_PATCH_NAME_REGISTRY: DoPatchNameRegistry(); @@ -751,21 +832,34 @@ static void NativeOp(int selector) GPR(3) = (int32)(int16)VideoDoDriverIO((void *)GPR(3), (void *)GPR(4), (void *)GPR(5), GPR(6), GPR(7)); break; - case NATIVE_GET_RESOURCE: - get_resource(); +#ifdef WORDS_BIGENDIAN + case NATIVE_ETHER_IRQ: + EtherIRQ(); break; - case NATIVE_GET_1_RESOURCE: - get_1_resource(); + case NATIVE_ETHER_INIT: + GPR(3) = InitStreamModule((void *)GPR(3)); break; - case NATIVE_GET_IND_RESOURCE: - get_ind_resource(); + case NATIVE_ETHER_TERM: + TerminateStreamModule(); break; - case NATIVE_GET_1_IND_RESOURCE: - get_1_ind_resource(); + case NATIVE_ETHER_OPEN: + GPR(3) = ether_open((queue_t *)GPR(3), (void *)GPR(4), GPR(5), GPR(6), (void*)GPR(7)); break; - case NATIVE_R_GET_RESOURCE: - r_get_resource(); + case NATIVE_ETHER_CLOSE: + GPR(3) = ether_close((queue_t *)GPR(3), GPR(4), (void *)GPR(5)); break; + case NATIVE_ETHER_WPUT: + GPR(3) = ether_wput((queue_t *)GPR(3), (mblk_t *)GPR(4)); + break; + case NATIVE_ETHER_RSRV: + GPR(3) = ether_rsrv((queue_t *)GPR(3)); + break; +#else + case NATIVE_ETHER_INIT: + // FIXME: needs more complicated thunks + GPR(3) = false; + break; +#endif case NATIVE_SERIAL_NOTHING: case NATIVE_SERIAL_OPEN: case NATIVE_SERIAL_PRIME_IN: @@ -786,31 +880,40 @@ static void NativeOp(int selector) GPR(3) = serial_callbacks[selector - NATIVE_SERIAL_NOTHING](GPR(3), GPR(4)); break; } + case NATIVE_GET_RESOURCE: + case NATIVE_GET_1_RESOURCE: + case NATIVE_GET_IND_RESOURCE: + case NATIVE_GET_1_IND_RESOURCE: + case NATIVE_R_GET_RESOURCE: { + typedef void (*GetResourceCallback)(void); + static const GetResourceCallback get_resource_callbacks[] = { + get_resource, + get_1_resource, + get_ind_resource, + get_1_ind_resource, + r_get_resource + }; + get_resource_callbacks[selector - NATIVE_GET_RESOURCE](); + break; + } case NATIVE_DISABLE_INTERRUPT: DisableInterrupt(); break; case NATIVE_ENABLE_INTERRUPT: EnableInterrupt(); break; + case NATIVE_MAKE_EXECUTABLE: + MakeExecutable(0, (void *)GPR(4), GPR(5)); + break; default: printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector); QuitEmulator(); break; } -} -/* - * Execute native subroutine (LR must contain return address) - */ - -void ExecuteNative(int selector) -{ - uint32 tvect[2]; - tvect[0] = tswap32(POWERPC_NATIVE_OP_FUNC(selector)); - tvect[1] = 0; // Fake TVECT - RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, tvect); - M68kRegisters r; - Execute68k((uint32)&desc, &r); +#if EMUL_TIME_STATS + native_exec_time += (clock() - native_exec_start); +#endif } /* @@ -831,10 +934,11 @@ void Execute68k(uint32 pc, M68kRegisters void Execute68kTrap(uint16 trap, M68kRegisters *r) { - uint16 proc[2]; - proc[0] = htons(trap); - proc[1] = htons(M68K_RTS); - Execute68k((uint32)proc, r); + SheepVar proc_var(4); + uint32 proc = proc_var.addr(); + WriteMacInt16(proc, trap); + WriteMacInt16(proc + 2, M68K_RTS); + Execute68k(proc, r); } /* @@ -889,31 +993,6 @@ uint32 call_macos7(uint32 tvect, uint32 } /* - * Atomic operations - */ - -int atomic_add(int *var, int v) -{ - int ret = *var; - *var += v; - return ret; -} - -int atomic_and(int *var, int v) -{ - int ret = *var; - *var &= v; - return ret; -} - -int atomic_or(int *var, int v) -{ - int ret = *var; - *var |= v; - return ret; -} - -/* * Resource Manager thunks */