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.
This commit is contained in:
magumagu 2014-04-23 21:35:49 -07:00
parent 2f92b82b29
commit 727ef4a625
18 changed files with 71 additions and 339 deletions

View File

@ -180,7 +180,6 @@ if(_M_X86)
set(SRCS ${SRCS} set(SRCS ${SRCS}
x64MemTools.cpp x64MemTools.cpp
PowerPC/Jit64IL/IR_X86.cpp PowerPC/Jit64IL/IR_X86.cpp
PowerPC/Jit64IL/JitILAsm.cpp
PowerPC/Jit64IL/JitIL.cpp PowerPC/Jit64IL/JitIL.cpp
PowerPC/Jit64IL/JitIL_Tables.cpp PowerPC/Jit64IL/JitIL_Tables.cpp
PowerPC/Jit64/Jit64_Tables.cpp PowerPC/Jit64/Jit64_Tables.cpp

View File

@ -209,7 +209,6 @@
<ClCompile Include="PowerPC\JitILCommon\JitILBase_SystemRegisters.cpp" /> <ClCompile Include="PowerPC\JitILCommon\JitILBase_SystemRegisters.cpp" />
<ClCompile Include="PowerPC\Jit64IL\IR_X86.cpp" /> <ClCompile Include="PowerPC\Jit64IL\IR_X86.cpp" />
<ClCompile Include="PowerPC\Jit64IL\JitIL.cpp" /> <ClCompile Include="PowerPC\Jit64IL\JitIL.cpp" />
<ClCompile Include="PowerPC\Jit64IL\JitILAsm.cpp" />
<ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp" /> <ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit.cpp" /> <ClCompile Include="PowerPC\Jit64\Jit.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit64_Tables.cpp" /> <ClCompile Include="PowerPC\Jit64\Jit64_Tables.cpp" />
@ -399,7 +398,6 @@
<ClInclude Include="PowerPC\Interpreter\Interpreter_FPUtils.h" /> <ClInclude Include="PowerPC\Interpreter\Interpreter_FPUtils.h" />
<ClInclude Include="PowerPC\Interpreter\Interpreter_Tables.h" /> <ClInclude Include="PowerPC\Interpreter\Interpreter_Tables.h" />
<ClInclude Include="PowerPC\Jit64IL\JitIL.h" /> <ClInclude Include="PowerPC\Jit64IL\JitIL.h" />
<ClInclude Include="PowerPC\Jit64IL\JitILAsm.h" />
<ClInclude Include="PowerPC\Jit64IL\JitIL_Tables.h" /> <ClInclude Include="PowerPC\Jit64IL\JitIL_Tables.h" />
<ClInclude Include="PowerPC\Jit64\Jit.h" /> <ClInclude Include="PowerPC\Jit64\Jit.h" />
<ClInclude Include="PowerPC\Jit64\Jit64_Tables.h" /> <ClInclude Include="PowerPC\Jit64\Jit64_Tables.h" />

View File

@ -641,9 +641,6 @@
<ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp"> <ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp">
<Filter>PowerPC\JitIL</Filter> <Filter>PowerPC\JitIL</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="PowerPC\Jit64IL\JitILAsm.cpp">
<Filter>PowerPC\JitIL</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64\Jit_Branch.cpp"> <ClCompile Include="PowerPC\Jit64\Jit_Branch.cpp">
<Filter>PowerPC\Jit64</Filter> <Filter>PowerPC\Jit64</Filter>
</ClCompile> </ClCompile>
@ -1191,9 +1188,6 @@
<ClInclude Include="PowerPC\Jit64IL\JitIL_Tables.h"> <ClInclude Include="PowerPC\Jit64IL\JitIL_Tables.h">
<Filter>PowerPC\JitIL</Filter> <Filter>PowerPC\JitIL</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="PowerPC\Jit64IL\JitILAsm.h">
<Filter>PowerPC\JitIL</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64\JitRegCache.h"> <ClInclude Include="PowerPC\Jit64\JitRegCache.h">
<Filter>PowerPC\Jit64</Filter> <Filter>PowerPC\Jit64</Filter>
</ClInclude> </ClInclude>

View File

@ -28,8 +28,6 @@ static bool enableDebug = false;
//RBX - Base pointer of memory //RBX - Base pointer of memory
//R15 - Pointer to array of block pointers //R15 - Pointer to array of block pointers
Jit64AsmRoutineManager asm_routines;
// PLAN: no more block numbers - crazy opcodes just contain offset within // PLAN: no more block numbers - crazy opcodes just contain offset within
// dynarec buffer // dynarec buffer
// At this offset - 4, there is an int specifying the block number. // At this offset - 4, there is an int specifying the block number.

View File

@ -37,5 +37,3 @@ public:
FreeCodeSpace(); FreeCodeSpace();
} }
}; };
extern Jit64AsmRoutineManager asm_routines;

