diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 0e98981a46..e6e857b2fb 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -136,6 +136,7 @@ public: void ClearCRFieldBit(int field, int bit); void SetCRFieldBit(int field, int bit); void FixGTBeforeSettingCRFieldBit(Gen::X64Reg reg); + void FixGTBeforeSettingEQ(Gen::X64Reg reg); // Generates a branch that will check if a given bit of a CR register part // is set or not. Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set = true); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index edab5ba3ea..136e24f308 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -57,21 +57,19 @@ void Jit64::SetCRFieldBit(int field, int bit, X64Reg in) MOV(64, R(RSCRATCH2), CROffset(field)); MOVZX(32, 8, in, R(in)); - if (bit != PowerPC::CR_GT_BIT) - FixGTBeforeSettingCRFieldBit(RSCRATCH2); - switch (bit) { case PowerPC::CR_SO_BIT: // set bit 59 to input + FixGTBeforeSettingCRFieldBit(RSCRATCH2); BTR(64, R(RSCRATCH2), Imm8(PowerPC::CR_EMU_SO_BIT)); SHL(64, R(in), Imm8(PowerPC::CR_EMU_SO_BIT)); OR(64, R(RSCRATCH2), R(in)); break; case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input + FixGTBeforeSettingEQ(RSCRATCH2); SHR(64, R(RSCRATCH2), Imm8(32)); SHL(64, R(RSCRATCH2), Imm8(32)); - BTS(64, R(RSCRATCH2), Imm8(32)); XOR(32, R(in), Imm8(1)); OR(64, R(RSCRATCH2), R(in)); break; @@ -85,6 +83,7 @@ void Jit64::SetCRFieldBit(int field, int bit, X64Reg in) break; case PowerPC::CR_LT_BIT: // set bit 62 to input + FixGTBeforeSettingCRFieldBit(RSCRATCH2); BTR(64, R(RSCRATCH2), Imm8(PowerPC::CR_EMU_LT_BIT)); SHL(64, R(in), Imm8(PowerPC::CR_EMU_LT_BIT)); OR(64, R(RSCRATCH2), R(in)); @@ -124,19 +123,18 @@ void Jit64::ClearCRFieldBit(int field, int bit) void Jit64::SetCRFieldBit(int field, int bit) { MOV(64, R(RSCRATCH), CROffset(field)); - if (bit != PowerPC::CR_GT_BIT) - FixGTBeforeSettingCRFieldBit(RSCRATCH); switch (bit) { case PowerPC::CR_SO_BIT: + FixGTBeforeSettingCRFieldBit(RSCRATCH); BTS(64, R(RSCRATCH), Imm8(PowerPC::CR_EMU_SO_BIT)); break; case PowerPC::CR_EQ_BIT: + FixGTBeforeSettingEQ(RSCRATCH); SHR(64, R(RSCRATCH), Imm8(32)); SHL(64, R(RSCRATCH), Imm8(32)); - BTS(64, R(RSCRATCH), Imm8(32)); break; case PowerPC::CR_GT_BIT: @@ -145,6 +143,7 @@ void Jit64::SetCRFieldBit(int field, int bit) break; case PowerPC::CR_LT_BIT: + FixGTBeforeSettingCRFieldBit(RSCRATCH); BTS(64, R(RSCRATCH), Imm8(PowerPC::CR_EMU_LT_BIT)); break; } @@ -164,6 +163,14 @@ void Jit64::FixGTBeforeSettingCRFieldBit(Gen::X64Reg reg) SetJumpTarget(dont_clear_gt); } +void Jit64::FixGTBeforeSettingEQ(Gen::X64Reg reg) +{ + TEST(32, R(reg), R(reg)); + FixupBranch dont_set_bit_32 = J_CC(CC_Z); + BTS(64, R(reg), Imm8(63)); + SetJumpTarget(dont_set_bit_32); +} + FixupBranch Jit64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set) { switch (bit) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 3f9c471e11..5c27eaa928 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -360,6 +360,7 @@ protected: void ClearCRFieldBit(int field, int bit); void SetCRFieldBit(int field, int bit); void FixGTBeforeSettingCRFieldBit(Arm64Gen::ARM64Reg reg); + void FixGTBeforeSettingEQ(Arm64Gen::ARM64Reg reg); Arm64Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set); void UpdateFPExceptionSummary(Arm64Gen::ARM64Reg fpscr); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 0a6139c177..1a08f4105f 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -55,20 +55,18 @@ void JitArm64::SetCRFieldBit(int field, int bit, ARM64Reg in, bool negate) gpr.BindCRToRegister(field, true); ARM64Reg CR = gpr.CR(field); - if (bit != PowerPC::CR_GT_BIT) - FixGTBeforeSettingCRFieldBit(CR); - switch (bit) { case PowerPC::CR_SO_BIT: // set bit 59 to input + FixGTBeforeSettingCRFieldBit(CR); BFI(CR, in, PowerPC::CR_EMU_SO_BIT, 1); if (negate) EOR(CR, CR, LogicalImm(1ULL << PowerPC::CR_EMU_SO_BIT, GPRSize::B64)); break; case PowerPC::CR_EQ_BIT: // clear low 32 bits, set bit 0 to !input + FixGTBeforeSettingEQ(CR); AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64)); - ORR(CR, CR, LogicalImm(1ULL << 32, GPRSize::B64)); ORR(CR, CR, in); if (!negate) EOR(CR, CR, LogicalImm(1ULL << 0, GPRSize::B64)); @@ -82,6 +80,7 @@ void JitArm64::SetCRFieldBit(int field, int bit, ARM64Reg in, bool negate) break; case PowerPC::CR_LT_BIT: // set bit 62 to input + FixGTBeforeSettingCRFieldBit(CR); BFI(CR, in, PowerPC::CR_EMU_LT_BIT, 1); if (negate) EOR(CR, CR, LogicalImm(1ULL << PowerPC::CR_EMU_LT_BIT, GPRSize::B64)); @@ -121,18 +120,16 @@ void JitArm64::SetCRFieldBit(int field, int bit) gpr.BindCRToRegister(field, true); ARM64Reg XA = gpr.CR(field); - if (bit != PowerPC::CR_GT_BIT) - FixGTBeforeSettingCRFieldBit(XA); - switch (bit) { case PowerPC::CR_SO_BIT: + FixGTBeforeSettingCRFieldBit(XA); ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_SO_BIT, GPRSize::B64)); break; case PowerPC::CR_EQ_BIT: + FixGTBeforeSettingEQ(XA); AND(XA, XA, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64)); - ORR(XA, XA, LogicalImm(u64(1) << 32, GPRSize::B64)); break; case PowerPC::CR_GT_BIT: @@ -141,6 +138,7 @@ void JitArm64::SetCRFieldBit(int field, int bit) break; case PowerPC::CR_LT_BIT: + FixGTBeforeSettingCRFieldBit(XA); ORR(XA, XA, LogicalImm(u64(1) << PowerPC::CR_EMU_LT_BIT, GPRSize::B64)); break; } @@ -159,6 +157,16 @@ void JitArm64::FixGTBeforeSettingCRFieldBit(ARM64Reg reg) CSEL(reg, reg, XA, CC_NEQ); } +void JitArm64::FixGTBeforeSettingEQ(Arm64Gen::ARM64Reg reg) +{ + ARM64Reg WA = gpr.GetReg(); + ARM64Reg XA = EncodeRegTo64(WA); + ORR(XA, reg, LogicalImm(1ULL << 32, GPRSize::B64)); + CMP(EncodeRegTo32(reg), ARM64Reg::WZR); + CSEL(reg, reg, XA, CC_EQ); + gpr.Unlock(WA); +} + FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set) { ARM64Reg XA = gpr.CR(field);