diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index c8aea9863e9..d9b5cb360b3 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -680,29 +680,7 @@ void Jit64::boolX(UGeckoInstruction inst) bool needs_test = false; DEBUG_ASSERT_MSG(DYNA_REC, inst.OPCD == 31, "Invalid boolX"); - if (gpr.IsImm(s, b)) - { - const u32 rs_offset = gpr.Imm32(s); - const u32 rb_offset = gpr.Imm32(b); - - if (inst.SUBOP10 == 28) // andx - gpr.SetImmediate32(a, rs_offset & rb_offset); - else if (inst.SUBOP10 == 476) // nandx - gpr.SetImmediate32(a, ~(rs_offset & rb_offset)); - else if (inst.SUBOP10 == 60) // andcx - gpr.SetImmediate32(a, rs_offset & (~rb_offset)); - else if (inst.SUBOP10 == 444) // orx - gpr.SetImmediate32(a, rs_offset | rb_offset); - else if (inst.SUBOP10 == 124) // norx - gpr.SetImmediate32(a, ~(rs_offset | rb_offset)); - else if (inst.SUBOP10 == 412) // orcx - gpr.SetImmediate32(a, rs_offset | (~rb_offset)); - else if (inst.SUBOP10 == 316) // xorx - gpr.SetImmediate32(a, rs_offset ^ rb_offset); - else if (inst.SUBOP10 == 284) // eqvx - gpr.SetImmediate32(a, ~(rs_offset ^ rb_offset)); - } - else if (gpr.IsImm(s) || gpr.IsImm(b)) + if (gpr.IsImm(s) || gpr.IsImm(b)) { const auto [i, j] = gpr.IsImm(s) ? std::pair(s, b) : std::pair(b, s); u32 imm = gpr.Imm32(i); @@ -756,53 +734,46 @@ void Jit64::boolX(UGeckoInstruction inst) } else if (is_and) { - if (imm == 0) + RCOpArg Rj = gpr.Use(j, RCMode::Read); + RCX64Reg Ra = gpr.Bind(a, RCMode::Write); + RegCache::Realize(Rj, Ra); + + if (imm == 0xFFFFFFFF) { - gpr.SetImmediate32(a, final_not ? 0xFFFFFFFF : 0); + if (a != j) + MOV(32, Ra, Rj); + if (final_not || complement_b) + NOT(32, Ra); + needs_test = true; + } + else if (complement_b) + { + if (a != j) + MOV(32, Ra, Rj); + NOT(32, Ra); + AND(32, Ra, Imm32(imm)); } else { - RCOpArg Rj = gpr.Use(j, RCMode::Read); - RCX64Reg Ra = gpr.Bind(a, RCMode::Write); - RegCache::Realize(Rj, Ra); - - if (imm == 0xFFFFFFFF) + if (a == j) { - if (a != j) - MOV(32, Ra, Rj); - if (final_not || complement_b) - NOT(32, Ra); - needs_test = true; + AND(32, Ra, Imm32(imm)); } - else if (complement_b) + else if (s32(imm) >= -128 && s32(imm) <= 127) { - if (a != j) - MOV(32, Ra, Rj); - NOT(32, Ra); + MOV(32, Ra, Rj); AND(32, Ra, Imm32(imm)); } else { - if (a == j) - { - AND(32, Ra, Imm32(imm)); - } - else if (s32(imm) >= -128 && s32(imm) <= 127) - { - MOV(32, Ra, Rj); - AND(32, Ra, Imm32(imm)); - } - else - { - MOV(32, Ra, Imm32(imm)); - AND(32, Ra, Rj); - } + MOV(32, Ra, Imm32(imm)); + AND(32, Ra, Rj); + } - if (final_not) - { - NOT(32, Ra); - needs_test = true; - } + if (final_not) + { + NOT(32, Ra); + needs_test = true; } } } diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 1628fe04c4d..9ab44b66aed 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -231,29 +231,7 @@ void JitArm64::boolX(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); int a = inst.RA, s = inst.RS, b = inst.RB; - if (gpr.IsImm(s) && gpr.IsImm(b)) - { - if (inst.SUBOP10 == 28) // andx - gpr.SetImmediate(a, (u32)gpr.GetImm(s) & (u32)gpr.GetImm(b)); - else if (inst.SUBOP10 == 476) // nandx - gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) & (u32)gpr.GetImm(b))); - else if (inst.SUBOP10 == 60) // andcx - gpr.SetImmediate(a, (u32)gpr.GetImm(s) & (~(u32)gpr.GetImm(b))); - else if (inst.SUBOP10 == 444) // orx - gpr.SetImmediate(a, (u32)gpr.GetImm(s) | (u32)gpr.GetImm(b)); - else if (inst.SUBOP10 == 124) // norx - gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) | (u32)gpr.GetImm(b))); - else if (inst.SUBOP10 == 412) // orcx - gpr.SetImmediate(a, (u32)gpr.GetImm(s) | (~(u32)gpr.GetImm(b))); - else if (inst.SUBOP10 == 316) // xorx - gpr.SetImmediate(a, (u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b)); - else if (inst.SUBOP10 == 284) // eqvx - gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b))); - - if (inst.Rc) - ComputeRC0(gpr.GetImm(a)); - } - else if (s == b) + if (s == b) { if ((inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 444 /* orx */)) { diff --git a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp index 34771366f3d..f29ce2a759e 100644 --- a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp @@ -36,6 +36,8 @@ ConstantPropagationResult ConstantPropagation::EvaluateInstruction(UGeckoInstruc case 28: // andi case 29: // andis return EvaluateBitwiseImm(inst, BitAND); + case 31: + return EvaluateTable31(inst); default: return {}; } @@ -69,6 +71,132 @@ ConstantPropagationResult ConstantPropagation::EvaluateBitwiseImm(UGeckoInstruct return ConstantPropagationResult(inst.RA, do_op(m_gpr_values[inst.RS], immediate), is_and); } +ConstantPropagationResult ConstantPropagation::EvaluateTable31(UGeckoInstruction inst) const +{ + const bool has_s = HasGPR(inst.RS); + const bool has_b = HasGPR(inst.RB); + if (!has_s || !has_b) + { + if (has_s) + return EvaluateTable31OneRegisterKnown(inst, GetGPR(inst.RS), false); + else if (has_b) + return EvaluateTable31OneRegisterKnown(inst, GetGPR(inst.RB), true); + else if (inst.RS == inst.RB) + return EvaluateTable31IdenticalRegisters(inst); + else + return {}; + } + + u32 a; + const u32 s = GetGPR(inst.RS); + const u32 b = GetGPR(inst.RB); + + switch (inst.SUBOP10) + { + case 28: // andx + a = s & b; + break; + case 60: // andcx + a = s & (~b); + break; + case 124: // norx + a = ~(s | b); + break; + case 284: // eqvx + a = ~(s ^ b); + break; + case 316: // xorx + a = s ^ b; + break; + case 412: // orcx + a = s | (~b); + break; + case 444: // orx + a = s | b; + break; + case 476: // nandx + a = ~(s & b); + break; + default: + return {}; + } + + return ConstantPropagationResult(inst.RA, a, inst.Rc); +} + +ConstantPropagationResult +ConstantPropagation::EvaluateTable31OneRegisterKnown(UGeckoInstruction inst, u32 value, + bool known_reg_is_b) const +{ + u32 a; + + switch (inst.SUBOP10) + { + case 60: // andcx + if (known_reg_is_b) + value = ~value; + [[fallthrough]]; + case 28: // andx + if (value == 0) + a = 0; + else + return {}; + break; + case 124: // norx + if (value == 0xFFFFFFFF) + a = 0; + else + return {}; + break; + case 412: // orcx + if (known_reg_is_b) + value = ~value; + [[fallthrough]]; + case 444: // orx + if (value == 0xFFFFFFFF) + a = 0xFFFFFFFF; + else + return {}; + break; + case 476: // nandx + if (value == 0) + a = 0xFFFFFFFF; + else + return {}; + break; + default: + return {}; + } + + return ConstantPropagationResult(inst.RA, a, inst.Rc); +} + +ConstantPropagationResult +ConstantPropagation::EvaluateTable31IdenticalRegisters(UGeckoInstruction inst) const +{ + u32 a; + + switch (inst.SUBOP10) + { + case 60: // andcx + a = 0; + break; + case 284: // eqvx + a = 0xFFFFFFFF; + break; + case 316: // xorx + a = 0; + break; + case 412: // orcx + a = 0xFFFFFFFF; + break; + default: + return {}; + } + + return ConstantPropagationResult(inst.RA, a, inst.Rc); +} + void ConstantPropagation::Apply(ConstantPropagationResult result) { if (result.gpr >= 0) diff --git a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h index 797c7839254..5560ffdb808 100644 --- a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h +++ b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h @@ -80,6 +80,10 @@ private: ConstantPropagationResult EvaluateAddImm(UGeckoInstruction inst) const; ConstantPropagationResult EvaluateBitwiseImm(UGeckoInstruction inst, u32 (*do_op)(u32, u32)) const; + ConstantPropagationResult EvaluateTable31(UGeckoInstruction inst) const; + ConstantPropagationResult EvaluateTable31OneRegisterKnown(UGeckoInstruction inst, u32 value, + bool known_reg_is_b) const; + ConstantPropagationResult EvaluateTable31IdenticalRegisters(UGeckoInstruction inst) const; static constexpr ConstantPropagationResult DO_NOTHING = [] { ConstantPropagationResult result;