View File

@ -1636,7 +1636,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
Jit->ABI_CallFunction((void *)&PowerPC::OnIdleIL); Jit->ABI_CallFunction((void *)&PowerPC::OnIdleIL);
Jit->MOV(32, M(&PC), Imm32(ibuild->GetImmValue( getOp2(I) ))); Jit->MOV(32, M(&PC), Imm32(ibuild->GetImmValue( getOp2(I) )));
Jit->JMP(((JitIL *)jit)->asm_routines.testExceptions, true); Jit->WriteExceptionExit();
Jit->SetJumpTarget(cont); Jit->SetJumpTarget(cont);
if (RI.IInfo[I - RI.FirstI] & 4) 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)); unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->ABI_CallFunction((void *)&CoreTiming::Idle); Jit->ABI_CallFunction((void *)&CoreTiming::Idle);
Jit->MOV(32, M(&PC), Imm32(InstLoc)); Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->JMP(((JitIL *)jit)->asm_routines.testExceptions, true); Jit->WriteExceptionExit();
break; break;
} }
case SystemCall: { 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. // from PC. Update PC with the latest value in case that happens.
Jit->MOV(32, M(&PC), Imm32(InstLoc)); 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->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); Jit->SetJumpTarget(b1);
break; break;
} }

View File

@ -13,7 +13,6 @@
#include "Core/PowerPC/Profiler.h" #include "Core/PowerPC/Profiler.h"
#include "Core/PowerPC/Jit64IL/JitIL.h" #include "Core/PowerPC/Jit64IL/JitIL.h"
#include "Core/PowerPC/Jit64IL/JitIL_Tables.h" #include "Core/PowerPC/Jit64IL/JitIL_Tables.h"
#include "Core/PowerPC/Jit64IL/JitILAsm.h"
using namespace Gen; using namespace Gen;
using namespace PowerPC; using namespace PowerPC;
@ -426,12 +425,14 @@ void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg)
void JitIL::WriteRfiExitDestInOpArg(const Gen::OpArg& arg) void JitIL::WriteRfiExitDestInOpArg(const Gen::OpArg& arg)
{ {
MOV(32, M(&PC), arg); MOV(32, M(&PC), arg);
MOV(32, M(&NPC), arg);
Cleanup(); Cleanup();
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
ABI_CallFunction((void *)JitILProfiler::End); ABI_CallFunction((void *)JitILProfiler::End);
} }
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); 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() void JitIL::WriteExceptionExit()
@ -440,8 +441,11 @@ void JitIL::WriteExceptionExit()
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
ABI_CallFunction((void *)JitILProfiler::End); ABI_CallFunction((void *)JitILProfiler::End);
} }
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); 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() 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 // This block uses FPU - needs to add FP exception bailout
TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit
FixupBranch b1 = J_CC(CC_NZ); 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)); 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); SetJumpTarget(b1);
} }

View File

@ -28,7 +28,7 @@
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/PPCAnalyst.h" #include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PPCTables.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/Jit_Util.h"
#include "Core/PowerPC/JitCommon/JitBackpatch.h" #include "Core/PowerPC/JitCommon/JitBackpatch.h"
#include "Core/PowerPC/JitCommon/JitBase.h" #include "Core/PowerPC/JitCommon/JitBase.h"
@ -50,7 +50,7 @@ private:
TrampolineCache trampolines; TrampolineCache trampolines;
public: public:
JitILAsmRoutineManager asm_routines; Jit64AsmRoutineManager asm_routines;
JitIL() {} JitIL() {}
~JitIL() {} ~JitIL() {}

View File

@ -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<void *>(&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<void *>(&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<void *>(&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<void *>(&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<void *>(&CoreTiming::Advance));
testExceptions = GetCodePtr();
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&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);*/
}

View File

@ -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;

View File

@ -166,17 +166,32 @@ void JitArm::WriteRfiExitDestInR(ARMReg Reg)
Cleanup(); Cleanup();
DoDownCount(); DoDownCount();
MOVI2R(Reg, (u32)asm_routines.testExceptions); ARMReg A = gpr.GetReg(false);
B(Reg);
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 gpr.Unlock(Reg); // This was locked in the instruction beforehand
MOVI2R(A, (u32)asm_routines.dispatcher);
B(A);
} }
void JitArm::WriteExceptionExit() void JitArm::WriteExceptionExit()
{ {
ARMReg A = gpr.GetReg(false);
Cleanup(); Cleanup();
DoDownCount(); 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); B(A);
} }
void JitArm::WriteExit(u32 destination) void JitArm::WriteExit(u32 destination)
@ -372,8 +387,17 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
TST(A, Shift); TST(A, Shift);
SetCC(CC_EQ); SetCC(CC_EQ);
STR(C, R9, PPCSTATE_OFF(pc)); 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); B(A);
SetCC(); SetCC();
gpr.Unlock(A, C); gpr.Unlock(A, C);
} }

