From 42fce74f390d9701b99f16a265c4b84a7d03c820 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 22 Mar 2018 15:20:45 -0400 Subject: [PATCH 1/3] Jit_Integer: Handle NOP case where RA == RS for ori ori can be used as a NOP if the two register operands are the same, and the immediate is zero, not only if the two register operands are r0. Also removes the check for !inst.Rc, as ori only has one encoding, and said encoding doesn't even have a record bit in it. --- Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 4 ++-- Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index d7fea234645f..333956b20214 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -304,8 +304,8 @@ void Jit64::reg_imm(UGeckoInstruction inst) case 15: // addis regimmop(d, a, false, (u32)inst.SIMM_16 << 16, Add, &XEmitter::ADD); break; - case 24: // ori - if (a == 0 && s == 0 && inst.UIMM == 0 && !inst.Rc) // check for nop + case 24: // ori + if (a == s && inst.UIMM == 0) // check for nop { // Make the nop visible in the generated code. not much use but interesting if we see one. NOP(); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 14a9562568bf..e78c9e984cd9 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -121,8 +121,9 @@ void JitArm64::arith_imm(UGeckoInstruction inst) switch (inst.OPCD) { - case 24: // ori - if (a == 0 && s == 0 && inst.UIMM == 0 && !inst.Rc) // check for nop + case 24: // ori + // check for nop + if (a == s && inst.UIMM == 0) { // NOP return; From 007f9e5309ba0666ef057f285632ffdc351732c8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 22 Mar 2018 15:34:47 -0400 Subject: [PATCH 2/3] Jit_Integer: Handle NOP case for oris as well Like ori, this can also be used as a NOP under the same conditions. --- Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 15 +++++++++------ .../Core/PowerPC/JitArm64/JitArm64_Integer.cpp | 10 ++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 333956b20214..cf7df035fa5c 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -304,18 +304,21 @@ void Jit64::reg_imm(UGeckoInstruction inst) case 15: // addis regimmop(d, a, false, (u32)inst.SIMM_16 << 16, Add, &XEmitter::ADD); break; - case 24: // ori - if (a == s && inst.UIMM == 0) // check for nop + case 24: // ori + case 25: // oris + { + // check for nop + if (a == s && inst.UIMM == 0) { // Make the nop visible in the generated code. not much use but interesting if we see one. NOP(); return; } - regimmop(a, s, true, inst.UIMM, Or, &XEmitter::OR); - break; - case 25: // oris - regimmop(a, s, true, inst.UIMM << 16, Or, &XEmitter::OR, false); + + const u32 immediate = inst.OPCD == 24 ? inst.UIMM : inst.UIMM << 16; + regimmop(a, s, true, immediate, Or, &XEmitter::OR); break; + } case 28: // andi regimmop(a, s, true, inst.UIMM, And, &XEmitter::AND, true); break; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index e78c9e984cd9..487f976a3dc1 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -122,17 +122,19 @@ void JitArm64::arith_imm(UGeckoInstruction inst) switch (inst.OPCD) { case 24: // ori + case 25: // oris + { // check for nop if (a == s && inst.UIMM == 0) { // NOP return; } - reg_imm(a, s, inst.UIMM, BitOR, &ARM64XEmitter::ORRI2R); - break; - case 25: // oris - reg_imm(a, s, inst.UIMM << 16, BitOR, &ARM64XEmitter::ORRI2R); + + const u32 immediate = inst.OPCD == 24 ? inst.UIMM : inst.UIMM << 16; + reg_imm(a, s, immediate, BitOR, &ARM64XEmitter::ORRI2R); break; + } case 28: // andi reg_imm(a, s, inst.UIMM, BitAND, &ARM64XEmitter::ANDI2R, true); break; From fc16a78f6ae313385ba1d2ac14e2b22462950103 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 22 Mar 2018 15:41:34 -0400 Subject: [PATCH 3/3] Jit_Integer: Handle NOP case for xori and xoris Like ori and oris, xori and xoris can also be used to introduce a NOP. In that case, just don't do anything. --- Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 14 +++++++++++--- .../Core/PowerPC/JitArm64/JitArm64_Integer.cpp | 13 ++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index cf7df035fa5c..241a5fe52bd0 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -326,11 +326,19 @@ void Jit64::reg_imm(UGeckoInstruction inst) regimmop(a, s, true, inst.UIMM << 16, And, &XEmitter::AND, true); break; case 26: // xori - regimmop(a, s, true, inst.UIMM, Xor, &XEmitter::XOR, false); - break; case 27: // xoris - regimmop(a, s, true, inst.UIMM << 16, Xor, &XEmitter::XOR, false); + { + if (s == a && inst.UIMM == 0) + { + // Make the nop visible in the generated code. + NOP(); + return; + } + + const u32 immediate = inst.OPCD == 26 ? inst.UIMM : inst.UIMM << 16; + regimmop(a, s, true, immediate, Xor, &XEmitter::XOR, false); break; + } case 12: // addic regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, false, true); break; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 487f976a3dc1..82c9e1180046 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -142,12 +142,19 @@ void JitArm64::arith_imm(UGeckoInstruction inst) reg_imm(a, s, inst.UIMM << 16, BitAND, &ARM64XEmitter::ANDI2R, true); break; case 26: // xori - reg_imm(a, s, inst.UIMM, BitXOR, &ARM64XEmitter::EORI2R); - break; case 27: // xoris - reg_imm(a, s, inst.UIMM << 16, BitXOR, &ARM64XEmitter::EORI2R); + { + if (a == s && inst.UIMM == 0) + { + // NOP + return; + } + + const u32 immediate = inst.OPCD == 26 ? inst.UIMM : inst.UIMM << 16; + reg_imm(a, s, immediate, BitXOR, &ARM64XEmitter::EORI2R); break; } + } } void JitArm64::addix(UGeckoInstruction inst)