From 2cddaa09f06329971fc3ec3e4a7f76d2a88058fe Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 29 Jun 2015 19:02:30 -0500 Subject: [PATCH] [AArch64] Implement rlwimix. --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 76 +++++++++++++++++++ .../Core/PowerPC/JitArm64/JitArm64_Tables.cpp | 2 +- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 639892e441..aa9f43add3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -98,6 +98,7 @@ public: void subfx(UGeckoInstruction inst); void addcx(UGeckoInstruction inst); void slwx(UGeckoInstruction inst); + void rlwimix(UGeckoInstruction inst); // System Registers void mtmsr(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 86d85cedb8..542b636b30 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -766,3 +766,79 @@ void JitArm64::slwx(UGeckoInstruction inst) ComputeRC(gpr.R(a), 0); } } + +void JitArm64::rlwimix(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + + int a = inst.RA, s = inst.RS; + u32 mask = Helper_Mask(inst.MB, inst.ME); + + if (gpr.IsImm(a) && gpr.IsImm(s)) + { + u32 res = (gpr.GetImm(a) & ~mask) | (_rotl(gpr.GetImm(s), inst.SH) & mask); + gpr.SetImmediate(a, res); + if (inst.Rc) + ComputeRC(res, 0); + } + else + { + if (mask == 0 || (a == s && inst.SH == 0)) + { + // Do Nothing + } + else if (mask == 0xFFFFFFFF) + { + if (inst.SH || a != s) + gpr.BindToRegister(a, a == s); + + if (inst.SH) + ROR(gpr.R(a), gpr.R(s), 32 - inst.SH); + else if (a != s) + MOV(gpr.R(a), gpr.R(s)); + } + else if (inst.SH == 0 && inst.MB <= inst.ME) + { + // No rotation + // No mask inversion + u32 lsb = 31 - inst.ME; + u32 width = inst.ME - inst.MB + 1; + + gpr.BindToRegister(a, true); + ARM64Reg WA = gpr.GetReg(); + UBFX(WA, gpr.R(s), lsb, width); + BFI(gpr.R(a), WA, lsb, width); + gpr.Unlock(WA); + } + else if (inst.SH && inst.MB <= inst.ME) + { + // No mask inversion + u32 lsb = 31 - inst.ME; + u32 width = inst.ME - inst.MB + 1; + + gpr.BindToRegister(a, true); + ARM64Reg WA = gpr.GetReg(); + ROR(WA, gpr.R(s), 32 - inst.SH); + UBFX(WA, WA, lsb, width); + BFI(gpr.R(a), WA, lsb, width); + gpr.Unlock(WA); + } + else + { + gpr.BindToRegister(a, true); + ARM64Reg WA = gpr.GetReg(); + ARM64Reg WB = gpr.GetReg(); + + MOVI2R(WA, mask); + BIC(WB, gpr.R(a), WA); + AND(WA, WA, gpr.R(s), ArithOption(gpr.R(s), ST_ROR, 32 - inst.SH)); + ORR(gpr.R(a), WB, WA); + + gpr.Unlock(WA, WB); + } + + if (inst.Rc) + ComputeRC(gpr.R(a), 0); + } +} diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index b25eb6ec50..fe3bb519a4 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -52,7 +52,7 @@ static GekkoOPTemplate primarytable[] = {14, &JitArm64::arith_imm}, // addi {15, &JitArm64::arith_imm}, // addis - {20, &JitArm64::FallBackToInterpreter}, // rlwimix + {20, &JitArm64::rlwimix}, // rlwimix {21, &JitArm64::rlwinmx}, // rlwinmx {23, &JitArm64::FallBackToInterpreter}, // rlwnmx