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}
|
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
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -37,5 +37,3 @@ public:
|
||||||
FreeCodeSpace();
|
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->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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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();
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue