From 550a90e69197619fe858b95f61e3944008f09ba5 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 14 Aug 2015 00:29:13 +0200 Subject: [PATCH 1/6] JitArm64: Implement subfex --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 60 +++++++++++++++++++ .../Core/PowerPC/JitArm64/JitArm64_Tables.cpp | 4 +- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 2a851e3339..9d44f967ef 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -99,6 +99,7 @@ public: void addcx(UGeckoInstruction inst); void slwx(UGeckoInstruction inst); void rlwimix(UGeckoInstruction inst); + void subfex(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 1ae60dc0b8..937bd07f3d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -724,6 +724,66 @@ void JitArm64::subfx(UGeckoInstruction inst) } } +void JitArm64::subfex(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + FALLBACK_IF(inst.OE); + + int a = inst.RA, b = inst.RB, d = inst.RD; + + if (gpr.IsImm(a) && gpr.IsImm(b)) + { + u32 i = gpr.GetImm(a), j = gpr.GetImm(b); + + gpr.BindToRegister(d, false); + MOVI2R(gpr.R(d), ~i + j); + ARM64Reg WA = gpr.GetReg(); + LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca)); + ADD(gpr.R(d), gpr.R(d), WA); + gpr.Unlock(WA); + + bool must_have_carry = Interpreter::Helper_Carry(~i, j); + bool might_have_carry = (~i + j) == 0xFFFFFFFF; + + if (must_have_carry) + { + ComputeCarry(true); + } + else if (might_have_carry) + { + // carry stay as it is + } + else + { + ComputeCarry(false); + } + } + else + { + ARM64Reg WA = gpr.GetReg(); + gpr.BindToRegister(d, d == a || d == b); + + // upload the carry state + LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca)); + CMP(WA, 1); + + // d = ~a + b + carry; + if (gpr.IsImm(a)) + MOVI2R(WA, ~gpr.GetImm(a)); + else + MVN(WA, gpr.R(a)); + ADCS(gpr.R(d), WA, gpr.R(b)); + + gpr.Unlock(WA); + + ComputeCarry(); + } + + if (inst.Rc) + ComputeRC(gpr.R(d), 0); +} + void JitArm64::addcx(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index a2c71acf91..7b3327706e 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -194,8 +194,8 @@ static GekkoOPTemplate table31[] = {552, &JitArm64::subfx}, // subfox {8, &JitArm64::FallBackToInterpreter}, // subfcx {520, &JitArm64::FallBackToInterpreter}, // subfcox - {136, &JitArm64::FallBackToInterpreter}, // subfex - {648, &JitArm64::FallBackToInterpreter}, // subfeox + {136, &JitArm64::subfex}, // subfex + {648, &JitArm64::subfex}, // subfeox {232, &JitArm64::FallBackToInterpreter}, // subfmex {744, &JitArm64::FallBackToInterpreter}, // subfmeox {200, &JitArm64::FallBackToInterpreter}, // subfzex From 025e7c835ab310119ee1a4e7c5505459efe29258 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 23 Aug 2015 11:22:46 +0200 Subject: [PATCH 2/6] JitArm64: Implement subfcx --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 32 +++++++++++++++++++ .../Core/PowerPC/JitArm64/JitArm64_Tables.cpp | 4 +-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 9d44f967ef..6022e9eb64 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -100,6 +100,7 @@ public: void slwx(UGeckoInstruction inst); void rlwimix(UGeckoInstruction inst); void subfex(UGeckoInstruction inst); + void subfcx(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 937bd07f3d..8c27c56ad8 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -784,6 +784,38 @@ void JitArm64::subfex(UGeckoInstruction inst) ComputeRC(gpr.R(d), 0); } +void JitArm64::subfcx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + FALLBACK_IF(inst.OE); + + int a = inst.RA, b = inst.RB, d = inst.RD; + + if (gpr.IsImm(a) && gpr.IsImm(b)) + { + u32 a_imm = gpr.GetImm(a), b_imm = gpr.GetImm(b); + + gpr.SetImmediate(d, b_imm - a_imm); + ComputeCarry(a_imm == 0 || Interpreter::Helper_Carry(b_imm, 0u - a_imm)); + + if (inst.Rc) + ComputeRC(gpr.GetImm(d), 0); + } + else + { + gpr.BindToRegister(d, d == a || d == b); + + // d = b - a + SUBS(gpr.R(d), gpr.R(b), gpr.R(a)); + + ComputeCarry(); + + if (inst.Rc) + ComputeRC(gpr.R(d), 0); + } +} + void JitArm64::addcx(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index 7b3327706e..6111e33e5a 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -192,8 +192,8 @@ static GekkoOPTemplate table31[] = {616, &JitArm64::negx}, // negox {40, &JitArm64::subfx}, // subfx {552, &JitArm64::subfx}, // subfox - {8, &JitArm64::FallBackToInterpreter}, // subfcx - {520, &JitArm64::FallBackToInterpreter}, // subfcox + {8, &JitArm64::subfcx}, // subfcx + {520, &JitArm64::subfcx}, // subfcox {136, &JitArm64::subfex}, // subfex {648, &JitArm64::subfex}, // subfeox {232, &JitArm64::FallBackToInterpreter}, // subfmex From 95be17772fdb05fa3a921da2cde96a17d06f83b7 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 23 Aug 2015 11:46:11 +0200 Subject: [PATCH 3/6] JitArm64: Implement addex --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 55 +++++++++++++++++++ .../Core/PowerPC/JitArm64/JitArm64_Tables.cpp | 4 +- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 6022e9eb64..244a58db05 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -101,6 +101,7 @@ public: void rlwimix(UGeckoInstruction inst); void subfex(UGeckoInstruction inst); void subfcx(UGeckoInstruction inst); + void addex(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 8c27c56ad8..119cc099c3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -816,6 +816,61 @@ void JitArm64::subfcx(UGeckoInstruction inst) } } +void JitArm64::addex(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + FALLBACK_IF(inst.OE); + + int a = inst.RA, b = inst.RB, d = inst.RD; + + if (gpr.IsImm(a) && gpr.IsImm(b)) + { + u32 i = gpr.GetImm(a), j = gpr.GetImm(b); + + gpr.BindToRegister(d, false); + MOVI2R(gpr.R(d), i + j); + ARM64Reg WA = gpr.GetReg(); + LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca)); + ADD(gpr.R(d), gpr.R(d), WA); + gpr.Unlock(WA); + + bool must_have_carry = Interpreter::Helper_Carry(i, j); + bool might_have_carry = (i + j) == 0xFFFFFFFF; + + if (must_have_carry) + { + ComputeCarry(true); + } + else if (might_have_carry) + { + // carry stay as it is + } + else + { + ComputeCarry(false); + } + } + else + { + gpr.BindToRegister(d, d == a || d == b); + + // upload the carry state + ARM64Reg WA = gpr.GetReg(); + LDRB(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(xer_ca)); + CMP(WA, 1); + gpr.Unlock(WA); + + // d = a + b + carry; + ADCS(gpr.R(d), gpr.R(a), gpr.R(b)); + + ComputeCarry(); + } + + if (inst.Rc) + ComputeRC(gpr.R(d), 0); +} + void JitArm64::addcx(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index 6111e33e5a..1cec717685 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -174,8 +174,8 @@ static GekkoOPTemplate table31[] = {778, &JitArm64::addx}, // addox {10, &JitArm64::addcx}, // addcx {522, &JitArm64::addcx}, // addcox - {138, &JitArm64::FallBackToInterpreter}, // addex - {650, &JitArm64::FallBackToInterpreter}, // addeox + {138, &JitArm64::addex}, // addex + {650, &JitArm64::addex}, // addeox {234, &JitArm64::FallBackToInterpreter}, // addmex {746, &JitArm64::FallBackToInterpreter}, // addmeox {202, &JitArm64::addzex}, // addzex From 9e4366963c42a81b49eb87969c13a3061deec0e9 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 23 Aug 2015 12:00:20 +0200 Subject: [PATCH 4/6] JitArm64: Implement subfic --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 35 +++++++++++++++++++ .../Core/PowerPC/JitArm64/JitArm64_Tables.cpp | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 244a58db05..a7c75b24e5 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -101,6 +101,7 @@ public: void rlwimix(UGeckoInstruction inst); void subfex(UGeckoInstruction inst); void subfcx(UGeckoInstruction inst); + void subfic(UGeckoInstruction inst); void addex(UGeckoInstruction inst); // System Registers diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 119cc099c3..fb3f1ec407 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -816,6 +816,41 @@ void JitArm64::subfcx(UGeckoInstruction inst) } } +void JitArm64::subfic(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + + int a = inst.RA, d = inst.RD; + s32 imm = inst.SIMM_16; + + if (gpr.IsImm(a)) + { + u32 a_imm = gpr.GetImm(a); + + gpr.SetImmediate(d, imm - a_imm); + ComputeCarry(a_imm == 0 || Interpreter::Helper_Carry(imm, 0u - a_imm)); + + if (inst.Rc) + ComputeRC(gpr.GetImm(d), 0); + } + else + { + gpr.BindToRegister(d, d == a); + + // d = imm - a + ARM64Reg WA = gpr.GetReg(); + MOVI2R(WA, imm); + SUBS(gpr.R(d), WA, gpr.R(a)); + gpr.Unlock(WA); + + ComputeCarry(); + + if (inst.Rc) + ComputeRC(gpr.R(d), 0); + } +} + void JitArm64::addex(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index 1cec717685..a33cb9909c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -44,7 +44,7 @@ static GekkoOPTemplate primarytable[] = {17, &JitArm64::sc}, // sc {7, &JitArm64::mulli}, // mulli - {8, &JitArm64::FallBackToInterpreter}, // subfic + {8, &JitArm64::subfic}, // subfic {10, &JitArm64::cmpli}, // cmpli {11, &JitArm64::cmpi}, // cmpi {12, &JitArm64::addic}, // addic From 4722a69fd04e3c3ae6ee43e2c9c32473863735f3 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 23 Aug 2015 12:11:21 +0200 Subject: [PATCH 5/6] JitArm64: Implement divwux --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 28 +++++++++++++++++++ .../Core/PowerPC/JitArm64/JitArm64_Tables.cpp | 4 +-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index a7c75b24e5..22d515e32b 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -103,6 +103,7 @@ public: void subfcx(UGeckoInstruction inst); void subfic(UGeckoInstruction inst); void addex(UGeckoInstruction inst); + void divwux(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 fb3f1ec407..70bed8e6c3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -935,6 +935,34 @@ void JitArm64::addcx(UGeckoInstruction inst) } } +void JitArm64::divwux(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + FALLBACK_IF(inst.OE); + + int a = inst.RA, b = inst.RB, d = inst.RD; + + if (gpr.IsImm(a) && gpr.IsImm(b)) + { + u32 i = gpr.GetImm(a), j = gpr.GetImm(b); + gpr.SetImmediate(d, j == 0 ? 0 : i / j); + + if (inst.Rc) + ComputeRC(gpr.GetImm(d), 0); + } + else + { + gpr.BindToRegister(d, d == a || d == b); + + // d = a / b + UDIV(gpr.R(d), gpr.R(a), gpr.R(b)); + + if (inst.Rc) + ComputeRC(gpr.R(d), 0); + } +} + void JitArm64::slwx(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index a33cb9909c..80a8e9c22a 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -182,8 +182,8 @@ static GekkoOPTemplate table31[] = {714, &JitArm64::addzex}, // addzeox {491, &JitArm64::FallBackToInterpreter}, // divwx {1003, &JitArm64::FallBackToInterpreter}, // divwox - {459, &JitArm64::FallBackToInterpreter}, // divwux - {971, &JitArm64::FallBackToInterpreter}, // divwuox + {459, &JitArm64::divwux}, // divwux + {971, &JitArm64::divwux}, // divwuox {75, &JitArm64::FallBackToInterpreter}, // mulhwx {11, &JitArm64::FallBackToInterpreter}, // mulhwux {235, &JitArm64::mullwx}, // mullwx From 7320d519b43a7e35a3e5acd095a4d652b18bef55 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 23 Aug 2015 17:29:02 +0200 Subject: [PATCH 6/6] JitArm64: Implement srwx --- Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 46 +++++++++++++++++++ .../Core/PowerPC/JitArm64/JitArm64_Tables.cpp | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 22d515e32b..c06cc122b7 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 srwx(UGeckoInstruction inst); void rlwimix(UGeckoInstruction inst); void subfex(UGeckoInstruction inst); void subfcx(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 70bed8e6c3..c9d6bafaef 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -1011,6 +1011,52 @@ void JitArm64::slwx(UGeckoInstruction inst) } } +void JitArm64::srwx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff); + + int a = inst.RA, b = inst.RB, s = inst.RS; + + if (gpr.IsImm(b) && gpr.IsImm(s)) + { + u32 i = gpr.GetImm(s), amount = gpr.GetImm(b); + gpr.SetImmediate(a, (amount & 0x20) ? 0 : i >> (amount & 0x1F)); + + if (inst.Rc) + ComputeRC(gpr.GetImm(a), 0); + } + else if (gpr.IsImm(b)) + { + u32 amount = gpr.GetImm(b); + if (amount & 0x20) + { + gpr.SetImmediate(a, 0); + if (inst.Rc) + ComputeRC(0, 0); + } + else + { + gpr.BindToRegister(a, a == s); + LSR(gpr.R(a), gpr.R(s), amount & 0x1F); + if (inst.Rc) + ComputeRC(gpr.R(a), 0); + } + } + else + { + gpr.BindToRegister(a, a == b || a == s); + + // wipe upper bits. TODO: get rid of it, but then no instruction is allowed to emit some higher bits. + MOV(gpr.R(s), gpr.R(s)); + + LSRV(EncodeRegTo64(gpr.R(a)), EncodeRegTo64(gpr.R(s)), EncodeRegTo64(gpr.R(b))); + + if (inst.Rc) + ComputeRC(gpr.R(a), 0); + } +} + void JitArm64::rlwimix(UGeckoInstruction inst) { INSTRUCTION_START diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index 80a8e9c22a..2aea4fc737 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -214,7 +214,7 @@ static GekkoOPTemplate table31[] = {26, &JitArm64::cntlzwx}, // cntlzwx {922, &JitArm64::extsXx}, // extshx {954, &JitArm64::extsXx}, // extsbx - {536, &JitArm64::FallBackToInterpreter}, // srwx + {536, &JitArm64::srwx}, // srwx {792, &JitArm64::FallBackToInterpreter}, // srawx {824, &JitArm64::srawix}, // srawix {24, &JitArm64::slwx}, // slwx