View File

@ -138,8 +138,7 @@ void JitArm::bx(UGeckoInstruction inst)
BL(R14); BL(R14);
MOVI2R(R14, js.compilerPC); MOVI2R(R14, js.compilerPC);
STR(R14, R9, PPCSTATE_OFF(pc)); STR(R14, R9, PPCSTATE_OFF(pc));
MOVI2R(R14, (u32)asm_routines.testExceptions); WriteExceptionExit();
B(R14);
} }
WriteExit(destination); WriteExit(destination);
} }

View File

@ -141,17 +141,6 @@ void JitArmAsmRoutineManager::Generate()
B(dispatcherNoCheck); 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); SetJumpTarget(bail);
doTiming = GetCodePtr(); doTiming = GetCodePtr();
// XXX: In JIT64, Advance() gets called /after/ the exception checking // XXX: In JIT64, Advance() gets called /after/ the exception checking
@ -159,7 +148,6 @@ void JitArmAsmRoutineManager::Generate()
QuickCallFunction(R14, (void*)&CoreTiming::Advance); QuickCallFunction(R14, (void*)&CoreTiming::Advance);
// Does exception checking // Does exception checking
testExceptions = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(pc)); LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(npc)); STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);

View File

@ -604,8 +604,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) {
Jit->BL(R14); Jit->BL(R14);
Jit->MOVI2R(R14, InstLoc); Jit->MOVI2R(R14, InstLoc);
Jit->STR(R14, R9, PPCSTATE_OFF(pc)); Jit->STR(R14, R9, PPCSTATE_OFF(pc));
Jit->MOVI2R(R14, (u32)Jit->GetAsmRoutines()->testExceptions); Jit->WriteExceptionExit();
Jit->B(R14);
break; break;
} }
case InterpreterBranch: { case InterpreterBranch: {

View File

@ -111,15 +111,28 @@ void JitArmIL::WriteRfiExitDestInR(ARMReg Reg)
{ {
STR(Reg, R9, PPCSTATE_OFF(pc)); STR(Reg, R9, PPCSTATE_OFF(pc));
DoDownCount(); 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() void JitArmIL::WriteExceptionExit()
{ {
DoDownCount(); DoDownCount();
MOVI2R(R14, (u32)asm_routines.testExceptions); LDR(R0, R9, PPCSTATE_OFF(pc));
B(R14); 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) void JitArmIL::WriteExit(u32 destination)
{ {

View File

@ -73,17 +73,6 @@ void JitArmILAsmRoutineManager::Generate()
B(dispatcherNoCheck); 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); SetJumpTarget(bail);
doTiming = GetCodePtr(); doTiming = GetCodePtr();
// XXX: In JIT64, Advance() gets called /after/ the exception checking // XXX: In JIT64, Advance() gets called /after/ the exception checking
@ -91,7 +80,6 @@ void JitArmILAsmRoutineManager::Generate()
QuickCallFunction(R14, (void*)&CoreTiming::Advance); QuickCallFunction(R14, (void*)&CoreTiming::Advance);
// Does exception checking // Does exception checking
testExceptions = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(pc)); LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(npc)); STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions); QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);

View File

@ -23,8 +23,6 @@ public:
const u8 *dispatcherNoCheck; const u8 *dispatcherNoCheck;
const u8 *dispatcherPcInEAX; const u8 *dispatcherPcInEAX;
const u8 *fpException;
const u8 *testExceptions;
const u8 *testExternalExceptions; const u8 *testExternalExceptions;
const u8 *dispatchPcInEAX; const u8 *dispatchPcInEAX;
const u8 *doTiming; const u8 *doTiming;

View File

@ -148,7 +148,8 @@ void JitILBase::mcrf(UGeckoInstruction inst)
void JitILBase::crXX(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 // Get bit CRBA in EAX aligned with bit CRBD
const int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3); const int shiftA = (inst.CRBD & 3) - (inst.CRBA & 3);