[ARM] Minor cleanup to lXX and stX. Fixes a bug.

Fixes an issue in lXX where if the instruction was an update instruction and was a register address offset that we would add garbage values to the
writeback register.
Does some minor cleanups as well which save a few instructions here and there.
This commit is contained in:
Ryan Houdek 2014-04-10 07:10:09 +00:00 committed by Ryan Houdek
parent 4deb8f4011
commit d17d5ead07
1 changed files with 41 additions and 32 deletions

View File

@ -103,11 +103,18 @@ void JitArm::SafeStoreFromReg(bool fastmem, s32 dest, u32 value, s32 regOffset,
} }
MOV(rB, RS); MOV(rB, RS);
if (regOffset == -1) if (regOffset == -1)
{
MOVI2R(rC, offset); MOVI2R(rC, offset);
else
MOV(rC, RB);
if (dest != -1) if (dest != -1)
ADD(rC, rC, RA); ADD(rC, rC, RA);
}
else
{
if (dest != -1)
ADD(rC, RA, RB);
else
MOV(rC, RB);
}
PUSH(4, R0, R1, R2, R3); PUSH(4, R0, R1, R2, R3);
MOV(R0, rB); MOV(R0, rB);
@ -126,7 +133,6 @@ void JitArm::stX(UGeckoInstruction inst)
s32 offset = inst.SIMM_16; s32 offset = inst.SIMM_16;
u32 accessSize = 0; u32 accessSize = 0;
s32 regOffset = -1; s32 regOffset = -1;
bool zeroA = true;
bool update = false; bool update = false;
bool fastmem = false; bool fastmem = false;
switch (inst.OPCD) switch (inst.OPCD)
@ -140,7 +146,6 @@ void JitArm::stX(UGeckoInstruction inst)
switch (inst.SUBOP10) switch (inst.SUBOP10)
{ {
case 183: // stwux case 183: // stwux
zeroA = false;
update = true; update = true;
case 151: // stwx case 151: // stwx
fastmem = true; fastmem = true;
@ -148,14 +153,12 @@ void JitArm::stX(UGeckoInstruction inst)
regOffset = b; regOffset = b;
break; break;
case 247: // stbux case 247: // stbux
zeroA = false;
update = true; update = true;
case 215: // stbx case 215: // stbx
accessSize = 8; accessSize = 8;
regOffset = b; regOffset = b;
break; break;
case 439: // sthux case 439: // sthux
zeroA = false;
update = true; update = true;
case 407: // sthx case 407: // sthx
accessSize = 16; accessSize = 16;
@ -175,7 +178,7 @@ void JitArm::stX(UGeckoInstruction inst)
accessSize = 8; accessSize = 8;
break; break;
} }
SafeStoreFromReg(fastmem, zeroA ? a ? a : -1 : a, s, regOffset, accessSize, offset); SafeStoreFromReg(fastmem, update ? a : (a ? a : -1), s, regOffset, accessSize, offset);
if (update) if (update)
{ {
ARMReg rA = gpr.GetReg(); ARMReg rA = gpr.GetReg();
@ -185,21 +188,27 @@ void JitArm::stX(UGeckoInstruction inst)
RB = gpr.R(regOffset); RB = gpr.R(regOffset);
// Check for DSI exception prior to writing back address // Check for DSI exception prior to writing back address
LDR(rA, R9, PPCSTATE_OFF(Exceptions)); LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI); TST(rA, EXCEPTION_DSI);
FixupBranch DoNotWrite = B_CC(CC_EQ); FixupBranch DoNotWrite = B_CC(CC_NEQ);
if (a) if (a)
{ {
if (regOffset == -1) if (regOffset == -1)
{
MOVI2R(rA, offset); MOVI2R(rA, offset);
else
MOV(rA, RB);
ADD(RA, RA, rA); ADD(RA, RA, rA);
} }
else else
{
ADD(RA, RA, RB);
}
}
else
{
if (regOffset == -1) if (regOffset == -1)
MOVI2R(RA, (u32)offset); MOVI2R(RA, (u32)offset);
else else
MOV(RA, RB); MOV(RA, RB);
}
SetJumpTarget(DoNotWrite); SetJumpTarget(DoNotWrite);
gpr.Unlock(rA); gpr.Unlock(rA);
} }
@ -262,12 +271,18 @@ void JitArm::SafeLoadToReg(bool fastmem, u32 dest, s32 addr, s32 offsetReg, int
ARMReg rB = gpr.GetReg(); ARMReg rB = gpr.GetReg();
if (offsetReg == -1) if (offsetReg == -1)
{
MOVI2R(rA, offset); MOVI2R(rA, offset);
else
MOV(rA, gpr.R(offsetReg));
if (addr != -1) if (addr != -1)
ADD(rA, rA, gpr.R(addr)); ADD(rA, rA, gpr.R(addr));
}
else
{
if (addr != -1)
ADD(rA, gpr.R(addr), gpr.R(offsetReg));
else
MOV(rA, gpr.R(offsetReg));
}
switch (accessSize) switch (accessSize)
{ {
@ -308,7 +323,6 @@ void JitArm::lXX(UGeckoInstruction inst)
s32 offset = inst.SIMM_16; s32 offset = inst.SIMM_16;
u32 accessSize = 0; u32 accessSize = 0;
s32 offsetReg = -1; s32 offsetReg = -1;
bool zeroA = true;
bool update = false; bool update = false;
bool signExtend = false; bool signExtend = false;
bool reverse = false; bool reverse = false;
@ -320,28 +334,24 @@ void JitArm::lXX(UGeckoInstruction inst)
switch (inst.SUBOP10) switch (inst.SUBOP10)
{ {
case 55: // lwzux case 55: // lwzux
zeroA = false;
update = true; update = true;
case 23: // lwzx case 23: // lwzx
accessSize = 32; accessSize = 32;
offsetReg = b; offsetReg = b;
break; break;
case 119: //lbzux case 119: //lbzux
zeroA = false;
update = true; update = true;
case 87: // lbzx case 87: // lbzx
accessSize = 8; accessSize = 8;
offsetReg = b; offsetReg = b;
break; break;
case 311: // lhzux case 311: // lhzux
zeroA = false;
update = true; update = true;
case 279: // lhzx case 279: // lhzx
accessSize = 16; accessSize = 16;
offsetReg = b; offsetReg = b;
break; break;
case 375: // lhaux case 375: // lhaux
zeroA = false;
update = true; update = true;
case 343: // lhax case 343: // lhax
accessSize = 16; accessSize = 16;
@ -359,28 +369,24 @@ void JitArm::lXX(UGeckoInstruction inst)
} }
break; break;
case 33: // lwzu case 33: // lwzu
zeroA = false;
update = true; update = true;
case 32: // lwz case 32: // lwz
fastmem = true; fastmem = true;
accessSize = 32; accessSize = 32;
break; break;
case 35: // lbzu case 35: // lbzu
zeroA = false;
update = true; update = true;
case 34: // lbz case 34: // lbz
fastmem = true; fastmem = true;
accessSize = 8; accessSize = 8;
break; break;
case 41: // lhzu case 41: // lhzu
zeroA = false;
update = true; update = true;
case 40: // lhz case 40: // lhz
fastmem = true; fastmem = true;
accessSize = 16; accessSize = 16;
break; break;
case 43: // lhau case 43: // lhau
zeroA = false;
update = true; update = true;
case 42: // lha case 42: // lha
signExtend = true; signExtend = true;
@ -392,21 +398,25 @@ void JitArm::lXX(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg(false); ARMReg rA = gpr.GetReg(false);
LDR(rA, R9, PPCSTATE_OFF(Exceptions)); LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI); TST(rA, EXCEPTION_DSI);
FixupBranch DoNotLoad = B_CC(CC_EQ); FixupBranch DoNotLoad = B_CC(CC_NEQ);
SafeLoadToReg(fastmem, d, zeroA ? a ? a : -1 : a, offsetReg, accessSize, offset, signExtend, reverse); SafeLoadToReg(fastmem, d, update ? a : (a ? a : -1), offsetReg, accessSize, offset, signExtend, reverse);
if (update) if (update)
{ {
rA = gpr.GetReg(false);
ARMReg RA = gpr.R(a); ARMReg RA = gpr.R(a);
if (offsetReg == -1) if (offsetReg == -1)
{
rA = gpr.GetReg(false);
MOVI2R(rA, offset); MOVI2R(rA, offset);
else
MOV(RA, gpr.R(offsetReg));
ADD(RA, RA, rA); ADD(RA, RA, rA);
} }
else
{
ADD(RA, RA, gpr.R(offsetReg));
}
}
SetJumpTarget(DoNotLoad); SetJumpTarget(DoNotLoad);
@ -439,7 +449,6 @@ void JitArm::lXX(UGeckoInstruction inst)
//js.compilerPC += 8; //js.compilerPC += 8;
return; return;
} }
} }
// Some games use this heavily in video codecs // Some games use this heavily in video codecs