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:
parent
2f92b82b29
commit
727ef4a625
|
@ -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
|
||||
|
|
|
@ -209,7 +209,6 @@
|
|||
<ClCompile Include="PowerPC\JitILCommon\JitILBase_SystemRegisters.cpp" />
|
||||
<ClCompile Include="PowerPC\Jit64IL\IR_X86.cpp" />
|
||||
<ClCompile Include="PowerPC\Jit64IL\JitIL.cpp" />
|
||||
<ClCompile Include="PowerPC\Jit64IL\JitILAsm.cpp" />
|
||||
<ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp" />
|
||||
<ClCompile Include="PowerPC\Jit64\Jit.cpp" />
|
||||
<ClCompile Include="PowerPC\Jit64\Jit64_Tables.cpp" />
|
||||
|
@ -399,7 +398,6 @@
|
|||
<ClInclude Include="PowerPC\Interpreter\Interpreter_FPUtils.h" />
|
||||
<ClInclude Include="PowerPC\Interpreter\Interpreter_Tables.h" />
|
||||
<ClInclude Include="PowerPC\Jit64IL\JitIL.h" />
|
||||
<ClInclude Include="PowerPC\Jit64IL\JitILAsm.h" />
|
||||
<ClInclude Include="PowerPC\Jit64IL\JitIL_Tables.h" />
|
||||
<ClInclude Include="PowerPC\Jit64\Jit.h" />
|
||||
<ClInclude Include="PowerPC\Jit64\Jit64_Tables.h" />
|
||||
|
|
|
@ -641,9 +641,6 @@
|
|||
<ClCompile Include="PowerPC\Jit64IL\JitIL_Tables.cpp">
|
||||
<Filter>PowerPC\JitIL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerPC\Jit64IL\JitILAsm.cpp">
|
||||
<Filter>PowerPC\JitIL</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerPC\Jit64\Jit_Branch.cpp">
|
||||
<Filter>PowerPC\Jit64</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1191,9 +1188,6 @@
|
|||
<ClInclude Include="PowerPC\Jit64IL\JitIL_Tables.h">
|
||||
<Filter>PowerPC\JitIL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowerPC\Jit64IL\JitILAsm.h">
|
||||
<Filter>PowerPC\JitIL</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowerPC\Jit64\JitRegCache.h">
|
||||
<Filter>PowerPC\Jit64</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -37,5 +37,3 @@ public:
|
|||
FreeCodeSpace();
|
||||
}
|
||||
};
|
||||
|
||||
extern Jit64AsmRoutineManager asm_routines;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<void *>(&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<void *>(&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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ private:
|
|||
TrampolineCache trampolines;
|
||||
|
||||
public:
|
||||
JitILAsmRoutineManager asm_routines;
|
||||
Jit64AsmRoutineManager asm_routines;
|
||||
|
||||
JitIL() {}
|
||||
~JitIL() {}
|
||||
|
|
|
@ -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);*/
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,8 +23,6 @@ public:
|
|||
const u8 *dispatcherNoCheck;
|
||||
const u8 *dispatcherPcInEAX;
|
||||
|
||||
const u8 *fpException;
|
||||
const u8 *testExceptions;
|
||||
const u8 *testExternalExceptions;
|
||||
const u8 *dispatchPcInEAX;
|
||||
const u8 *doTiming;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue