Merge pull request #13266 from JosJuice/jitarm64-cr-bits-1-to-31
JitArm64: Fix creqv/crorc setting eq bit
This commit is contained in:
commit
af87d60b6c
|
@ -356,7 +356,10 @@ protected:
|
|||
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
|
||||
|
||||
void GetCRFieldBit(int field, int bit, Arm64Gen::ARM64Reg out);
|
||||
void SetCRFieldBit(int field, int bit, Arm64Gen::ARM64Reg in, bool negate = false);
|
||||
// This assumes that all bits except for bit 0 (LSB) are set to 0. But if bits_1_to_31_are_set
|
||||
// equals true, it instead assumes that all of bits 1 to 31 are set.
|
||||
void SetCRFieldBit(int field, int bit, Arm64Gen::ARM64Reg in, bool negate = false,
|
||||
bool bits_1_to_31_are_set = false);
|
||||
void ClearCRFieldBit(int field, int bit);
|
||||
void SetCRFieldBit(int field, int bit);
|
||||
void FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg);
|
||||
|
|
|
@ -50,7 +50,8 @@ void JitArm64::GetCRFieldBit(int field, int bit, ARM64Reg out)
|
|||
}
|
||||
}
|
||||
|
||||
void JitArm64::SetCRFieldBit(int field, int bit, ARM64Reg in, bool negate)
|
||||
void JitArm64::SetCRFieldBit(int field, int bit, ARM64Reg in, bool negate,
|
||||
bool bits_1_to_31_are_set)
|
||||
{
|
||||
gpr.BindCRToRegister(field, true);
|
||||
ARM64Reg CR = gpr.CR(field);
|
||||
|
@ -70,7 +71,9 @@ void JitArm64::SetCRFieldBit(int field, int bit, ARM64Reg in, bool negate)
|
|||
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
|
||||
ORR(CR, CR, in);
|
||||
if (!negate)
|
||||
EOR(CR, CR, LogicalImm(1ULL << 0, GPRSize::B64));
|
||||
EOR(CR, CR, LogicalImm(bits_1_to_31_are_set ? 0xFFFF'FFFFULL : 1ULL, GPRSize::B64));
|
||||
else if (bits_1_to_31_are_set)
|
||||
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0001ULL, GPRSize::B64));
|
||||
break;
|
||||
|
||||
case PowerPC::CR_GT_BIT: // set bit 63 to !input
|
||||
|
@ -632,8 +635,12 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||
}
|
||||
}
|
||||
|
||||
// crnor or crnand
|
||||
const bool negate_result = inst.SUBOP10 == 33 || inst.SUBOP10 == 225;
|
||||
const u32 crbd_bit = 3 - (inst.CRBD & 3);
|
||||
// crnor, crnand and sometimes creqv
|
||||
const bool negate_result =
|
||||
inst.SUBOP10 == 33 || inst.SUBOP10 == 225 ||
|
||||
(inst.SUBOP10 == 289 && (crbd_bit == PowerPC::CR_EQ_BIT || crbd_bit == PowerPC::CR_GT_BIT));
|
||||
bool bits_1_to_31_are_set = false;
|
||||
|
||||
auto WA = gpr.GetScopedReg();
|
||||
ARM64Reg XA = EncodeRegTo64(WA);
|
||||
|
@ -661,7 +668,17 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||
break;
|
||||
|
||||
case 289: // creqv: ~(A ^ B) = A ^ ~B
|
||||
EON(XA, XA, XB);
|
||||
// Both of these two implementations are equally correct, but which one is more efficient
|
||||
// depends on which bit we're going to set in CRBD
|
||||
if (negate_result)
|
||||
{
|
||||
EOR(XA, XA, XB);
|
||||
}
|
||||
else
|
||||
{
|
||||
EON(WA, WA, WB);
|
||||
bits_1_to_31_are_set = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 33: // crnor: ~(A || B)
|
||||
|
@ -670,13 +687,14 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||
break;
|
||||
|
||||
case 417: // crorc: A || ~B
|
||||
ORN(XA, XA, XB);
|
||||
ORN(WA, WA, WB);
|
||||
bits_1_to_31_are_set = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Store result bit in CRBD
|
||||
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, negate_result);
|
||||
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), XA, negate_result, bits_1_to_31_are_set);
|
||||
}
|
||||
|
||||
void JitArm64::mfcr(UGeckoInstruction inst)
|
||||
|
|
Loading…
Reference in New Issue