diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index d52e7c5ba4..e9e20892c7 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -13,13 +13,12 @@ #include "Core/PowerPC/JitArm64/JitAsm.h" #include "Core/PowerPC/JitCommon/JitBase.h" -#define PPCSTATE_OFF(elem) ((s64)&PowerPC::ppcState.elem - (s64)&PowerPC::ppcState) +#define PPCSTATE_OFF(elem) (offsetof(PowerPC::PowerPCState, elem)) // Some asserts to make sure we will be able to load everything static_assert(PPCSTATE_OFF(spr[1023]) <= 16380, "LDR(32bit) can't reach the last SPR"); static_assert((PPCSTATE_OFF(ps[0][0]) % 8) == 0, "LDR(64bit VFP) requires FPRs to be 8 byte aligned"); -using namespace Arm64Gen; class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock { public: @@ -117,9 +116,10 @@ private: FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set); - void ComputeRC(u32 d); + void ComputeRC(Arm64Gen::ARM64Reg reg, int crf = 0); + void ComputeRC(u32 imm, int crf = 0); typedef u32 (*Operation)(u32, u32); - void reg_imm(u32 d, u32 a, bool binary, u32 value, Operation do_op, void (ARM64XEmitter::*op)(ARM64Reg, ARM64Reg, ARM64Reg, ArithOption), bool Rc = false); + void reg_imm(u32 d, u32 a, bool binary, u32 value, Operation do_op, void (ARM64XEmitter::*op)(Arm64Gen::ARM64Reg, Arm64Gen::ARM64Reg, Arm64Gen::ARM64Reg, ArithOption), bool Rc = false); }; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 84c00449be..db03b99872 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -15,22 +15,27 @@ using namespace Arm64Gen; -void JitArm64::ComputeRC(u32 d) +void JitArm64::ComputeRC(ARM64Reg reg, int crf) { ARM64Reg WA = gpr.GetReg(); ARM64Reg XA = EncodeRegTo64(WA); - if (gpr.IsImm(d)) - { - MOVI2R(WA, gpr.GetImm(d)); - SXTW(XA, WA); - } - else - { - SXTW(XA, gpr.R(d)); - } + SXTW(XA, reg); - STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(cr_val[0])); + STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(cr_val[crf])); + gpr.Unlock(WA); +} + +void JitArm64::ComputeRC(u32 imm, int crf) +{ + ARM64Reg WA = gpr.GetReg(); + ARM64Reg XA = EncodeRegTo64(WA); + + MOVI2R(WA, imm); + if (!(imm & 0x80000000)) + SXTW(XA, WA); + + STR(INDEX_UNSIGNED, XA, X29, PPCSTATE_OFF(cr_val[crf])); gpr.Unlock(WA); } @@ -62,24 +67,27 @@ void JitArm64::reg_imm(u32 d, u32 a, bool binary, u32 value, Operation do_op, vo if (gpr.IsImm(a)) { gpr.SetImmediate(d, do_op(gpr.GetImm(a), value)); + if (Rc) + ComputeRC(gpr.GetImm(d)); } else { + gpr.BindToRegister(d, d == a); ARM64Reg WA = gpr.GetReg(); MOVI2R(WA, value); (this->*op)(gpr.R(d), gpr.R(a), WA, ArithOption(WA, ST_LSL, 0)); gpr.Unlock(WA); - } - if (Rc) - ComputeRC(d); + if (Rc) + ComputeRC(gpr.R(d), 0); + } } else if (do_op == Add) { // a == 0, implies zero register gpr.SetImmediate(d, value); if (Rc) - ComputeRC(d); + ComputeRC(value, 0); } else { @@ -153,7 +161,7 @@ void JitArm64::boolX(UGeckoInstruction inst) gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b))); if (inst.Rc) - ComputeRC(a); + ComputeRC(gpr.GetImm(a), 0); } else if (s == b) { @@ -161,30 +169,39 @@ void JitArm64::boolX(UGeckoInstruction inst) { if (a != s) { + gpr.BindToRegister(a, false); MOV(gpr.R(a), gpr.R(s)); } + if (inst.Rc) + ComputeRC(gpr.R(a)); } else if ((inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */)) { + gpr.BindToRegister(a, a == s); MVN(gpr.R(a), gpr.R(s)); + if (inst.Rc) + ComputeRC(gpr.R(a)); } else if ((inst.SUBOP10 == 412 /* orcx */) || (inst.SUBOP10 == 284 /* eqvx */)) { gpr.SetImmediate(a, 0xFFFFFFFF); + if (inst.Rc) + ComputeRC(gpr.GetImm(a), 0); } else if ((inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 316 /* xorx */)) { gpr.SetImmediate(a, 0); + if (inst.Rc) + ComputeRC(gpr.GetImm(a), 0); } else { PanicAlert("WTF!"); } - if (inst.Rc) - ComputeRC(a); } else { + gpr.BindToRegister(a, (a == s) || (a == b)); if (inst.SUBOP10 == 28) // andx { AND(gpr.R(a), gpr.R(s), gpr.R(b), ArithOption(gpr.R(a), ST_LSL, 0)); @@ -224,7 +241,7 @@ void JitArm64::boolX(UGeckoInstruction inst) PanicAlert("WTF!"); } if (inst.Rc) - ComputeRC(a); + ComputeRC(gpr.R(a), 0); } } @@ -235,13 +252,21 @@ void JitArm64::extsXx(UGeckoInstruction inst) int a = inst.RA, s = inst.RS; int size = inst.SUBOP10 == 922 ? 16 : 8; - if (gpr.IsImm(s)) - gpr.SetImmediate(a, (u32)(s32)(size == 16 ? (s16)gpr.GetImm(s) : (s8)gpr.GetImm(s))); - else - SBFM(gpr.R(a), gpr.R(s), 0, size - 1); + gpr.BindToRegister(a, a == s); + + if (gpr.IsImm(s)) + { + gpr.SetImmediate(a, (u32)(s32)(size == 16 ? (s16)gpr.GetImm(s) : (s8)gpr.GetImm(s))); + if (inst.Rc) + ComputeRC(gpr.GetImm(a), 0); + } + else + { + SBFM(gpr.R(a), gpr.R(s), 0, size - 1); + if (inst.Rc) + ComputeRC(gpr.R(a), 0); + } - if (inst.Rc) - ComputeRC(a); } void JitArm64::cntlzwx(UGeckoInstruction inst) @@ -251,13 +276,20 @@ void JitArm64::cntlzwx(UGeckoInstruction inst) int a = inst.RA; int s = inst.RS; - if (gpr.IsImm(s)) - gpr.SetImmediate(a, __builtin_clz(gpr.GetImm(s))); - else - CLZ(gpr.R(a), gpr.R(s)); + gpr.BindToRegister(a, a == s); - if (inst.Rc) - ComputeRC(a); + if (gpr.IsImm(s)) + { + gpr.SetImmediate(a, __builtin_clz(gpr.GetImm(s))); + if (inst.Rc) + ComputeRC(gpr.GetImm(a), 0); + } + else + { + CLZ(gpr.R(a), gpr.R(s)); + if (inst.Rc) + ComputeRC(gpr.R(a), 0); + } } void JitArm64::negx(UGeckoInstruction inst) @@ -269,11 +301,18 @@ void JitArm64::negx(UGeckoInstruction inst) FALLBACK_IF(inst.OE); - if (gpr.IsImm(a)) - gpr.SetImmediate(d, ~((u32)gpr.GetImm(a)) + 1); - else - SUB(gpr.R(d), WSP, gpr.R(a), ArithOption(gpr.R(a), ST_LSL, 0)); + gpr.BindToRegister(d, d == a); - if (inst.Rc) - ComputeRC(d); + if (gpr.IsImm(a)) + { + gpr.SetImmediate(d, ~((u32)gpr.GetImm(a)) + 1); + if (inst.Rc) + ComputeRC(gpr.GetImm(d), 0); + } + else + { + SUB(gpr.R(d), WSP, gpr.R(a), ArithOption(gpr.R(a), ST_LSL, 0)); + if (inst.Rc) + ComputeRC(gpr.R(d), 0); + } }