DSPJit: Fix xA and xB
This commit is contained in:
parent
a30a186d30
commit
7cd1b2c4d1
|
@ -54,12 +54,25 @@ void DSPEmitter::ReJitConditional(const UDSPInstruction opc,
|
||||||
break;
|
break;
|
||||||
case 0xa: // ?
|
case 0xa: // ?
|
||||||
case 0xb: // ?
|
case 0xb: // ?
|
||||||
|
// We want to test this expression, which corresponds to xB:
|
||||||
|
// (!(IsSRFlagSet(SR_OVER_S32) || IsSRFlagSet(SR_TOP2BITS))) || IsSRFlagSet(SR_ARITH_ZERO)
|
||||||
|
// The xB expression is used due to even instructions (i.e. xA) looking for the expression to
|
||||||
|
// evaluate to false, while odd ones look for it to be true.
|
||||||
|
|
||||||
|
// Since SR_OVER_S32 is bit 4 (0x10) and SR_TOP2BITS is bit 5 (0x20),
|
||||||
|
// set EDX to 2*EAX, so that SR_OVER_S32 is in bit 5 of EDX.
|
||||||
LEA(16, EDX, MRegSum(EAX, EAX));
|
LEA(16, EDX, MRegSum(EAX, EAX));
|
||||||
OR(16, R(EAX), R(EDX));
|
// Now OR them together, so bit 5 of EDX is
|
||||||
SHL(16, R(EDX), Imm8(3));
|
// (IsSRFlagSet(SR_OVER_S32) || IsSRFlagSet(SR_TOP2BITS))
|
||||||
NOT(16, R(EAX));
|
OR(16, R(EDX), R(EAX));
|
||||||
OR(16, R(EAX), R(EDX));
|
// EDX bit 5 is !(IsSRFlagSet(SR_OVER_S32) || IsSRFlagSet(SR_TOP2BITS))
|
||||||
TEST(16, R(EAX), Imm16(0x20));
|
NOT(16, R(EDX));
|
||||||
|
// SR_ARITH_ZERO is bit 2 (0x04). We want that in bit 5, so shift left by 3.
|
||||||
|
SHL(16, R(EAX), Imm8(3));
|
||||||
|
// Bit 5 of EAX is IsSRFlagSet(SR_OVER_S32), so or-ing EDX with EAX gives our target expression.
|
||||||
|
OR(16, R(EDX), R(EAX));
|
||||||
|
// Test bit 5
|
||||||
|
TEST(16, R(EDX), Imm16(0x20));
|
||||||
break;
|
break;
|
||||||
case 0xc: // LNZ - Logic Not Zero
|
case 0xc: // LNZ - Logic Not Zero
|
||||||
case 0xd: // LZ - Logic Zero
|
case 0xd: // LZ - Logic Zero
|
||||||
|
@ -70,8 +83,14 @@ void DSPEmitter::ReJitConditional(const UDSPInstruction opc,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DSPJitRegCache c1(m_gpr);
|
DSPJitRegCache c1(m_gpr);
|
||||||
FixupBranch skip_code =
|
CCFlags flag;
|
||||||
cond == 0xe ? J_CC(CC_E, true) : J_CC((CCFlags)(CC_NE - (cond & 1)), true);
|
if (cond == 0xe) // Overflow, special case as there is no inverse case
|
||||||
|
flag = CC_Z;
|
||||||
|
else if ((cond & 1) == 0) // Even conditions run if the bit is zero, so jump if it IS NOT zero
|
||||||
|
flag = CC_NZ;
|
||||||
|
else // Odd conditions run if the bit IS NOT zero, so jump if it IS zero
|
||||||
|
flag = CC_Z;
|
||||||
|
FixupBranch skip_code = J_CC(flag, true);
|
||||||
(this->*conditional_fn)(opc);
|
(this->*conditional_fn)(opc);
|
||||||
m_gpr.FlushRegs(c1);
|
m_gpr.FlushRegs(c1);
|
||||||
SetJumpTarget(skip_code);
|
SetJumpTarget(skip_code);
|
||||||
|
|
Loading…
Reference in New Issue