mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
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:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user