JitArm64: Use a register as PC argument for the dispatcher.
This commit is contained in:
parent
050932ed23
commit
7b017c6a65
|
@ -193,31 +193,28 @@ void JitArm64::WriteExit(u32 destination)
|
||||||
linkData.exitAddress = destination;
|
linkData.exitAddress = destination;
|
||||||
linkData.exitPtrs = GetWritableCodePtr();
|
linkData.exitPtrs = GetWritableCodePtr();
|
||||||
linkData.linkStatus = false;
|
linkData.linkStatus = false;
|
||||||
|
b->linkData.push_back(linkData);
|
||||||
|
|
||||||
// the code generated in JitArm64BlockCache::WriteDestroyBlock must fit in this block
|
// the code generated in JitArm64BlockCache::WriteDestroyBlock must fit in this block
|
||||||
ARM64Reg WA = gpr.GetReg();
|
MOVI2R(X30, (u64)asm_routines.dispatcher);
|
||||||
ARM64Reg XA = EncodeRegTo64(WA);
|
MOVI2R(DISPATCHER_PC, destination);
|
||||||
MOVI2R(WA, destination);
|
BR(X30);
|
||||||
STR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(pc));
|
|
||||||
MOVI2R(XA, (u64)asm_routines.dispatcher);
|
|
||||||
BR(XA);
|
|
||||||
gpr.Unlock(WA);
|
|
||||||
|
|
||||||
b->linkData.push_back(linkData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm64::WriteExit(ARM64Reg Reg)
|
void JitArm64::WriteExit(ARM64Reg Reg)
|
||||||
{
|
{
|
||||||
STR(INDEX_UNSIGNED, Reg, X29, PPCSTATE_OFF(pc));
|
|
||||||
Cleanup();
|
Cleanup();
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
|
|
||||||
|
if (Reg != DISPATCHER_PC)
|
||||||
|
MOV(DISPATCHER_PC, Reg);
|
||||||
|
gpr.Unlock(Reg);
|
||||||
|
|
||||||
if (Profiler::g_ProfileBlocks)
|
if (Profiler::g_ProfileBlocks)
|
||||||
EndTimeProfile(js.curBlock);
|
EndTimeProfile(js.curBlock);
|
||||||
|
|
||||||
MOVI2R(EncodeRegTo64(Reg), (u64)asm_routines.dispatcher);
|
MOVI2R(X30, (u64)asm_routines.dispatcher);
|
||||||
BR(EncodeRegTo64(Reg));
|
BR(X30);
|
||||||
gpr.Unlock(Reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
|
void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
|
||||||
|
@ -227,10 +224,10 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
|
||||||
|
|
||||||
ARM64Reg WA = gpr.GetReg();
|
ARM64Reg WA = gpr.GetReg();
|
||||||
LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||||
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(pc));
|
|
||||||
FixupBranch no_exceptions = CBZ(WA);
|
FixupBranch no_exceptions = CBZ(WA);
|
||||||
gpr.Unlock(WA);
|
gpr.Unlock(WA);
|
||||||
|
|
||||||
|
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(pc));
|
||||||
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(npc));
|
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(npc));
|
||||||
if (only_external)
|
if (only_external)
|
||||||
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExternalExceptions);
|
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExternalExceptions);
|
||||||
|
@ -238,17 +235,18 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
|
||||||
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExceptions);
|
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExceptions);
|
||||||
BLR(EncodeRegTo64(dest));
|
BLR(EncodeRegTo64(dest));
|
||||||
LDR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(npc));
|
LDR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(npc));
|
||||||
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(pc));
|
|
||||||
|
|
||||||
SetJumpTarget(no_exceptions);
|
SetJumpTarget(no_exceptions);
|
||||||
|
|
||||||
|
if (dest != DISPATCHER_PC)
|
||||||
|
MOV(DISPATCHER_PC, dest);
|
||||||
|
gpr.Unlock(dest);
|
||||||
|
|
||||||
if (Profiler::g_ProfileBlocks)
|
if (Profiler::g_ProfileBlocks)
|
||||||
EndTimeProfile(js.curBlock);
|
EndTimeProfile(js.curBlock);
|
||||||
|
|
||||||
MOVI2R(EncodeRegTo64(dest), (u64)asm_routines.dispatcher);
|
MOVI2R(X30, (u64)asm_routines.dispatcher);
|
||||||
BR(EncodeRegTo64(dest));
|
BR(X30);
|
||||||
|
|
||||||
gpr.Unlock(dest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm64::DumpCode(const u8* start, const u8* end)
|
void JitArm64::DumpCode(const u8* start, const u8* end)
|
||||||
|
@ -389,8 +387,7 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
||||||
FixupBranch bail = B(CC_PL);
|
FixupBranch bail = B(CC_PL);
|
||||||
ARM64Reg WA = gpr.GetReg();
|
ARM64Reg WA = gpr.GetReg();
|
||||||
ARM64Reg XA = EncodeRegTo64(WA);
|
ARM64Reg XA = EncodeRegTo64(WA);
|
||||||
MOVI2R(WA, js.blockStart);
|
MOVI2R(DISPATCHER_PC, js.blockStart);
|
||||||
STR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(pc));
|
|
||||||
MOVI2R(XA, (u64)asm_routines.doTiming);
|
MOVI2R(XA, (u64)asm_routines.doTiming);
|
||||||
BR(XA);
|
BR(XA);
|
||||||
gpr.Unlock(WA);
|
gpr.Unlock(WA);
|
||||||
|
@ -423,8 +420,8 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
|
||||||
FixupBranch fail = B();
|
FixupBranch fail = B();
|
||||||
SwitchToFarCode();
|
SwitchToFarCode();
|
||||||
SetJumpTarget(fail);
|
SetJumpTarget(fail);
|
||||||
MOVI2R(W0, js.blockStart);
|
MOVI2R(DISPATCHER_PC, js.blockStart);
|
||||||
STR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(pc));
|
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||||
MOVI2R(W0, (u32)JitInterface::ExceptionType::EXCEPTIONS_PAIRED_QUANTIZE);
|
MOVI2R(W0, (u32)JitInterface::ExceptionType::EXCEPTIONS_PAIRED_QUANTIZE);
|
||||||
MOVI2R(X1, (u64)&JitInterface::CompileExceptionCheck);
|
MOVI2R(X1, (u64)&JitInterface::CompileExceptionCheck);
|
||||||
BLR(X1);
|
BLR(X1);
|
||||||
|
|
|
@ -29,9 +29,8 @@ void JitArm64BlockCache::WriteDestroyBlock(const u8* location, u32 address)
|
||||||
{
|
{
|
||||||
// must fit within the code generated in JitArm64::WriteExit
|
// must fit within the code generated in JitArm64::WriteExit
|
||||||
ARM64XEmitter emit((u8 *)location);
|
ARM64XEmitter emit((u8 *)location);
|
||||||
emit.MOVI2R(W0, address);
|
|
||||||
emit.MOVI2R(X30, (u64)jit->GetAsmRoutines()->dispatcher);
|
emit.MOVI2R(X30, (u64)jit->GetAsmRoutines()->dispatcher);
|
||||||
emit.STR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(pc));
|
emit.MOVI2R(DISPATCHER_PC, address);
|
||||||
emit.BR(X30);
|
emit.BR(X30);
|
||||||
emit.FlushIcache();
|
emit.FlushIcache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ using namespace Arm64Gen;
|
||||||
// Dedicated host registers
|
// Dedicated host registers
|
||||||
static const ARM64Reg MEM_REG = X28; // memory base register
|
static const ARM64Reg MEM_REG = X28; // memory base register
|
||||||
static const ARM64Reg PPC_REG = X29; // ppcState pointer
|
static const ARM64Reg PPC_REG = X29; // ppcState pointer
|
||||||
|
static const ARM64Reg DISPATCHER_PC = W26; // register for PC when calling the dispatcher
|
||||||
|
|
||||||
#define PPCSTATE_OFF(elem) (offsetof(PowerPC::PowerPCState, elem))
|
#define PPCSTATE_OFF(elem) (offsetof(PowerPC::PowerPCState, elem))
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ void JitArm64AsmRoutineManager::Generate()
|
||||||
MOVI2R(PPC_REG, (u64)&PowerPC::ppcState);
|
MOVI2R(PPC_REG, (u64)&PowerPC::ppcState);
|
||||||
MOVI2R(MEM_REG, (u64)Memory::logical_base);
|
MOVI2R(MEM_REG, (u64)Memory::logical_base);
|
||||||
|
|
||||||
|
// Load the current PC into DISPATCHER_PC
|
||||||
|
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||||
|
|
||||||
FixupBranch to_dispatcher = B();
|
FixupBranch to_dispatcher = B();
|
||||||
|
|
||||||
// If we align the dispatcher to a page then we can load its location with one ADRP instruction
|
// If we align the dispatcher to a page then we can load its location with one ADRP instruction
|
||||||
|
@ -46,11 +49,10 @@ void JitArm64AsmRoutineManager::Generate()
|
||||||
|
|
||||||
// This block of code gets the address of the compiled block of code
|
// This block of code gets the address of the compiled block of code
|
||||||
// It runs though to the compiling portion if it isn't found
|
// It runs though to the compiling portion if it isn't found
|
||||||
LDR(INDEX_UNSIGNED, W26, PPC_REG, PPCSTATE_OFF(pc)); // Load the current PC into W26
|
BFM(DISPATCHER_PC, WSP, 3, 2); // Wipe the top 3 bits. Same as PC & JIT_ICACHE_MASK
|
||||||
BFM(W26, WSP, 3, 2); // Wipe the top 3 bits. Same as PC & JIT_ICACHE_MASK
|
|
||||||
|
|
||||||
MOVI2R(X27, (u64)jit->GetBlockCache()->iCache.data());
|
MOVI2R(X27, (u64)jit->GetBlockCache()->iCache.data());
|
||||||
LDR(W27, X27, X26);
|
LDR(W27, X27, EncodeRegTo64(DISPATCHER_PC));
|
||||||
|
|
||||||
FixupBranch JitBlock = TBNZ(W27, 7); // Test the 7th bit
|
FixupBranch JitBlock = TBNZ(W27, 7); // Test the 7th bit
|
||||||
// Success, it is our Jitblock.
|
// Success, it is our Jitblock.
|
||||||
|
@ -62,6 +64,8 @@ void JitArm64AsmRoutineManager::Generate()
|
||||||
|
|
||||||
SetJumpTarget(JitBlock);
|
SetJumpTarget(JitBlock);
|
||||||
|
|
||||||
|
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||||
|
|
||||||
MOVI2R(X30, (u64)&Jit);
|
MOVI2R(X30, (u64)&Jit);
|
||||||
BLR(X30);
|
BLR(X30);
|
||||||
|
|
||||||
|
@ -75,12 +79,11 @@ void JitArm64AsmRoutineManager::Generate()
|
||||||
// Does exception checking
|
// Does exception checking
|
||||||
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(Exceptions));
|
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||||
FixupBranch no_exceptions = CBZ(W0);
|
FixupBranch no_exceptions = CBZ(W0);
|
||||||
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(pc));
|
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||||
STR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(npc));
|
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
|
||||||
MOVI2R(X30, (u64)&PowerPC::CheckExceptions);
|
MOVI2R(X30, (u64)&PowerPC::CheckExceptions);
|
||||||
BLR(X30);
|
BLR(X30);
|
||||||
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(npc));
|
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
|
||||||
STR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(pc));
|
|
||||||
SetJumpTarget(no_exceptions);
|
SetJumpTarget(no_exceptions);
|
||||||
|
|
||||||
// Check the state pointer to see if we are exiting
|
// Check the state pointer to see if we are exiting
|
||||||
|
@ -94,6 +97,7 @@ void JitArm64AsmRoutineManager::Generate()
|
||||||
B(dispatcher);
|
B(dispatcher);
|
||||||
|
|
||||||
SetJumpTarget(Exit);
|
SetJumpTarget(Exit);
|
||||||
|
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||||
|
|
||||||
// Let the waiting thread know we are done leaving
|
// Let the waiting thread know we are done leaving
|
||||||
MOVI2R(X0, (u64)&PowerPC::FinishStateMove);
|
MOVI2R(X0, (u64)&PowerPC::FinishStateMove);
|
||||||
|
|
Loading…
Reference in New Issue