Fixed JIT register allocator.

Now it only writes back dirty registers when flushed
	* Fixed KillImmediate
	* Renamed LoadToX64 and StoreFromX64 to BindToRegister and StoreFromRegister respectively (as suggested by ector)
	* Code cleanup in calls to the reg allocator


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6053 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
dok.slade
2010-08-04 19:34:47 +00:00
parent a8f6904ec7
commit 9b6180ab27
9 changed files with 175 additions and 207 deletions
@@ -128,7 +128,7 @@ X64Reg RegCache::GetFreeXReg()
int preg = xregs[xr].ppcReg;
if (!locks[preg])
{
StoreFromX64(preg);
StoreFromRegister(preg);
return xr;
}
}
@@ -159,7 +159,7 @@ void RegCache::FlushR(X64Reg reg)
PanicAlert("Flushing non existent reg");
if (!xregs[reg].free)
{
StoreFromX64(xregs[reg].ppcReg);
StoreFromRegister(xregs[reg].ppcReg);
}
}
@@ -185,9 +185,12 @@ void RegCache::DiscardRegContentsIfCached(int preg)
{
if (regs[preg].away && regs[preg].location.IsSimpleReg())
{
xregs[regs[preg].location.GetSimpleReg()].free = true;
xregs[regs[preg].location.GetSimpleReg()].dirty = false;
X64Reg xr = regs[preg].location.GetSimpleReg();
xregs[xr].free = true;
xregs[xr].dirty = false;
xregs[xr].ppcReg = -1;
regs[preg].away = false;
regs[preg].location = GetDefaultLocation(preg);
}
}
@@ -252,15 +255,18 @@ OpArg FPURegCache::GetDefaultLocation(int reg) const
return M(&ppcState.ps[reg][0]);
}
void RegCache::KillImmediate(int preg)
void RegCache::KillImmediate(int preg, bool doLoad, bool makeDirty)
{
if (regs[preg].away && regs[preg].location.IsImm())
if (regs[preg].away)
{
LoadToX64(preg, true, true);
if (regs[preg].location.IsImm())
BindToRegister(preg, doLoad, makeDirty);
else if (regs[preg].location.IsSimpleReg())
xregs[RX(preg)].dirty |= makeDirty;
}
}
void GPRRegCache::LoadToX64(int i, bool doLoad, bool makeDirty)
void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty)
{
if (!regs[i].away && regs[i].location.IsImm())
PanicAlert("Bad immediate");
@@ -297,7 +303,7 @@ void GPRRegCache::LoadToX64(int i, bool doLoad, bool makeDirty)
}
}
void GPRRegCache::StoreFromX64(int i)
void GPRRegCache::StoreFromRegister(int i)
{
if (regs[i].away)
{
@@ -316,14 +322,14 @@ void GPRRegCache::StoreFromX64(int i)
doStore = true;
}
OpArg newLoc = GetDefaultLocation(i);
// if (doStore) //<-- Breaks JIT compilation
if (doStore)
emit->MOV(32, newLoc, regs[i].location);
regs[i].location = newLoc;
regs[i].away = false;
}
}
void FPURegCache::LoadToX64(int i, bool doLoad, bool makeDirty)
void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty)
{
_assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - load - imm");
if (!regs[i].away)
@@ -351,7 +357,7 @@ void FPURegCache::LoadToX64(int i, bool doLoad, bool makeDirty)
}
}
void FPURegCache::StoreFromX64(int i)
void FPURegCache::StoreFromRegister(int i)
{
_assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - store - imm");
if (regs[i].away)
@@ -389,12 +395,12 @@ void RegCache::Flush(FlushMode mode)
if (regs[i].location.IsSimpleReg())
{
X64Reg xr = RX(i);
StoreFromX64(i);
StoreFromRegister(i);
xregs[xr].dirty = false;
}
else if (regs[i].location.IsImm())
{
StoreFromX64(i);
StoreFromRegister(i);
}
else
{
@@ -96,12 +96,12 @@ public:
virtual void Flush(FlushMode mode);
virtual void Flush(PPCAnalyst::CodeOp *op) {Flush(FLUSH_ALL);}
int SanityCheck() const;
void KillImmediate(int preg);
void KillImmediate(int preg, bool doLoad, bool makeDirty);
//TODO - instead of doload, use "read", "write"
//read only will not set dirty flag
virtual void LoadToX64(int preg, bool doLoad = true, bool makeDirty = true) = 0;
virtual void StoreFromX64(int preg) = 0;
virtual void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) = 0;
virtual void StoreFromRegister(int preg) = 0;
const OpArg &R(int preg) const {return regs[preg].location;}
X64Reg RX(int preg) const
@@ -131,8 +131,8 @@ class GPRRegCache : public RegCache
{
public:
void Start(PPCAnalyst::BlockRegStats &stats);
void LoadToX64(int preg, bool doLoad = true, bool makeDirty = true);
void StoreFromX64(int preg);
void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true);
void StoreFromRegister(int preg);
OpArg GetDefaultLocation(int reg) const;
const int *GetAllocationOrder(int &count);
void SetImmediate32(int preg, u32 immValue);
@@ -143,8 +143,8 @@ class FPURegCache : public RegCache
{
public:
void Start(PPCAnalyst::BlockRegStats &stats);
void LoadToX64(int preg, bool doLoad = true, bool makeDirty = true);
void StoreFromX64(int preg);
void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true);
void StoreFromRegister(int preg);
const int *GetAllocationOrder(int &count);
OpArg GetDefaultLocation(int reg) const;
};
@@ -34,24 +34,24 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEm
fpr.Lock(d, a, b);
if (d == a)
{
fpr.LoadToX64(d, true);
fpr.BindToRegister(d, true);
(this->*op)(fpr.RX(d), fpr.R(b));
}
else if (d == b && reversible)
{
fpr.LoadToX64(d, true);
fpr.BindToRegister(d, true);
(this->*op)(fpr.RX(d), fpr.R(a));
}
else if (a != d && b != d)
{
// Sources different from d, can use rather quick solution
fpr.LoadToX64(d, !dupe);
fpr.BindToRegister(d, !dupe);
MOVSD(fpr.RX(d), fpr.R(a));
(this->*op)(fpr.RX(d), fpr.R(b));
}
else if (b != d)
{
fpr.LoadToX64(d, !dupe);
fpr.BindToRegister(d, !dupe);
MOVSD(XMM0, fpr.R(b));
MOVSD(fpr.RX(d), fpr.R(a));
(this->*op)(fpr.RX(d), Gen::R(XMM0));
@@ -60,7 +60,7 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEm
{
MOVSD(XMM0, fpr.R(a));
MOVSD(XMM1, fpr.R(b));
fpr.LoadToX64(d, !dupe);
fpr.BindToRegister(d, !dupe);
(this->*op)(XMM0, Gen::R(XMM1));
MOVSD(fpr.RX(d), Gen::R(XMM0));
}
@@ -87,7 +87,7 @@ void Jit64::fp_arith_s(UGeckoInstruction inst)
int d = inst.FD;
int b = inst.FB;
fpr.Lock(b, d);
fpr.LoadToX64(d, true, true);
fpr.BindToRegister(d, true, true);
MOVSD(XMM0, M((void *)&one_const));
SQRTSD(XMM1, fpr.R(b));
DIVSD(XMM0, R(XMM1));
@@ -160,7 +160,7 @@ void Jit64::fmaddXX(UGeckoInstruction inst)
XORPD(XMM0, M((void*)&psSignBits2));
break;
}
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
//YES it is necessary to dupe the result :(
//TODO : analysis - does the top reg get used? If so, dupe, if not, don't.
if (single_precision) {
@@ -186,7 +186,7 @@ void Jit64::fsign(UGeckoInstruction inst)
int d = inst.FD;
int b = inst.FB;
fpr.Lock(b, d);
fpr.LoadToX64(d, true, true);
fpr.BindToRegister(d, true, true);
MOVSD(XMM0, fpr.R(b));
switch (inst.SUBOP10) {
case 40: // fnegx
@@ -216,7 +216,7 @@ void Jit64::fmrx(UGeckoInstruction inst)
int d = inst.FD;
int b = inst.FB;
fpr.Lock(b, d);
fpr.LoadToX64(d, true, true);
fpr.BindToRegister(d, true, true);
MOVSD(XMM0, fpr.R(b));
MOVSD(fpr.R(d), XMM0);
fpr.UnlockAll();
@@ -238,7 +238,7 @@ void Jit64::fcmpx(UGeckoInstruction inst)
int crf = inst.CRFD;
fpr.Lock(a,b);
if (a != b) fpr.LoadToX64(a, true);
if (a != b) fpr.BindToRegister(a, true);
// Are we masking sNaN invalid floating point exceptions? If not this could crash if we don't handle the exception?
UCOMISD(fpr.R(a).GetSimpleReg(), fpr.R(b));
File diff suppressed because it is too large Load Diff
@@ -44,11 +44,9 @@ void Jit64::lbzx(UGeckoInstruction inst)
int a = inst.RA, b = inst.RB, d = inst.RD;
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(b);
MOV(32, R(ABI_PARAM1), gpr.R(b));
if (a)
{
gpr.Lock(a);
ADD(32, R(ABI_PARAM1), gpr.R(a));
}
@@ -57,7 +55,7 @@ void Jit64::lbzx(UGeckoInstruction inst)
MEMCHECK_START
gpr.Lock(d);
gpr.LoadToX64(d, (b == d || a == d), true);
gpr.KillImmediate(d, false, true);
MOV(32, gpr.R(d), R(EAX));
MEMCHECK_END
@@ -73,11 +71,9 @@ void Jit64::lhax(UGeckoInstruction inst)
int a = inst.RA, b = inst.RB, d = inst.RD;
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(b);
MOV(32, R(ABI_PARAM1), gpr.R(b));
if (a)
{
gpr.Lock(a);
ADD(32, R(ABI_PARAM1), gpr.R(a));
}
@@ -87,7 +83,7 @@ void Jit64::lhax(UGeckoInstruction inst)
MEMCHECK_START
gpr.Lock(d);
gpr.LoadToX64(d, (b == d || a == d), true);
gpr.KillImmediate(d, false, true);
MOV(32, gpr.R(d), R(EAX));
MEMCHECK_END
@@ -103,11 +99,9 @@ void Jit64::lwzx(UGeckoInstruction inst)
int a = inst.RA, b = inst.RB, d = inst.RD;
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(b);
MOV(32, R(ABI_PARAM1), gpr.R(b));
if (a)
{
gpr.Lock(a);
ADD(32, R(ABI_PARAM1), gpr.R(a));
}
@@ -116,7 +110,7 @@ void Jit64::lwzx(UGeckoInstruction inst)
MEMCHECK_START
gpr.Lock(d);
gpr.LoadToX64(d, (b == d || a == d), true);
gpr.KillImmediate(d, false, true);
MOV(32, gpr.R(d), R(EAX));
MEMCHECK_END
@@ -157,10 +151,10 @@ void Jit64::lXz(UGeckoInstruction inst)
// do our job at first
s32 offset = (s32)(s16)inst.SIMM_16;
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(d, a);
gpr.Lock(d);
MOV(32, R(ABI_PARAM1), gpr.R(a));
SafeLoadRegToEAX(ABI_PARAM1, 32, offset);
gpr.LoadToX64(d, false, true);
gpr.KillImmediate(d, false, true);
MOV(32, gpr.R(d), R(EAX));
gpr.UnlockAll();
gpr.UnlockAllX();
@@ -214,8 +208,8 @@ void Jit64::lXz(UGeckoInstruction inst)
{
// Fast and daring
gpr.Lock(a, d);
gpr.LoadToX64(a, true, false);
gpr.LoadToX64(d, a == d, true);
gpr.BindToRegister(a, true, false);
gpr.BindToRegister(d, a == d, true);
MOV(accessSize, gpr.R(d), MComplex(RBX, gpr.R(a).GetSimpleReg(), SCALE_1, offset));
BSWAP(32, gpr.R(d).GetSimpleReg());
gpr.UnlockAll();
@@ -223,16 +217,13 @@ void Jit64::lXz(UGeckoInstruction inst)
else
{
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(a);
gpr.LoadToX64(a, true, false);
MOV(32, R(ABI_PARAM1), gpr.R(a));
SafeLoadRegToEAX(ABI_PARAM1, accessSize, offset);
MEMCHECK_START
gpr.Lock(d);
gpr.LoadToX64(d, a == d, true);
gpr.KillImmediate(d, false, true);
MOV(32, gpr.R(d), R(EAX));
MEMCHECK_END
@@ -252,14 +243,13 @@ void Jit64::lha(UGeckoInstruction inst)
s32 offset = (s32)(s16)inst.SIMM_16;
// Safe and boring
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(a);
MOV(32, R(ABI_PARAM1), gpr.R(a));
SafeLoadRegToEAX(ABI_PARAM1, 16, offset, true);
MEMCHECK_START
gpr.Lock(d);
gpr.LoadToX64(d, d == a, true);
gpr.KillImmediate(d, false, true);
MOV(32, gpr.R(d), R(EAX));
MEMCHECK_END
@@ -280,7 +270,7 @@ void Jit64::lwzux(UGeckoInstruction inst)
return;
}
gpr.Lock(a);
gpr.LoadToX64(a, true, true);
gpr.BindToRegister(a, true, true);
ADD(32, gpr.R(a), gpr.R(b));
MOV(32, R(EAX), gpr.R(a));
SafeLoadRegToEAX(EAX, 32, 0, false);
@@ -288,7 +278,7 @@ void Jit64::lwzux(UGeckoInstruction inst)
MEMCHECK_START
gpr.Lock(d);
gpr.LoadToX64(d, b == d, true);
gpr.KillImmediate(d, false, true);
MOV(32, gpr.R(d), R(EAX));
MEMCHECK_END
@@ -392,7 +382,11 @@ void Jit64::stX(UGeckoInstruction inst)
MOV(accessSize, MDisp(ABI_PARAM1, (u32)Memory::base + (u32)offset), R(EAX));
#endif
if (update)
{
gpr.Lock(a);
gpr.KillImmediate(a, true, true);
ADD(32, gpr.R(a), Imm32(offset));
}
gpr.UnlockAllX();
return;
}
@@ -403,7 +397,7 @@ void Jit64::stX(UGeckoInstruction inst)
{
// Fast and daring - requires 64-bit
MOV(32, R(EAX), gpr.R(s));
gpr.LoadToX64(a, true, false);
gpr.BindToRegister(a, true, false);
BSWAP(32, EAX);
MOV(accessSize, MComplex(RBX, gpr.RX(a), SCALE_1, (u32)offset), R(EAX));
return;
@@ -415,7 +409,7 @@ void Jit64::stX(UGeckoInstruction inst)
gpr.FlushLockX(ECX, EDX);
gpr.Lock(s, a);
if (update && offset)
gpr.LoadToX64(a, true, true);
gpr.BindToRegister(a, true, true);
MOV(32, R(EDX), gpr.R(a));
MOV(32, R(ECX), gpr.R(s));
SafeWriteRegToReg(ECX, EDX, accessSize, offset);
@@ -453,7 +447,7 @@ void Jit64::stXx(UGeckoInstruction inst)
gpr.FlushLockX(ECX, EDX);
if (inst.SUBOP10 & 32) {
gpr.LoadToX64(a, true, true);
gpr.BindToRegister(a, true, true);
ADD(32, gpr.R(a), gpr.R(b));
MOV(32, R(EDX), gpr.R(a));
} else {
@@ -496,7 +490,7 @@ void Jit64::lmw(UGeckoInstruction inst)
{
MOV(32, R(ECX), MComplex(EBX, EAX, SCALE_1, (i - inst.RD) * 4));
BSWAP(32, ECX);
gpr.LoadToX64(i, false, true);
gpr.BindToRegister(i, false, true);
MOV(32, gpr.R(i), R(ECX));
}
gpr.UnlockAllX();
@@ -77,7 +77,7 @@ void Jit64::lfs(UGeckoInstruction inst)
MOV(32, M(&temp32), R(EAX));
fpr.Lock(d);
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
CVTSS2SD(fpr.RX(d), M(&temp32));
MOVDDUP(fpr.RX(d), fpr.R(d));
@@ -107,8 +107,8 @@ void Jit64::lfd(UGeckoInstruction inst)
gpr.Lock(a);
MOV(32, R(ABI_PARAM1), gpr.R(a));
// TODO - optimize. This has to load the previous value - upper double should stay unmodified.
fpr.LoadToX64(d, true);
fpr.Lock(d);
fpr.BindToRegister(d, true);
X64Reg xd = fpr.RX(d);
if (cpu_info.bSSSE3) {
#ifdef _M_X64
@@ -184,7 +184,7 @@ void Jit64::stfd(UGeckoInstruction inst)
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(a);
fpr.Lock(s);
gpr.LoadToX64(a, true, false);
gpr.BindToRegister(a, true, false);
LEA(32, ABI_PARAM1, MDisp(gpr.R(a).GetSimpleReg(), offset));
TEST(32, R(ABI_PARAM1), Imm32(0x0c000000));
FixupBranch not_ram = J_CC(CC_Z);
@@ -222,7 +222,7 @@ void Jit64::stfd(UGeckoInstruction inst)
#endif
} else {
#ifdef _M_X64
fpr.LoadToX64(s, true, false);
fpr.BindToRegister(s, true, false);
MOVSD(M(&temp64), fpr.RX(s));
MEMCHECK_START
@@ -233,7 +233,7 @@ void Jit64::stfd(UGeckoInstruction inst)
MEMCHECK_END
#else
fpr.LoadToX64(s, true, false);
fpr.BindToRegister(s, true, false);
MOVSD(M(&temp64), fpr.RX(s));
MEMCHECK_START
@@ -301,6 +301,7 @@ void Jit64::stfs(UGeckoInstruction inst)
{
MEMCHECK_START
gpr.KillImmediate(a, false, true);
MOV(32, gpr.R(a), R(ABI_PARAM2));
MEMCHECK_END
@@ -345,7 +346,7 @@ void Jit64::lfsx(UGeckoInstruction inst)
}
if (cpu_info.bSSSE3 && !js.memcheck) {
fpr.Lock(inst.RS);
fpr.LoadToX64(inst.RS, false, true);
fpr.BindToRegister(inst.RS, false, true);
X64Reg r = fpr.R(inst.RS).GetSimpleReg();
#ifdef _M_IX86
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
@@ -368,7 +369,7 @@ void Jit64::lfsx(UGeckoInstruction inst)
MOV(32, M(&temp32), R(EAX));
CVTSS2SD(XMM0, M(&temp32));
fpr.Lock(inst.RS);
fpr.LoadToX64(inst.RS, false, true);
fpr.BindToRegister(inst.RS, false, true);
MOVDDUP(fpr.R(inst.RS).GetSimpleReg(), R(XMM0));
MEMCHECK_END
@@ -99,8 +99,8 @@ void Jit64::psq_st(UGeckoInstruction inst)
gpr.FlushLockX(EAX, EDX);
gpr.FlushLockX(ECX);
if (update)
gpr.LoadToX64(inst.RA, true, true);
fpr.LoadToX64(inst.RS, true);
gpr.BindToRegister(inst.RA, true, true);
fpr.BindToRegister(inst.RS, true, false);
MOV(32, R(ECX), gpr.R(inst.RA));
if (offset)
ADD(32, R(ECX), Imm32((u32)offset));
@@ -159,8 +159,8 @@ void Jit64::psq_l(UGeckoInstruction inst)
gpr.FlushLockX(EAX, EDX);
gpr.FlushLockX(ECX);
gpr.LoadToX64(inst.RA, true, true);
fpr.LoadToX64(inst.RS, false, true);
gpr.BindToRegister(inst.RA, true, update && offset);
fpr.BindToRegister(inst.RS, false, true);
if (offset)
LEA(32, ECX, MDisp(gpr.RX(inst.RA), offset));
else
@@ -50,7 +50,7 @@ void Jit64::ps_mr(UGeckoInstruction inst)
int b = inst.FB;
if (d == b)
return;
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
MOVAPD(fpr.RX(d), fpr.R(b));
}
@@ -72,8 +72,8 @@ void Jit64::ps_sel(UGeckoInstruction inst)
fpr.FlushLockX(XMM7);
fpr.FlushLockX(XMM6);
fpr.Lock(a, b, c, d);
fpr.LoadToX64(a, true, false);
fpr.LoadToX64(d, false, true);
fpr.BindToRegister(a, true, false);
fpr.BindToRegister(d, false, true);
// BLENDPD would have been nice...
MOVAPD(XMM7, fpr.R(a));
CMPPD(XMM7, M((void*)psZeroZero), 1); //less-than = 111111
@@ -99,12 +99,12 @@ void Jit64::ps_sign(UGeckoInstruction inst)
fpr.Lock(d, b);
if (d != b)
{
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
MOVAPD(fpr.RX(d), fpr.R(b));
}
else
{
fpr.LoadToX64(d, true);
fpr.BindToRegister(d, true);
}
switch (inst.SUBOP10)
@@ -133,6 +133,7 @@ void Jit64::ps_rsqrte(UGeckoInstruction inst)
int d = inst.FD;
int b = inst.FB;
fpr.Lock(d, b);
fpr.BindToRegister(d, (d == b), true);
SQRTPD(XMM0, fpr.R(b));
MOVAPD(XMM1, M((void*)&psOneOne));
DIVPD(XMM1, R(XMM0));
@@ -161,24 +162,24 @@ void Jit64::tri_op(int d, int a, int b, bool reversible, void (XEmitter::*op)(X6
if (d == a)
{
fpr.LoadToX64(d, true);
fpr.BindToRegister(d, true);
(this->*op)(fpr.RX(d), fpr.R(b));
}
else if (d == b && reversible)
{
fpr.LoadToX64(d, true);
fpr.BindToRegister(d, true);
(this->*op)(fpr.RX(d), fpr.R(a));
}
else if (a != d && b != d)
{
//sources different from d, can use rather quick solution
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
MOVAPD(fpr.RX(d), fpr.R(a));
(this->*op)(fpr.RX(d), fpr.R(b));
}
else if (b != d)
{
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
MOVAPD(XMM0, fpr.R(b));
MOVAPD(fpr.RX(d), fpr.R(a));
(this->*op)(fpr.RX(d), Gen::R(XMM0));
@@ -187,7 +188,7 @@ void Jit64::tri_op(int d, int a, int b, bool reversible, void (XEmitter::*op)(X6
{
MOVAPD(XMM0, fpr.R(a));
MOVAPD(XMM1, fpr.R(b));
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
(this->*op)(XMM0, Gen::R(XMM1));
MOVAPD(fpr.RX(d), Gen::R(XMM0));
}
@@ -231,7 +232,7 @@ void Jit64::ps_sum(UGeckoInstruction inst)
int b = inst.FB;
int c = inst.FC;
fpr.Lock(a,b,c,d);
fpr.LoadToX64(d, d == a || d == b || d == c, true);
fpr.BindToRegister(d, d == a || d == b || d == c, true);
switch (inst.SUBOP5)
{
case 10:
@@ -271,7 +272,7 @@ void Jit64::ps_muls(UGeckoInstruction inst)
int a = inst.FA;
int c = inst.FC;
fpr.Lock(a, c, d);
fpr.LoadToX64(d, d == a || d == c, true);
fpr.BindToRegister(d, d == a || d == c, true);
switch (inst.SUBOP5)
{
case 12:
@@ -329,7 +330,7 @@ void Jit64::ps_mergeXX(UGeckoInstruction inst)
default:
_assert_msg_(DYNA_REC, 0, "ps_merge - invalid op");
}
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
MOVAPD(fpr.RX(d), Gen::R(XMM0));
fpr.UnlockAll();
}
@@ -387,7 +388,7 @@ void Jit64::ps_maddXX(UGeckoInstruction inst)
//fpr.UnlockAll();
return;
}
fpr.LoadToX64(d, false);
fpr.BindToRegister(d, false);
MOVAPD(fpr.RX(d), Gen::R(XMM0));
ForceSinglePrecisionP(fpr.RX(d));
fpr.UnlockAll();
@@ -72,8 +72,11 @@ void Jit64::mtspr(UGeckoInstruction inst)
}
// OK, this is easy.
gpr.Lock(d);
gpr.LoadToX64(d, true);
if (!gpr.R(d).IsImm())
{
gpr.Lock(d);
gpr.BindToRegister(d, true, false);
}
MOV(32, M(&PowerPC::ppcState.spr[iIndex]), gpr.R(d));
gpr.UnlockAll();
}
@@ -98,7 +101,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
// fall through
default:
gpr.Lock(d);
gpr.LoadToX64(d, false);
gpr.BindToRegister(d, false);
MOV(32, gpr.R(d), M(&PowerPC::ppcState.spr[iIndex]));
gpr.UnlockAll();
break;
@@ -113,8 +116,13 @@ void Jit64::mtmsr(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(SystemRegisters)
gpr.LoadToX64(inst.RS, true, false);
if (!gpr.R(inst.RS).IsImm())
{
gpr.Lock(inst.RS);
gpr.BindToRegister(inst.RS, true, false);
}
MOV(32, M(&MSR), gpr.R(inst.RS));
gpr.UnlockAll();
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
WriteExit(js.compilerPC + 4, 0);
@@ -127,8 +135,10 @@ void Jit64::mfmsr(UGeckoInstruction inst)
INSTRUCTION_START
JITDISABLE(SystemRegisters)
//Privileged?
gpr.LoadToX64(inst.RD, false);
gpr.Lock(inst.RD);
gpr.BindToRegister(inst.RD, false, true);
MOV(32, gpr.R(inst.RD), M(&MSR));
gpr.UnlockAll();
}
void Jit64::mftb(UGeckoInstruction inst)
@@ -144,7 +154,8 @@ void Jit64::mfcr(UGeckoInstruction inst)
JITDISABLE(SystemRegisters)
// USES_CR
int d = inst.RD;
gpr.LoadToX64(d, false, true);
gpr.Lock(d);
gpr.KillImmediate(d, false, true);
MOV(8, R(EAX), M(&PowerPC::ppcState.cr_fast[0]));
for (int i = 1; i < 8; i++) {
SHL(32, R(EAX), Imm8(4));
@@ -175,7 +186,8 @@ void Jit64::mtcrf(UGeckoInstruction inst)
}
else
{
gpr.LoadToX64(inst.RS, true);
gpr.Lock(inst.RS);
gpr.BindToRegister(inst.RS, true, false);
for (int i = 0; i < 8; i++)
{
if ((crm & (0x80 >> i)) != 0)
@@ -186,6 +198,7 @@ void Jit64::mtcrf(UGeckoInstruction inst)
MOV(8, M(&PowerPC::ppcState.cr_fast[i]), R(EAX));
}
}
gpr.UnlockAll();
}
}
}