--- SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp 2003/11/10 16:23:58 1.17 +++ SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp 2004/01/12 15:37:24 1.25 @@ -1,7 +1,7 @@ /* * sheepshaver_glue.cpp - Glue Kheperix CPU to SheepShaver CPU engine interface * - * SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig + * SheepShaver (C) 1997-2004 Christian Bauer and Marc Hellwig * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,8 @@ #include "sigsegv.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" @@ -71,6 +73,12 @@ 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 (ASYNC_IRQ ? 1 : 0) @@ -92,11 +100,22 @@ static KernelData * const kernel_data = // 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 **/ +enum { + PPC_I(SHEEP) = PPC_I(MAX), + PPC_I(SHEEP_MAX) +}; + class sheepshaver_cpu : public powerpc_cpu { @@ -108,12 +127,11 @@ public: // 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 entry, bool enable_cache = false); + 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); @@ -147,7 +165,7 @@ public: lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator; sheepshaver_cpu::sheepshaver_cpu() - : powerpc_cpu() + : powerpc_cpu(enable_jit_p()) { init_decoder(); } @@ -165,6 +183,7 @@ void sheepshaver_cpu::init_decoder() { "sheep", (execute_pmf)&sheepshaver_cpu::execute_sheep, NULL, + PPC_I(SHEEP), D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP } }; @@ -224,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++) @@ -237,12 +260,6 @@ void sheepshaver_cpu::execute_sheep(uint } } -// Execution loop -void sheepshaver_cpu::execute(uint32 entry, bool enable_cache) -{ - powerpc_cpu::execute(entry, enable_cache); -} - // Handle MacOS interrupt void sheepshaver_cpu::interrupt(uint32 entry) { @@ -260,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)); @@ -282,8 +299,8 @@ 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(10) = trampoline.addr(); + gpr(12) = trampoline.addr(); gpr(13) = get_cr(); // rlwimi. r7,r7,8,0,0 @@ -420,8 +437,8 @@ uint32 sheepshaver_cpu::execute_macos_co 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 @@ -465,8 +482,9 @@ inline void sheepshaver_cpu::execute_ppc // Save branch registers uint32 saved_lr = lr(); - const uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) }; - lr() = (uint32)trampoline; + SheepVar32 trampoline = POWERPC_EXEC_RETURN; + WriteMacInt32(trampoline.addr(), POWERPC_EXEC_RETURN); + lr() = trampoline.addr(); execute(entry); @@ -611,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 @@ -675,11 +694,11 @@ void exit_emul_ppc(void) void emul_ppc(uint32 entry) { current_cpu = main_cpu; -#if DEBUG +#if 0 current_cpu->start_log(); #endif // start emulation loop and enable code translation or caching - current_cpu->execute(entry, true); + current_cpu->execute(entry); } /* @@ -774,7 +793,7 @@ void sheepshaver_cpu::handle_interrupt(v if (InterruptFlags & INTFLAG_VIA) { ClearInterruptFlag(INTFLAG_VIA); ADBInterrupt(); - ExecutePPC(VideoVBL); + ExecuteNative(NATIVE_VIDEO_VBL); } } #endif @@ -784,43 +803,6 @@ void sheepshaver_cpu::handle_interrupt(v } } -/* - * 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), - POWERPC_NATIVE_OP_INIT(1, NATIVE_MAKE_EXECUTABLE), -}; - static void get_resource(void); static void get_1_resource(void); static void get_ind_resource(void); @@ -935,20 +917,6 @@ static void NativeOp(int selector) } /* - * 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); -} - -/* * Execute 68k subroutine (must be ended with EXEC_RETURN) * This must only be called by the emul_thread when in EMUL_OP mode * r->a[7] is unused, the routine runs on the caller's stack @@ -966,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); } /*