JitArm64: Fix CoreTiming contract

Call Advance at the start of each timing slice instead of the end.

Possibly fixed a bug where a slice would randomly branch straight
back to Advance() because the flags were not set to the right
values before branching to the dispatcher entrypoint.
This commit is contained in:
EmptyChaos 2016-09-12 09:08:56 +00:00
parent f5bfce657c
commit 55a7f576aa

View File

@ -28,18 +28,28 @@ void JitArm64::GenerateAsm()
MOVP2R(PPC_REG, &PowerPC::ppcState); MOVP2R(PPC_REG, &PowerPC::ppcState);
// Load the current PC into DISPATCHER_PC // The PC will be loaded into DISPATCHER_PC after the call to CoreTiming::Advance().
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); // Advance() does an exception check so we don't know what PC to use until afterwards.
FixupBranch to_start_of_timing_slice = 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
// do
// {
// CoreTiming::Advance(); // <-- Checks for exceptions (changes PC)
// DISPATCHER_PC = PC;
// do
// {
// dispatcherNoCheck:
// ExecuteBlock(JitBase::Dispatch());
// dispatcher:
// } while (PowerPC::ppcState.downcount > 0);
// doTiming:
// NPC = PC = DISPATCHER_PC;
// } while (CPU::GetState() == CPU::CPU_RUNNING);
AlignCodePage(); AlignCodePage();
dispatcher = GetCodePtr(); dispatcher = GetCodePtr();
WARN_LOG(DYNA_REC, "Dispatcher is %p\n", dispatcher); WARN_LOG(DYNA_REC, "Dispatcher is %p\n", dispatcher);
SetJumpTarget(to_dispatcher);
// Downcount Check // Downcount Check
// The result of slice decrementation should be in flags if somebody jumped here // The result of slice decrementation should be in flags if somebody jumped here
// IMPORTANT - We jump on negative, not carry!!! // IMPORTANT - We jump on negative, not carry!!!
@ -119,12 +129,6 @@ void JitArm64::GenerateAsm()
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc)); STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc)); STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
MOVP2R(X30, &CoreTiming::Advance);
BLR(X30);
// Load the PC back into DISPATCHER_PC (the exception handler might have changed it)
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
// Check the state pointer to see if we are exiting // Check the state pointer to see if we are exiting
// Gets checked on at the end of every slice // Gets checked on at the end of every slice
MOVP2R(X0, CPU::GetStatePtr()); MOVP2R(X0, CPU::GetStatePtr());
@ -133,11 +137,17 @@ void JitArm64::GenerateAsm()
CMP(W0, 0); CMP(W0, 0);
FixupBranch Exit = B(CC_NEQ); FixupBranch Exit = B(CC_NEQ);
B(dispatcher); SetJumpTarget(to_start_of_timing_slice);
MOVP2R(X30, &CoreTiming::Advance);
BLR(X30);
// Load the PC back into DISPATCHER_PC (the exception handler might have changed it)
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
// We can safely assume that downcount >= 1
B(dispatcherNoCheck);
SetJumpTarget(Exit); SetJumpTarget(Exit);
STR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
ABI_PopRegisters(regs_to_save); ABI_PopRegisters(regs_to_save);
RET(X30); RET(X30);