From 727ef4a625b36a9abe57f199eadf0271164db887 Mon Sep 17 00:00:00 2001 From: magumagu Date: Wed, 23 Apr 2014 21:35:49 -0700 Subject: [PATCH] JIT: unify JitAsm for JIT64 and JIT64IL. Having a bunch of nearly identical code sitting around isn't a good idea, so fix that. JITIL had a couple of extra entry points into the JIT main loop, so adjust the code appropriately. Also fixes Issue 7186. --- Source/Core/Core/CMakeLists.txt | 1 - Source/Core/Core/Core.vcxproj | 4 +- Source/Core/Core/Core.vcxproj.filters | 8 +- Source/Core/Core/PowerPC/Jit64/JitAsm.cpp | 2 - Source/Core/Core/PowerPC/Jit64/JitAsm.h | 2 - Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp | 7 +- Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp | 17 +- Source/Core/Core/PowerPC/Jit64IL/JitIL.h | 4 +- Source/Core/Core/PowerPC/Jit64IL/JitILAsm.cpp | 233 ------------------ Source/Core/Core/PowerPC/Jit64IL/JitILAsm.h | 42 ---- Source/Core/Core/PowerPC/JitArm32/Jit.cpp | 34 ++- .../Core/PowerPC/JitArm32/JitArm_Branch.cpp | 3 +- Source/Core/Core/PowerPC/JitArm32/JitAsm.cpp | 12 - Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp | 3 +- Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp | 21 +- .../Core/Core/PowerPC/JitArmIL/JitILAsm.cpp | 12 - .../Core/PowerPC/JitCommon/JitAsmCommon.h | 2 - .../JitILCommon/JitILBase_SystemRegisters.cpp | 3 +- 18 files changed, 71 insertions(+), 339 deletions(-) delete mode 100644 Source/Core/Core/PowerPC/Jit64IL/JitILAsm.cpp delete mode 100644 Source/Core/Core/PowerPC/Jit64IL/JitILAsm.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 77ab02e230cd..62e7de44204e 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -180,7 +180,6 @@ if(_M_X86) set(SRCS ${SRCS} x64MemTools.cpp PowerPC/Jit64IL/IR_X86.cpp - PowerPC/Jit64IL/JitILAsm.cpp PowerPC/Jit64IL/JitIL.cpp PowerPC/Jit64IL/JitIL_Tables.cpp PowerPC/Jit64/Jit64_Tables.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 65593f40217d..784e7503bd6d 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -209,7 +209,6 @@ - @@ -399,7 +398,6 @@ - @@ -470,4 +468,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 3ca5e3f9704b..f25fbe6248b5 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -641,9 +641,6 @@ PowerPC\JitIL - - PowerPC\JitIL - PowerPC\Jit64 @@ -1191,9 +1188,6 @@ PowerPC\JitIL - - PowerPC\JitIL - PowerPC\Jit64 @@ -1211,4 +1205,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp b/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp index e690d089747b..2de7cc31e743 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitAsm.cpp @@ -28,8 +28,6 @@ static bool enableDebug = false; //RBX - Base pointer of memory //R15 - Pointer to array of block pointers -Jit64AsmRoutineManager asm_routines; - // PLAN: no more block numbers - crazy opcodes just contain offset within // dynarec buffer // At this offset - 4, there is an int specifying the block number. diff --git a/Source/Core/Core/PowerPC/Jit64/JitAsm.h b/Source/Core/Core/PowerPC/Jit64/JitAsm.h index f2475ee0360b..19679247ec57 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitAsm.h +++ b/Source/Core/Core/PowerPC/Jit64/JitAsm.h @@ -37,5 +37,3 @@ class Jit64AsmRoutineManager : public CommonAsmRoutines FreeCodeSpace(); } }; - -extern Jit64AsmRoutineManager asm_routines; diff --git a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp index 53d0323c71e6..830b787e706b 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp @@ -1636,7 +1636,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { Jit->ABI_CallFunction((void *)&PowerPC::OnIdleIL); Jit->MOV(32, M(&PC), Imm32(ibuild->GetImmValue( getOp2(I) ))); - Jit->JMP(((JitIL *)jit)->asm_routines.testExceptions, true); + Jit->WriteExceptionExit(); Jit->SetJumpTarget(cont); if (RI.IInfo[I - RI.FirstI] & 4) @@ -1691,7 +1691,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); Jit->ABI_CallFunction((void *)&CoreTiming::Idle); Jit->MOV(32, M(&PC), Imm32(InstLoc)); - Jit->JMP(((JitIL *)jit)->asm_routines.testExceptions, true); + Jit->WriteExceptionExit(); break; } case SystemCall: { @@ -1734,7 +1734,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { // from PC. Update PC with the latest value in case that happens. Jit->MOV(32, M(&PC), Imm32(InstLoc)); Jit->SUB(32, M(&CoreTiming::downcount), Jit->js.downcountAmount > 127 ? Imm32(Jit->js.downcountAmount) : Imm8(Jit->js.downcountAmount)); - Jit->JMP(Jit->asm_routines.fpException, true); + Jit->OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE)); + Jit->WriteExceptionExit(); Jit->SetJumpTarget(b1); break; } diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index b686cbc5141b..9348740134c0 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -13,7 +13,6 @@ #include "Core/PowerPC/Profiler.h" #include "Core/PowerPC/Jit64IL/JitIL.h" #include "Core/PowerPC/Jit64IL/JitIL_Tables.h" -#include "Core/PowerPC/Jit64IL/JitILAsm.h" using namespace Gen; using namespace PowerPC; @@ -426,12 +425,14 @@ void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg) void JitIL::WriteRfiExitDestInOpArg(const Gen::OpArg& arg) { MOV(32, M(&PC), arg); + MOV(32, M(&NPC), arg); Cleanup(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { ABI_CallFunction((void *)JitILProfiler::End); } + ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); - JMP(asm_routines.testExceptions, true); + JMP(asm_routines.dispatcher, true); } void JitIL::WriteExceptionExit() @@ -440,8 +441,11 @@ void JitIL::WriteExceptionExit() if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { ABI_CallFunction((void *)JitILProfiler::End); } + MOV(32, R(EAX), M(&PC)); + MOV(32, M(&NPC), R(EAX)); + ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); - JMP(asm_routines.testExceptions, true); + JMP(asm_routines.dispatcher, true); } void STACKALIGN JitIL::Run() @@ -567,8 +571,13 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc // This block uses FPU - needs to add FP exception bailout TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit FixupBranch b1 = J_CC(CC_NZ); + + // If a FPU exception occurs, the exception handler will read + // from PC. Update PC with the latest value in case that happens. MOV(32, M(&PC), Imm32(js.blockStart)); - JMP(asm_routines.fpException, true); + OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE)); + WriteExceptionExit(); + SetJumpTarget(b1); } diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h index 14dc5c69e80b..638dafd37e82 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h @@ -28,7 +28,7 @@ #include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PPCAnalyst.h" #include "Core/PowerPC/PPCTables.h" -#include "Core/PowerPC/Jit64IL/JitILAsm.h" +#include "Core/PowerPC/Jit64/JitAsm.h" #include "Core/PowerPC/JitCommon/Jit_Util.h" #include "Core/PowerPC/JitCommon/JitBackpatch.h" #include "Core/PowerPC/JitCommon/JitBase.h" @@ -50,7 +50,7 @@ class JitIL : public JitILBase, public EmuCodeBlock TrampolineCache trampolines; public: - JitILAsmRoutineManager asm_routines; + Jit64AsmRoutineManager asm_routines; JitIL() {} ~JitIL() {} diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitILAsm.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitILAsm.cpp deleted file mode 100644 index 030ffdc81783..000000000000 --- a/Source/Core/Core/PowerPC/Jit64IL/JitILAsm.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include "Common/CPUDetect.h" -#include "Common/MemoryUtil.h" - -#include "Core/PowerPC/Jit64IL/JitIL.h" -#include "Core/PowerPC/Jit64IL/JitILAsm.h" - -using namespace Gen; - -//static int temp32; // unused? - -//TODO - make an option -//#if _DEBUG -static bool enableDebug = false; -//#else -// bool enableDebug = false; -//#endif - -//static bool enableStatistics = false; // unused? - -//GLOBAL STATIC ALLOCATIONS x86 -//EAX - ubiquitous scratch register - EVERYBODY scratches this - -//GLOBAL STATIC ALLOCATIONS x64 -//EAX - ubiquitous scratch register - EVERYBODY scratches this -//RBX - Base pointer of memory -//R15 - Pointer to array of block pointers - -JitILAsmRoutineManager jitil_asm_routines; - -// PLAN: no more block numbers - crazy opcodes just contain offset within -// dynarec buffer -// At this offset - 4, there is an int specifying the block number. - -void JitILAsmRoutineManager::Generate() -{ - enterCode = AlignCode16(); - ABI_PushAllCalleeSavedRegsAndAdjustStack(); -#if _M_X86_64 - // Two statically allocated registers. - MOV(64, R(RBX), Imm64((u64)Memory::base)); - MOV(64, R(R15), Imm64((u64)jit->GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough -#endif -// INT3(); - - const u8 *outer_loop = GetCodePtr(); - ABI_CallFunction(reinterpret_cast(&CoreTiming::Advance)); - FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time - - dispatcher = GetCodePtr(); - //This is the place for CPUCompare! - - //The result of slice decrement should be in flags if somebody jumped here - FixupBranch bail = J_CC(CC_BE, true); - - if (Core::g_CoreStartupParameter.bEnableDebugging) - { - TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(PowerPC::CPU_STEPPING)); - FixupBranch notStepping = J_CC(CC_Z); - ABI_CallFunction(reinterpret_cast(&PowerPC::CheckBreakPoints)); - TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); - FixupBranch noBreakpoint = J_CC(CC_Z); - ABI_PopAllCalleeSavedRegsAndAdjustStack(); - RET(); - SetJumpTarget(noBreakpoint); - SetJumpTarget(notStepping); - } - - SetJumpTarget(skipToRealDispatch); - - dispatcherNoCheck = GetCodePtr(); - MOV(32, R(EAX), M(&PowerPC::ppcState.pc)); - dispatcherPcInEAX = GetCodePtr(); - - u32 mask = 0; - FixupBranch no_mem; - FixupBranch exit_mem; - FixupBranch exit_vmem; - if (Core::g_CoreStartupParameter.bWii) - mask = JIT_ICACHE_EXRAM_BIT; - if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.bTLBHack) - mask |= JIT_ICACHE_VMEM_BIT; - if (Core::g_CoreStartupParameter.bWii || Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.bTLBHack) - { - TEST(32, R(EAX), Imm32(mask)); - no_mem = J_CC(CC_NZ); - } - AND(32, R(EAX), Imm32(JIT_ICACHE_MASK)); -#if _M_X86_32 - MOV(32, R(EAX), MDisp(EAX, (u32)jit->GetBlockCache()->iCache)); -#else - MOV(64, R(RSI), Imm64((u64)jit->GetBlockCache()->iCache)); - MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0)); -#endif - if (Core::g_CoreStartupParameter.bWii || Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.bTLBHack) - { - exit_mem = J(); - SetJumpTarget(no_mem); - } - if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.bTLBHack) - { - TEST(32, R(EAX), Imm32(JIT_ICACHE_VMEM_BIT)); - FixupBranch no_vmem = J_CC(CC_Z); - AND(32, R(EAX), Imm32(JIT_ICACHE_MASK)); -#if _M_X86_32 - MOV(32, R(EAX), MDisp(EAX, (u32)jit->GetBlockCache()->iCacheVMEM)); -#else - MOV(64, R(RSI), Imm64((u64)jit->GetBlockCache()->iCacheVMEM)); - MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0)); -#endif - if (Core::g_CoreStartupParameter.bWii) exit_vmem = J(); - SetJumpTarget(no_vmem); - } - if (Core::g_CoreStartupParameter.bWii) - { - TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT)); - FixupBranch no_exram = J_CC(CC_Z); - AND(32, R(EAX), Imm32(JIT_ICACHEEX_MASK)); -#if _M_X86_32 - MOV(32, R(EAX), MDisp(EAX, (u32)jit->GetBlockCache()->iCacheEx)); -#else - MOV(64, R(RSI), Imm64((u64)jit->GetBlockCache()->iCacheEx)); - MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0)); -#endif - SetJumpTarget(no_exram); - } - if (Core::g_CoreStartupParameter.bWii || Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.bTLBHack) - SetJumpTarget(exit_mem); - if (Core::g_CoreStartupParameter.bWii && (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.bTLBHack)) - SetJumpTarget(exit_vmem); - - TEST(32, R(EAX), R(EAX)); - FixupBranch notfound = J_CC(CC_L); - //IDEA - we have 26 bits, why not just use offsets from base of code? - if (enableDebug) - { - ADD(32, M(&PowerPC::ppcState.DebugCount), Imm8(1)); - } - //grab from list and jump to it -#if _M_X86_32 - MOV(32, R(EDX), ImmPtr(jit->GetBlockCache()->GetCodePointers())); - JMPptr(MComplex(EDX, EAX, 4, 0)); -#else - JMPptr(MComplex(R15, RAX, 8, 0)); -#endif - SetJumpTarget(notfound); - - //Ok, no block, let's jit -#if _M_X86_32 - ABI_AlignStack(4); - PUSH(32, M(&PowerPC::ppcState.pc)); - CALL(reinterpret_cast(&Jit)); - ABI_RestoreStack(4); -#else - MOV(32, R(ABI_PARAM1), M(&PowerPC::ppcState.pc)); - CALL((void *)&Jit); -#endif - JMP(dispatcherNoCheck); // no point in special casing this - - //FP blocks test for FPU available, jump here if false - fpException = AlignCode4(); - MOV(32, R(EAX), M(&PC)); - MOV(32, M(&NPC), R(EAX)); - LOCK(); - OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE)); - ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); - MOV(32, R(EAX), M(&NPC)); - MOV(32, M(&PC), R(EAX)); - JMP(dispatcher, true); - - SetJumpTarget(bail); - doTiming = GetCodePtr(); - - ABI_CallFunction(reinterpret_cast(&CoreTiming::Advance)); - - testExceptions = GetCodePtr(); - MOV(32, R(EAX), M(&PC)); - MOV(32, M(&NPC), R(EAX)); - ABI_CallFunction(reinterpret_cast(&PowerPC::CheckExceptions)); - MOV(32, R(EAX), M(&NPC)); - MOV(32, M(&PC), R(EAX)); - - TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); - J_CC(CC_Z, outer_loop, true); - //Landing pad for drec space - ABI_PopAllCalleeSavedRegsAndAdjustStack(); - RET(); - - breakpointBailout = GetCodePtr(); - //Landing pad for drec space - ABI_PopAllCalleeSavedRegsAndAdjustStack(); - RET(); - - GenerateCommon(); -} - -void JitILAsmRoutineManager::GenerateCommon() -{ - fifoDirectWrite8 = AlignCode4(); - GenFifoWrite(8); - fifoDirectWrite16 = AlignCode4(); - GenFifoWrite(16); - fifoDirectWrite32 = AlignCode4(); - GenFifoWrite(32); - fifoDirectWriteFloat = AlignCode4(); - GenFifoFloatWrite(); - fifoDirectWriteXmm64 = AlignCode4(); - GenFifoXmm64Write(); - - GenQuantizedLoads(); - GenQuantizedStores(); - GenQuantizedSingleStores(); - - //CMPSD(R(XMM0), M(&zero), - // TODO - - // Fast write routines - special case the most common hardware write - // TODO: use this. - // Even in x86, the param values will be in the right registers. - /* - const u8 *fastMemWrite8 = AlignCode16(); - CMP(32, R(ABI_PARAM2), Imm32(0xCC008000)); - FixupBranch skip_fast_write = J_CC(CC_NE, false); - MOV(32, EAX, M(&m_gatherPipeCount)); - MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1); - ADD(32, 1, M(&m_gatherPipeCount)); - RET(); - SetJumpTarget(skip_fast_write); - CALL((void *)&Memory::Write_U8);*/ -} diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitILAsm.h b/Source/Core/Core/PowerPC/Jit64IL/JitILAsm.h deleted file mode 100644 index a465df88e2e9..000000000000 --- a/Source/Core/Core/PowerPC/Jit64IL/JitILAsm.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include "Common/x64Emitter.h" -#include "Core/PowerPC/JitCommon/JitAsmCommon.h" - -// In Dolphin, we don't use inline assembly. Instead, we generate all machine-near -// code at runtime. In the case of fixed code like this, after writing it, we write -// protect the memory, essentially making it work just like precompiled code. - -// There are some advantages to this approach: -// 1) No need to setup an external assembler in the build. -// 2) Cross platform, as long as it's x86/x64. -// 3) Can optimize code at runtime for the specific CPU model. -// There aren't really any disadvantages other than having to maintain a x86 emitter, -// which we have to do anyway :) -// -// To add a new asm routine, just add another const here, and add the code to Generate. -// Also, possibly increase the size of the code buffer. - -class JitILAsmRoutineManager : public CommonAsmRoutines -{ -private: - void Generate(); - void GenerateCommon(); - -public: - void Init() { - AllocCodeSpace(8192); - Generate(); - WriteProtect(); - } - - void Shutdown() { - FreeCodeSpace(); - } -}; - -extern JitILAsmRoutineManager jitil_asm_routines; diff --git a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp index c08e1809be89..fd5033a8248c 100644 --- a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp @@ -166,17 +166,32 @@ void JitArm::WriteRfiExitDestInR(ARMReg Reg) Cleanup(); DoDownCount(); - MOVI2R(Reg, (u32)asm_routines.testExceptions); - B(Reg); + ARMReg A = gpr.GetReg(false); + + LDR(A, R9, PPCSTATE_OFF(pc)); + STR(A, R9, PPCSTATE_OFF(npc)); + QuickCallFunction(A, (void*)&PowerPC::CheckExceptions); + LDR(A, R9, PPCSTATE_OFF(npc)); + STR(A, R9, PPCSTATE_OFF(pc)); gpr.Unlock(Reg); // This was locked in the instruction beforehand + + MOVI2R(A, (u32)asm_routines.dispatcher); + B(A); } void JitArm::WriteExceptionExit() { - ARMReg A = gpr.GetReg(false); Cleanup(); DoDownCount(); - MOVI2R(A, (u32)asm_routines.testExceptions); + ARMReg A = gpr.GetReg(false); + + LDR(A, R9, PPCSTATE_OFF(pc)); + STR(A, R9, PPCSTATE_OFF(npc)); + QuickCallFunction(A, (void*)&PowerPC::CheckExceptions); + LDR(A, R9, PPCSTATE_OFF(npc)); + STR(A, R9, PPCSTATE_OFF(pc)); + + MOVI2R(A, (u32)asm_routines.dispatcher); B(A); } void JitArm::WriteExit(u32 destination) @@ -372,8 +387,17 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo TST(A, Shift); SetCC(CC_EQ); STR(C, R9, PPCSTATE_OFF(pc)); - MOVI2R(A, (u32)asm_routines.fpException); + + LDR(A, R9, PPCSTATE_OFF(Exceptions)); + ORR(A, A, EXCEPTION_FPU_UNAVAILABLE); + STR(A, R9, PPCSTATE_OFF(Exceptions)); + QuickCallFunction(A, (void*)&PowerPC::CheckExceptions); + LDR(A, R9, PPCSTATE_OFF(npc)); + STR(A, R9, PPCSTATE_OFF(pc)); + + MOVI2R(A, (u32)asm_routines.dispatcher); B(A); + SetCC(); gpr.Unlock(A, C); } diff --git a/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp b/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp index b1b310b5ad31..3ff35e90a9f4 100644 --- a/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp @@ -138,8 +138,7 @@ void JitArm::bx(UGeckoInstruction inst) BL(R14); MOVI2R(R14, js.compilerPC); STR(R14, R9, PPCSTATE_OFF(pc)); - MOVI2R(R14, (u32)asm_routines.testExceptions); - B(R14); + WriteExceptionExit(); } WriteExit(destination); } diff --git a/Source/Core/Core/PowerPC/JitArm32/JitAsm.cpp b/Source/Core/Core/PowerPC/JitArm32/JitAsm.cpp index 8cec544b9d3d..fae765798e88 100644 --- a/Source/Core/Core/PowerPC/JitArm32/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/JitAsm.cpp @@ -141,17 +141,6 @@ void JitArmAsmRoutineManager::Generate() B(dispatcherNoCheck); - // fpException() - // Floating Point Exception Check, Jumped to if false - fpException = GetCodePtr(); - LDR(R0, R9, PPCSTATE_OFF(Exceptions)); - ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE); - STR(R0, R9, PPCSTATE_OFF(Exceptions)); - QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); - LDR(R0, R9, PPCSTATE_OFF(npc)); - STR(R0, R9, PPCSTATE_OFF(pc)); - B(dispatcher); - SetJumpTarget(bail); doTiming = GetCodePtr(); // XXX: In JIT64, Advance() gets called /after/ the exception checking @@ -159,7 +148,6 @@ void JitArmAsmRoutineManager::Generate() QuickCallFunction(R14, (void*)&CoreTiming::Advance); // Does exception checking - testExceptions = GetCodePtr(); LDR(R0, R9, PPCSTATE_OFF(pc)); STR(R0, R9, PPCSTATE_OFF(npc)); QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); diff --git a/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp b/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp index d85260d15a34..26d2616bdbd8 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp +++ b/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp @@ -604,8 +604,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) { Jit->BL(R14); Jit->MOVI2R(R14, InstLoc); Jit->STR(R14, R9, PPCSTATE_OFF(pc)); - Jit->MOVI2R(R14, (u32)Jit->GetAsmRoutines()->testExceptions); - Jit->B(R14); + Jit->WriteExceptionExit(); break; } case InterpreterBranch: { diff --git a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp index 2c5baf33bbf3..a6260e30fce7 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp @@ -111,15 +111,28 @@ void JitArmIL::WriteRfiExitDestInR(ARMReg Reg) { STR(Reg, R9, PPCSTATE_OFF(pc)); DoDownCount(); - MOVI2R(Reg, (u32)asm_routines.testExceptions); - B(Reg); + + LDR(R0, R9, PPCSTATE_OFF(pc)); + STR(R0, R9, PPCSTATE_OFF(npc)); + QuickCallFunction(R0, (void*)&PowerPC::CheckExceptions); + LDR(R0, R9, PPCSTATE_OFF(npc)); + STR(R0, R9, PPCSTATE_OFF(pc)); + + MOVI2R(R0, (u32)asm_routines.dispatcher); + B(R0); } void JitArmIL::WriteExceptionExit() { DoDownCount(); - MOVI2R(R14, (u32)asm_routines.testExceptions); - B(R14); + LDR(R0, R9, PPCSTATE_OFF(pc)); + STR(R0, R9, PPCSTATE_OFF(npc)); + QuickCallFunction(R0, (void*)&PowerPC::CheckExceptions); + LDR(R0, R9, PPCSTATE_OFF(npc)); + STR(R0, R9, PPCSTATE_OFF(pc)); + + MOVI2R(R0, (u32)asm_routines.dispatcher); + B(R0); } void JitArmIL::WriteExit(u32 destination) { diff --git a/Source/Core/Core/PowerPC/JitArmIL/JitILAsm.cpp b/Source/Core/Core/PowerPC/JitArmIL/JitILAsm.cpp index 72f76ec001fc..56e2ce1d67e9 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/JitILAsm.cpp +++ b/Source/Core/Core/PowerPC/JitArmIL/JitILAsm.cpp @@ -73,17 +73,6 @@ void JitArmILAsmRoutineManager::Generate() B(dispatcherNoCheck); - // fpException() - // Floating Point Exception Check, Jumped to if false - fpException = GetCodePtr(); - LDR(R0, R9, PPCSTATE_OFF(Exceptions)); - ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE); - STR(R0, R9, PPCSTATE_OFF(Exceptions)); - QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); - LDR(R0, R9, PPCSTATE_OFF(npc)); - STR(R0, R9, PPCSTATE_OFF(pc)); - B(dispatcher); - SetJumpTarget(bail); doTiming = GetCodePtr(); // XXX: In JIT64, Advance() gets called /after/ the exception checking @@ -91,7 +80,6 @@ void JitArmILAsmRoutineManager::Generate() QuickCallFunction(R14, (void*)&CoreTiming::Advance); // Does exception checking - testExceptions = GetCodePtr(); LDR(R0, R9, PPCSTATE_OFF(pc)); STR(R0, R9, PPCSTATE_OFF(npc)); QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitAsmCommon.h b/Source/Core/Core/PowerPC/JitCommon/JitAsmCommon.h index 5d6e92a0784f..72a8675a446e 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitAsmCommon.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitAsmCommon.h @@ -23,8 +23,6 @@ class CommonAsmRoutinesBase const u8 *dispatcherNoCheck; const u8 *dispatcherPcInEAX; - const u8 *fpException; - const u8 *testExceptions; const u8 *testExternalExceptions; const u8 *dispatchPcInEAX; const u8 *doTiming; diff --git a/Source/Core/Core/PowerPC/JitILCommon/JitILBase_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitILCommon/JitILBase_SystemRegisters.cpp index 1188cf1aa3ca..bc0eac6cc7fe 100644 --- a/Source/Core/Core/PowerPC/JitILCommon/JitILBase_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitILCommon/JitILBase_SystemRegisters.cpp @@ -148,7 +148,8 @@ void JitILBase::mcrf(UGeckoInstruction inst) void JitILBase::crXX(UGeckoInstruction inst) { - // Ported from Jit_SystemRegister.cpp + INSTRUCTION_START + JITDISABLE(bJITSystemRegistersOff) // Get bit CRBA in EAX aligned with bit CRBD const int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);