summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2015-06-29 19:02:30 -0500
committerRyan Houdek <Sonicadvance1@gmail.com>2015-06-30 19:49:10 -0500
commit2cddaa09f06329971fc3ec3e4a7f76d2a88058fe (patch)
tree42d7e93c400082e19f523d31ec86699c670c39b7 /Source/Core
parentafc3d30f5ce270d64cdc4c7a9151b9fb1590b818 (diff)
[AArch64] Implement rlwimix.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/Jit.h1
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp76
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp2
3 files changed, 78 insertions, 1 deletions
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