Jit_SystemRegisters: mfspr

This commit is contained in:
MerryMage 2018-10-15 21:01:41 +01:00
parent 9438ea0ef5
commit 1d867493d9

View File

@ -281,22 +281,23 @@ void Jit64::mfspr(UGeckoInstruction inst)
// redundant for the JIT. // redundant for the JIT.
// no register choice // no register choice
gpr.FlushLockX(RDX, RAX); RCX64Reg rdx = gpr.Scratch(RDX);
gpr.FlushLockX(RCX); RCX64Reg rax = gpr.Scratch(RAX);
RCX64Reg rcx = gpr.Scratch(RCX);
MOV(64, R(RCX), ImmPtr(&CoreTiming::g)); MOV(64, rcx, ImmPtr(&CoreTiming::g));
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the // An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
// cost of calling out to C for this is actually significant. // cost of calling out to C for this is actually significant.
// Scale downcount by the CPU overclocking factor. // Scale downcount by the CPU overclocking factor.
CVTSI2SS(XMM0, PPCSTATE(downcount)); CVTSI2SS(XMM0, PPCSTATE(downcount));
MULSS(XMM0, MDisp(RCX, offsetof(CoreTiming::Globals, last_OC_factor_inverted))); MULSS(XMM0, MDisp(rcx, offsetof(CoreTiming::Globals, last_OC_factor_inverted)));
CVTSS2SI(RDX, R(XMM0)); // RDX is downcount scaled by the overclocking factor CVTSS2SI(rdx, R(XMM0)); // RDX is downcount scaled by the overclocking factor
MOV(32, R(RAX), MDisp(RCX, offsetof(CoreTiming::Globals, slice_length))); MOV(32, rax, MDisp(rcx, offsetof(CoreTiming::Globals, slice_length)));
SUB(64, R(RAX), R(RDX)); // cycles since the last CoreTiming::Advance() event is (slicelength - SUB(64, rax, rdx); // cycles since the last CoreTiming::Advance() event is (slicelength -
// Scaled_downcount) // Scaled_downcount)
ADD(64, R(RAX), MDisp(RCX, offsetof(CoreTiming::Globals, global_timer))); ADD(64, rax, MDisp(rcx, offsetof(CoreTiming::Globals, global_timer)));
SUB(64, R(RAX), MDisp(RCX, offsetof(CoreTiming::Globals, fake_TB_start_ticks))); SUB(64, rax, MDisp(rcx, offsetof(CoreTiming::Globals, fake_TB_start_ticks)));
// It might seem convenient to correct the timer for the block position here for even more // It might seem convenient to correct the timer for the block position here for even more
// accurate // accurate
// timing, but as of currently, this can break games. If we end up reading a time *after* the // timing, but as of currently, this can break games. If we end up reading a time *after* the
@ -307,15 +308,15 @@ void Jit64::mfspr(UGeckoInstruction inst)
// Revolution, // Revolution,
// which won't get past the loading screen. // which won't get past the loading screen.
// if (js.downcountAmount) // if (js.downcountAmount)
// ADD(64, R(RAX), Imm32(js.downcountAmount)); // ADD(64, rax, Imm32(js.downcountAmount));
// a / 12 = (a * 0xAAAAAAAAAAAAAAAB) >> 67 // a / 12 = (a * 0xAAAAAAAAAAAAAAAB) >> 67
MOV(64, R(RDX), Imm64(0xAAAAAAAAAAAAAAABULL)); MOV(64, rdx, Imm64(0xAAAAAAAAAAAAAAABULL));
MUL(64, R(RDX)); MUL(64, rdx);
MOV(64, R(RAX), MDisp(RCX, offsetof(CoreTiming::Globals, fake_TB_start_value))); MOV(64, rax, MDisp(rcx, offsetof(CoreTiming::Globals, fake_TB_start_value)));
SHR(64, R(RDX), Imm8(3)); SHR(64, rdx, Imm8(3));
ADD(64, R(RAX), R(RDX)); ADD(64, rax, rdx);
MOV(64, PPCSTATE(spr[SPR_TL]), R(RAX)); MOV(64, PPCSTATE(spr[SPR_TL]), rax);
if (CanMergeNextInstructions(1)) if (CanMergeNextInstructions(1))
{ {
@ -330,40 +331,42 @@ void Jit64::mfspr(UGeckoInstruction inst)
{ {
js.downcountAmount++; js.downcountAmount++;
js.skipInstructions = 1; js.skipInstructions = 1;
gpr.Lock(d, n); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
gpr.BindToRegister(d, false); RCX64Reg Rn = gpr.Bind(n, RCMode::Write);
gpr.BindToRegister(n, false); RegCache::Realize(Rd, Rn);
if (iIndex == SPR_TL) if (iIndex == SPR_TL)
MOV(32, gpr.R(d), R(RAX)); MOV(32, Rd, rax);
if (nextIndex == SPR_TL) if (nextIndex == SPR_TL)
MOV(32, gpr.R(n), R(RAX)); MOV(32, Rn, rax);
SHR(64, R(RAX), Imm8(32)); SHR(64, rax, Imm8(32));
if (iIndex == SPR_TU) if (iIndex == SPR_TU)
MOV(32, gpr.R(d), R(RAX)); MOV(32, Rd, rax);
if (nextIndex == SPR_TU) if (nextIndex == SPR_TU)
MOV(32, gpr.R(n), R(RAX)); MOV(32, Rn, rax);
break; break;
} }
} }
gpr.Lock(d); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
gpr.BindToRegister(d, false); RegCache::Realize(Rd);
if (iIndex == SPR_TU) if (iIndex == SPR_TU)
SHR(64, R(RAX), Imm8(32)); SHR(64, rax, Imm8(32));
MOV(32, gpr.R(d), R(RAX)); MOV(32, Rd, rax);
break; break;
} }
case SPR_XER: case SPR_XER:
gpr.Lock(d); {
gpr.BindToRegister(d, false); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
MOVZX(32, 16, gpr.RX(d), PPCSTATE(xer_stringctrl)); RegCache::Realize(Rd);
MOVZX(32, 16, Rd, PPCSTATE(xer_stringctrl));
MOVZX(32, 8, RSCRATCH, PPCSTATE(xer_ca)); MOVZX(32, 8, RSCRATCH, PPCSTATE(xer_ca));
SHL(32, R(RSCRATCH), Imm8(XER_CA_SHIFT)); SHL(32, R(RSCRATCH), Imm8(XER_CA_SHIFT));
OR(32, gpr.R(d), R(RSCRATCH)); OR(32, Rd, R(RSCRATCH));
MOVZX(32, 8, RSCRATCH, PPCSTATE(xer_so_ov)); MOVZX(32, 8, RSCRATCH, PPCSTATE(xer_so_ov));
SHL(32, R(RSCRATCH), Imm8(XER_OV_SHIFT)); SHL(32, R(RSCRATCH), Imm8(XER_OV_SHIFT));
OR(32, gpr.R(d), R(RSCRATCH)); OR(32, Rd, R(RSCRATCH));
break; break;
}
case SPR_WPAR: case SPR_WPAR:
case SPR_DEC: case SPR_DEC:
case SPR_PMC1: case SPR_PMC1:
@ -372,13 +375,13 @@ void Jit64::mfspr(UGeckoInstruction inst)
case SPR_PMC4: case SPR_PMC4:
FALLBACK_IF(true); FALLBACK_IF(true);
default: default:
gpr.Lock(d); {
gpr.BindToRegister(d, false); RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
MOV(32, gpr.R(d), PPCSTATE(spr[iIndex])); RegCache::Realize(Rd);
MOV(32, Rd, PPCSTATE(spr[iIndex]));
break; break;
} }
gpr.UnlockAllX(); }
gpr.UnlockAll();
} }
void Jit64::mtmsr(UGeckoInstruction inst) void Jit64::mtmsr(UGeckoInstruction inst)