mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-08 13:43:33 +01:00
Merge pull request #9770 from JosJuice/jits-accidental-gt
Jits: Fix accidentally setting GT in CR when clearing EQ
This commit is contained in:
commit
89af7b82f2
@ -116,6 +116,7 @@ public:
|
|||||||
void SetCRFieldBit(int field, int bit, Gen::X64Reg in);
|
void SetCRFieldBit(int field, int bit, Gen::X64Reg in);
|
||||||
void ClearCRFieldBit(int field, int bit);
|
void ClearCRFieldBit(int field, int bit);
|
||||||
void SetCRFieldBit(int field, int bit);
|
void SetCRFieldBit(int field, int bit);
|
||||||
|
void FixGTBeforeSettingCRFieldBit(Gen::X64Reg reg);
|
||||||
|
|
||||||
// Generates a branch that will check if a given bit of a CR register part
|
// Generates a branch that will check if a given bit of a CR register part
|
||||||
// is set or not.
|
// is set or not.
|
||||||
|
@ -54,16 +54,8 @@ void Jit64::SetCRFieldBit(int field, int bit, X64Reg in)
|
|||||||
MOV(64, R(RSCRATCH2), CROffset(field));
|
MOV(64, R(RSCRATCH2), CROffset(field));
|
||||||
MOVZX(32, 8, in, R(in));
|
MOVZX(32, 8, in, R(in));
|
||||||
|
|
||||||
// Gross but necessary; if the input is totally zero and we set SO or LT,
|
|
||||||
// or even just add the (1<<32), GT will suddenly end up set without us
|
|
||||||
// intending to. This can break actual games, so fix it up.
|
|
||||||
if (bit != PowerPC::CR_GT_BIT)
|
if (bit != PowerPC::CR_GT_BIT)
|
||||||
{
|
FixGTBeforeSettingCRFieldBit(RSCRATCH2);
|
||||||
TEST(64, R(RSCRATCH2), R(RSCRATCH2));
|
|
||||||
FixupBranch dont_clear_gt = J_CC(CC_NZ);
|
|
||||||
BTS(64, R(RSCRATCH2), Imm8(63));
|
|
||||||
SetJumpTarget(dont_clear_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bit)
|
switch (bit)
|
||||||
{
|
{
|
||||||
@ -107,7 +99,10 @@ void Jit64::ClearCRFieldBit(int field, int bit)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PowerPC::CR_EQ_BIT:
|
case PowerPC::CR_EQ_BIT:
|
||||||
OR(64, CROffset(field), Imm8(1));
|
MOV(64, R(RSCRATCH), CROffset(field));
|
||||||
|
FixGTBeforeSettingCRFieldBit(RSCRATCH);
|
||||||
|
OR(64, R(RSCRATCH), Imm8(1));
|
||||||
|
MOV(64, CROffset(field), R(RSCRATCH));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PowerPC::CR_GT_BIT:
|
case PowerPC::CR_GT_BIT:
|
||||||
@ -126,12 +121,7 @@ void Jit64::SetCRFieldBit(int field, int bit)
|
|||||||
{
|
{
|
||||||
MOV(64, R(RSCRATCH), CROffset(field));
|
MOV(64, R(RSCRATCH), CROffset(field));
|
||||||
if (bit != PowerPC::CR_GT_BIT)
|
if (bit != PowerPC::CR_GT_BIT)
|
||||||
{
|
FixGTBeforeSettingCRFieldBit(RSCRATCH);
|
||||||
TEST(64, R(RSCRATCH), R(RSCRATCH));
|
|
||||||
FixupBranch dont_clear_gt = J_CC(CC_NZ);
|
|
||||||
BTS(64, R(RSCRATCH), Imm8(63));
|
|
||||||
SetJumpTarget(dont_clear_gt);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bit)
|
switch (bit)
|
||||||
{
|
{
|
||||||
@ -157,6 +147,17 @@ void Jit64::SetCRFieldBit(int field, int bit)
|
|||||||
MOV(64, CROffset(field), R(RSCRATCH));
|
MOV(64, CROffset(field), R(RSCRATCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::FixGTBeforeSettingCRFieldBit(Gen::X64Reg reg)
|
||||||
|
{
|
||||||
|
// Gross but necessary; if the input is totally zero and we set SO or LT,
|
||||||
|
// or even just add the (1<<32), GT will suddenly end up set without us
|
||||||
|
// intending to. This can break actual games, so fix it up.
|
||||||
|
TEST(64, R(reg), R(reg));
|
||||||
|
FixupBranch dont_clear_gt = J_CC(CC_NZ);
|
||||||
|
BTS(64, R(reg), Imm8(63));
|
||||||
|
SetJumpTarget(dont_clear_gt);
|
||||||
|
}
|
||||||
|
|
||||||
FixupBranch Jit64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
|
FixupBranch Jit64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
|
||||||
{
|
{
|
||||||
switch (bit)
|
switch (bit)
|
||||||
|
@ -255,6 +255,7 @@ protected:
|
|||||||
void FakeLKExit(u32 exit_address_after_return);
|
void FakeLKExit(u32 exit_address_after_return);
|
||||||
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
|
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
|
||||||
|
|
||||||
|
void FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg);
|
||||||
Arm64Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set);
|
Arm64Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set);
|
||||||
|
|
||||||
void ComputeRC0(Arm64Gen::ARM64Reg reg);
|
void ComputeRC0(Arm64Gen::ARM64Reg reg);
|
||||||
|
@ -36,6 +36,19 @@ FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JitArm64::FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg)
|
||||||
|
{
|
||||||
|
// Gross but necessary; if the input is totally zero and we set SO or LT,
|
||||||
|
// or even just add the (1<<32), GT will suddenly end up set without us
|
||||||
|
// intending to. This can break actual games, so fix it up.
|
||||||
|
ARM64Reg WA = gpr.GetReg();
|
||||||
|
ARM64Reg XA = EncodeRegTo64(WA);
|
||||||
|
ORR(XA, reg, 64 - 63, 0, true); // XB | 1<<63
|
||||||
|
CMP(reg, ARM64Reg::ZR);
|
||||||
|
CSEL(reg, reg, XA, CC_NEQ);
|
||||||
|
gpr.Unlock(WA);
|
||||||
|
}
|
||||||
|
|
||||||
void JitArm64::mtmsr(UGeckoInstruction inst)
|
void JitArm64::mtmsr(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
@ -432,6 +445,7 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PowerPC::CR_EQ_BIT:
|
case PowerPC::CR_EQ_BIT:
|
||||||
|
FixGTBeforeSettingCRFieldBit(XA);
|
||||||
ORR(XA, XA, 0, 0, true); // XA | 1<<0
|
ORR(XA, XA, 0, 0, true); // XA | 1<<0
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -457,14 +471,7 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||||||
ARM64Reg XA = gpr.CR(field);
|
ARM64Reg XA = gpr.CR(field);
|
||||||
|
|
||||||
if (bit != PowerPC::CR_GT_BIT)
|
if (bit != PowerPC::CR_GT_BIT)
|
||||||
{
|
FixGTBeforeSettingCRFieldBit(XA);
|
||||||
ARM64Reg WB = gpr.GetReg();
|
|
||||||
ARM64Reg XB = EncodeRegTo64(WB);
|
|
||||||
ORR(XB, XA, 64 - 63, 0, true); // XA | 1<<63
|
|
||||||
CMP(XA, ARM64Reg::ZR);
|
|
||||||
CSEL(XA, XA, XB, CC_NEQ);
|
|
||||||
gpr.Unlock(WB);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bit)
|
switch (bit)
|
||||||
{
|
{
|
||||||
@ -569,18 +576,8 @@ void JitArm64::crXXX(UGeckoInstruction inst)
|
|||||||
gpr.BindCRToRegister(field, true);
|
gpr.BindCRToRegister(field, true);
|
||||||
XB = gpr.CR(field);
|
XB = gpr.CR(field);
|
||||||
|
|
||||||
// Gross but necessary; if the input is totally zero and we set SO or LT,
|
|
||||||
// or even just add the (1<<32), GT will suddenly end up set without us
|
|
||||||
// intending to. This can break actual games, so fix it up.
|
|
||||||
if (bit != PowerPC::CR_GT_BIT)
|
if (bit != PowerPC::CR_GT_BIT)
|
||||||
{
|
FixGTBeforeSettingCRFieldBit(XB);
|
||||||
ARM64Reg WC = gpr.GetReg();
|
|
||||||
ARM64Reg XC = EncodeRegTo64(WC);
|
|
||||||
ORR(XC, XB, 64 - 63, 0, true); // XB | 1<<63
|
|
||||||
CMP(XB, ARM64Reg::ZR);
|
|
||||||
CSEL(XB, XB, XC, CC_NEQ);
|
|
||||||
gpr.Unlock(WC);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bit)
|
switch (bit)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user