JitArm64: Use a register as PC argument for the dispatcher.

This commit is contained in:
degasus 2016-02-29 09:39:54 +01:00
parent 050932ed23
commit 7b017c6a65
4 changed files with 33 additions and 32 deletions

View File

@ -193,31 +193,28 @@ void JitArm64::WriteExit(u32 destination)
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
b->linkData.push_back(linkData);
// the code generated in JitArm64BlockCache::WriteDestroyBlock must fit in this block
ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA);
MOVI2R(WA, destination);
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);
MOVI2R(X30, (u64)asm_routines.dispatcher);
MOVI2R(DISPATCHER_PC, destination);
BR(X30);
}
void JitArm64::WriteExit(ARM64Reg Reg)
{
STR(INDEX_UNSIGNED, Reg, X29, PPCSTATE_OFF(pc));
Cleanup();
DoDownCount();
if (Reg != DISPATCHER_PC)
MOV(DISPATCHER_PC, Reg);
gpr.Unlock(Reg);
if (Profiler::g_ProfileBlocks)
EndTimeProfile(js.curBlock);
MOVI2R(EncodeRegTo64(Reg), (u64)asm_routines.dispatcher);
BR(EncodeRegTo64(Reg));
gpr.Unlock(Reg);
MOVI2R(X30, (u64)asm_routines.dispatcher);
BR(X30);
}
void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
@ -227,10 +224,10 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
ARM64Reg WA = gpr.GetReg();
LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(pc));
FixupBranch no_exceptions = CBZ(WA);
gpr.Unlock(WA);
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(pc));
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(npc));
if (only_external)
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExternalExceptions);
@ -238,17 +235,18 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
MOVI2R(EncodeRegTo64(dest), (u64)&PowerPC::CheckExceptions);
BLR(EncodeRegTo64(dest));
LDR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(npc));
STR(INDEX_UNSIGNED, dest, PPC_REG, PPCSTATE_OFF(pc));
SetJumpTarget(no_exceptions);
if (dest != DISPATCHER_PC)
MOV(DISPATCHER_PC, dest);
gpr.Unlock(dest);
if (Profiler::g_ProfileBlocks)
EndTimeProfile(js.curBlock);
MOVI2R(EncodeRegTo64(dest), (u64)asm_routines.dispatcher);
BR(EncodeRegTo64(dest));
gpr.Unlock(dest);
MOVI2R(X30, (u64)asm_routines.dispatcher);
BR(X30);
}
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);
ARM64Reg WA = gpr.GetReg();
ARM64Reg XA = EncodeRegTo64(WA);
MOVI2R(WA, js.blockStart);
STR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(pc));
MOVI2R(DISPATCHER_PC, js.blockStart);
MOVI2R(XA, (u64)asm_routines.doTiming);
BR(XA);
gpr.Unlock(WA);
@ -423,8 +420,8 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
FixupBranch fail = B();
SwitchToFarCode();
SetJumpTarget(fail);
MOVI2R(W0, js.blockStart);
STR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(pc));
MOVI2R(DISPATCHER_PC, js.blockStart);
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
MOVI2R(W0, (u32)JitInterface::ExceptionType::EXCEPTIONS_PAIRED_QUANTIZE);
MOVI2R(X1, (u64)&JitInterface::CompileExceptionCheck);
BLR(X1);

View File

@ -29,9 +29,8 @@ void JitArm64BlockCache::WriteDestroyBlock(const u8* location, u32 address)
{
// must fit within the code generated in JitArm64::WriteExit
ARM64XEmitter emit((u8 *)location);
emit.MOVI2R(W0, address);
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.FlushIcache();
}

View File

@ -17,6 +17,7 @@ using namespace Arm64Gen;
// Dedicated host registers
static const ARM64Reg MEM_REG = X28; // memory base register
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))

View File

@ -28,6 +28,9 @@ void JitArm64AsmRoutineManager::Generate()
MOVI2R(PPC_REG, (u64)&PowerPC::ppcState);
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();
// 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
// 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(W26, WSP, 3, 2); // Wipe the top 3 bits. Same as PC & JIT_ICACHE_MASK
BFM(DISPATCHER_PC, WSP, 3, 2); // Wipe the top 3 bits. Same as PC & JIT_ICACHE_MASK
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
// Success, it is our Jitblock.
@ -62,6 +64,8 @@ void JitArm64AsmRoutineManager::Generate()
SetJumpTarget(JitBlock);
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
MOVI2R(X30, (u64)&Jit);
BLR(X30);
@ -75,12 +79,11 @@ void JitArm64AsmRoutineManager::Generate()
// Does exception checking
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(Exceptions));
FixupBranch no_exceptions = CBZ(W0);
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(pc));
STR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(npc));
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
MOVI2R(X30, (u64)&PowerPC::CheckExceptions);
BLR(X30);
LDR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(npc));
STR(INDEX_UNSIGNED, W0, PPC_REG, PPCSTATE_OFF(pc));
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
SetJumpTarget(no_exceptions);
// Check the state pointer to see if we are exiting
@ -94,6 +97,7 @@ void JitArm64AsmRoutineManager::Generate()
B(dispatcher);
SetJumpTarget(Exit);
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
// Let the waiting thread know we are done leaving
MOVI2R(X0, (u64)&PowerPC::FinishStateMove);