From 4d88f5410ec838c4eb287865f83a64611438a2b1 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 27 Oct 2016 20:49:15 +0200 Subject: [PATCH 1/7] JitArm64: Store carry within the host carry flag. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 3 ++ Source/Core/Core/PowerPC/JitArm64/Jit.h | 1 + .../PowerPC/JitArm64/JitArm64_Integer.cpp | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 977dda4867..4be9fb1a91 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -54,6 +54,7 @@ void JitArm64::Init() code_block.m_gpa = &js.gpa; code_block.m_fpa = &js.fpa; analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE); + analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CARRY_MERGE); m_supports_cycle_counter = HasCycleCounters(); } @@ -79,6 +80,7 @@ void JitArm64::Shutdown() void JitArm64::FallBackToInterpreter(UGeckoInstruction inst) { + FlushCarry(); gpr.Flush(FlushMode::FLUSH_ALL, js.op); fpr.Flush(FlushMode::FLUSH_ALL, js.op); @@ -419,6 +421,7 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitB js.downcountAmount = 0; js.skipInstructions = 0; js.curBlock = b; + js.carryFlagSet = false; PPCAnalyst::CodeOp* ops = code_buf->codebuffer; diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 60746b580a..3393d12b0d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -241,6 +241,7 @@ private: void ComputeRC(u64 imm, int crf = 0, bool needs_sext = true); void ComputeCarry(bool Carry); void ComputeCarry(); + void FlushCarry(); void reg_imm(u32 d, u32 a, u32 value, u32 (*do_op)(u32, u32), void (ARM64XEmitter::*op)(ARM64Reg, ARM64Reg, u64, ARM64Reg), bool Rc = false); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 4882f82176..4c6347bb28 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -49,6 +49,8 @@ void JitArm64::ComputeRC(u64 imm, int crf, bool needs_sext) void JitArm64::ComputeCarry(bool Carry) { + js.carryFlagSet = false; + if (!js.op->wantsCA) return; @@ -66,13 +68,31 @@ void JitArm64::ComputeCarry(bool Carry) void JitArm64::ComputeCarry() { + js.carryFlagSet = false; + if (!js.op->wantsCA) return; + js.carryFlagSet = true; + if (MergeAllowedNextInstructions(1) && js.op[1].wantsCAInFlags) + { + return; + } + + FlushCarry(); +} + +void JitArm64::FlushCarry() +{ + if (!js.carryFlagSet) + return; + ARM64Reg WA = gpr.GetReg(); CSINC(WA, WSP, WSP, CC_CC); STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); gpr.Unlock(WA); + + js.carryFlagSet = false; } void JitArm64::reg_imm(u32 d, u32 a, u32 value, u32 (*do_op)(u32, u32), @@ -732,6 +752,8 @@ void JitArm64::addzex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); + FlushCarry(); + int a = inst.RA, d = inst.RD; if (d == a) @@ -784,6 +806,8 @@ void JitArm64::subfex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); + FlushCarry(); + int a = inst.RA, b = inst.RB, d = inst.RD; if (gpr.IsImm(a) && gpr.IsImm(b)) @@ -875,6 +899,8 @@ void JitArm64::subfzex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); + FlushCarry(); + int a = inst.RA, d = inst.RD; gpr.BindToRegister(d, d == a); @@ -926,6 +952,8 @@ void JitArm64::addex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); + FlushCarry(); + int a = inst.RA, b = inst.RB, d = inst.RD; if (gpr.IsImm(a) && gpr.IsImm(b)) From f449541e65b673f3ff46fd20ec04016170bff7c4 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 27 Oct 2016 21:11:56 +0200 Subject: [PATCH 2/7] JitArm64: Implement derefered carry usage. --- .../PowerPC/JitArm64/JitArm64_Integer.cpp | 77 +++++++++++++------ 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 4c6347bb28..1dbf9c4cd3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -752,11 +752,14 @@ void JitArm64::addzex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); - FlushCarry(); - int a = inst.RA, d = inst.RD; - if (d == a) + if (js.carryFlagSet) + { + gpr.BindToRegister(d, d == a); + ADCS(gpr.R(d), gpr.R(a), WZR); + } + else if (d == a) { gpr.BindToRegister(d, true); ARM64Reg WA = gpr.GetReg(); @@ -806,8 +809,6 @@ void JitArm64::subfex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); - FlushCarry(); - int a = inst.RA, b = inst.RB, d = inst.RD; if (gpr.IsImm(a) && gpr.IsImm(b)) @@ -816,8 +817,16 @@ void JitArm64::subfex(UGeckoInstruction inst) gpr.BindToRegister(d, false); ARM64Reg WA = gpr.GetReg(); - LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d)); + if (js.carryFlagSet) + { + MOVI2R(WA, ~i + j, gpr.R(d)); + ADC(gpr.R(d), WA, WZR); + } + else + { + LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + ADDI2R(gpr.R(d), WA, ~i + j, gpr.R(d)); + } gpr.Unlock(WA); bool must_have_carry = Interpreter::Helper_Carry(~i, j); @@ -842,8 +851,11 @@ void JitArm64::subfex(UGeckoInstruction inst) gpr.BindToRegister(d, d == a || d == b); // upload the carry state - LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - CMP(WA, 1); + if (!js.carryFlagSet) + { + LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + CMP(WA, 1); + } // d = ~a + b + carry; if (gpr.IsImm(a)) @@ -899,17 +911,23 @@ void JitArm64::subfzex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); - FlushCarry(); - int a = inst.RA, d = inst.RD; gpr.BindToRegister(d, d == a); - ARM64Reg WA = gpr.GetReg(); - LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - MVN(gpr.R(d), gpr.R(a)); - ADDS(gpr.R(d), gpr.R(d), WA); - gpr.Unlock(WA); + if (js.carryFlagSet) + { + MVN(gpr.R(d), gpr.R(a)); + ADCS(gpr.R(d), gpr.R(d), WZR); + } + else + { + ARM64Reg WA = gpr.GetReg(); + LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + MVN(gpr.R(d), gpr.R(a)); + ADDS(gpr.R(d), gpr.R(d), WA); + gpr.Unlock(WA); + } ComputeCarry(); @@ -952,8 +970,6 @@ void JitArm64::addex(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); FALLBACK_IF(inst.OE); - FlushCarry(); - int a = inst.RA, b = inst.RB, d = inst.RD; if (gpr.IsImm(a) && gpr.IsImm(b)) @@ -962,8 +978,16 @@ void JitArm64::addex(UGeckoInstruction inst) gpr.BindToRegister(d, false); ARM64Reg WA = gpr.GetReg(); - LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - ADDI2R(gpr.R(d), WA, i + j, gpr.R(d)); + if (js.carryFlagSet) + { + MOVI2R(WA, i + j); + ADC(gpr.R(d), WA, WZR); + } + else + { + LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + ADDI2R(gpr.R(d), WA, i + j, gpr.R(d)); + } gpr.Unlock(WA); bool must_have_carry = Interpreter::Helper_Carry(i, j); @@ -987,10 +1011,13 @@ void JitArm64::addex(UGeckoInstruction inst) gpr.BindToRegister(d, d == a || d == b); // upload the carry state - ARM64Reg WA = gpr.GetReg(); - LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - CMP(WA, 1); - gpr.Unlock(WA); + if (!js.carryFlagSet) + { + ARM64Reg WA = gpr.GetReg(); + LDRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + CMP(WA, 1); + gpr.Unlock(WA); + } // d = a + b + carry; ADCS(gpr.R(d), gpr.R(a), gpr.R(b)); @@ -1104,6 +1131,8 @@ void JitArm64::divwx(UGeckoInstruction inst) } else { + FlushCarry(); + gpr.BindToRegister(d, d == a || d == b); ARM64Reg WA = gpr.GetReg(); From 0d78f5926fed4a00e7ee124386ed057e00a23663 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 27 Oct 2016 21:29:05 +0200 Subject: [PATCH 3/7] JitArm64: Keep carry in the host flag for all integer instructions. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 2 ++ Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 4be9fb1a91..3aec0032ae 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -606,6 +606,8 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitB } JitArm64Tables::CompileInstruction(ops[i]); + if (!MergeAllowedNextInstructions(1) || js.op[1].opinfo->type != OPTYPE_INTEGER) + FlushCarry(); // If we have a register that will never be used again, flush it. gpr.StoreRegisters(~ops[i].gprInUse); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 1dbf9c4cd3..3b667c525b 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -74,7 +74,7 @@ void JitArm64::ComputeCarry() return; js.carryFlagSet = true; - if (MergeAllowedNextInstructions(1) && js.op[1].wantsCAInFlags) + if (MergeAllowedNextInstructions(1) && js.op[1].opinfo->type == OPTYPE_INTEGER) { return; } From 3405f5ac1a28560e62eb42236d0f103d5ffbd4cc Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 27 Oct 2016 21:41:58 +0200 Subject: [PATCH 4/7] JitArm64: Optimize carry behavior of srawix. --- .../PowerPC/JitArm64/JitArm64_Integer.cpp | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 3b667c525b..bdd92e0d9c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -595,17 +595,24 @@ void JitArm64::srawix(UGeckoInstruction inst) gpr.BindToRegister(a, a == s); ARM64Reg RA = gpr.R(a); ARM64Reg RS = gpr.R(s); - ARM64Reg WA = gpr.GetReg(); + ARM64Reg WA; - ORR(WA, WSP, RS, ArithOption(RS, ST_LSL, 32 - amount)); + if (js.op->wantsCA) + { + WA = gpr.GetReg(); + ORR(WA, WSP, RS, ArithOption(RS, ST_LSL, 32 - amount)); + } ORR(RA, WSP, RS, ArithOption(RS, ST_ASR, amount)); if (inst.Rc) ComputeRC(RA, 0); - ANDS(WSP, WA, RA); - CSINC(WA, WSP, WSP, CC_EQ); - STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - gpr.Unlock(WA); + if (js.op->wantsCA) + { + ANDS(WSP, WA, RA); + CSINC(WA, WSP, WSP, CC_EQ); + STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + gpr.Unlock(WA); + } } else { @@ -613,7 +620,7 @@ void JitArm64::srawix(UGeckoInstruction inst) ARM64Reg RA = gpr.R(a); ARM64Reg RS = gpr.R(s); MOV(RA, RS); - STRB(INDEX_UNSIGNED, WSP, PPC_REG, PPCSTATE_OFF(xer_ca)); + ComputeCarry(false); } } From c69903eb4279f9e3d72d0177a36ece9eb13a2415 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 27 Oct 2016 21:48:52 +0200 Subject: [PATCH 5/7] JitArm64: CR field cleanup. --- .../PowerPC/JitArm64/JitArm64_FloatingPoint.cpp | 3 +-- .../Core/PowerPC/JitArm64/JitArm64_Integer.cpp | 9 +++------ .../JitArm64/JitArm64_SystemRegisters.cpp | 16 ++++++++-------- Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp | 2 +- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp index 3ea2abdaf1..79ad36faab 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp @@ -313,8 +313,7 @@ void JitArm64::fcmpX(UGeckoInstruction inst) } SetJumpTarget(continue1); - STR(INDEX_UNSIGNED, XA, PPC_REG, - PPCSTATE_OFF(cr_val[0]) + (sizeof(PowerPC::ppcState.cr_val[0]) * crf)); + STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[crf])); gpr.Unlock(WA); } diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index bdd92e0d9c..dc2c3917b2 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -423,8 +423,7 @@ void JitArm64::cmp(UGeckoInstruction inst) SXTW(XB, RB); SUB(XA, XA, XB); - STR(INDEX_UNSIGNED, XA, PPC_REG, - PPCSTATE_OFF(cr_val[0]) + (sizeof(PowerPC::ppcState.cr_val[0]) * crf)); + STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[crf])); gpr.Unlock(WA, WB); } @@ -451,8 +450,7 @@ void JitArm64::cmpl(UGeckoInstruction inst) ARM64Reg WA = gpr.GetReg(); ARM64Reg XA = EncodeRegTo64(WA); SUB(XA, EncodeRegTo64(gpr.R(a)), EncodeRegTo64(gpr.R(b))); - STR(INDEX_UNSIGNED, XA, PPC_REG, - PPCSTATE_OFF(cr_val[0]) + (sizeof(PowerPC::ppcState.cr_val[0]) * crf)); + STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[crf])); gpr.Unlock(WA); } @@ -502,8 +500,7 @@ void JitArm64::cmpli(UGeckoInstruction inst) SUBI2R(XA, EncodeRegTo64(gpr.R(a)), inst.UIMM, XA); - STR(INDEX_UNSIGNED, XA, PPC_REG, - PPCSTATE_OFF(cr_val[0]) + (sizeof(PowerPC::ppcState.cr_val[0]) * crf)); + STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[crf])); gpr.Unlock(WA); } diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 84deac9703..e74e0573d3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -417,7 +417,7 @@ void JitArm64::crXXX(UGeckoInstruction inst) ARM64Reg WA = gpr.GetReg(); ARM64Reg XA = EncodeRegTo64(WA); - LDR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field); + LDR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[field])); switch (bit) { case CR_SO_BIT: @@ -436,7 +436,7 @@ void JitArm64::crXXX(UGeckoInstruction inst) AND(XA, XA, 64 - 63, 62, true); // XA & ~(1<<62) break; } - STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field); + STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[field])); gpr.Unlock(WA); return; } @@ -450,7 +450,7 @@ void JitArm64::crXXX(UGeckoInstruction inst) ARM64Reg WA = gpr.GetReg(); ARM64Reg XA = EncodeRegTo64(WA); - LDR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field); + LDR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[field])); if (bit != CR_GT_BIT) { @@ -483,7 +483,7 @@ void JitArm64::crXXX(UGeckoInstruction inst) ORR(XA, XA, 32, 0, true); // XA | 1<<32 - STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field); + STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[field])); gpr.Unlock(WA); return; } @@ -509,7 +509,7 @@ void JitArm64::crXXX(UGeckoInstruction inst) ARM64Reg WC = gpr.GetReg(); ARM64Reg XC = EncodeRegTo64(WC); - LDR(INDEX_UNSIGNED, XC, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field); + LDR(INDEX_UNSIGNED, XC, PPC_REG, PPCSTATE_OFF(cr_val[field])); switch (bit) { case CR_SO_BIT: // check bit 61 set @@ -565,7 +565,7 @@ void JitArm64::crXXX(UGeckoInstruction inst) int field = inst.CRBD >> 2; int bit = 3 - (inst.CRBD & 3); - LDR(INDEX_UNSIGNED, XB, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field); + LDR(INDEX_UNSIGNED, XB, PPC_REG, PPCSTATE_OFF(cr_val[field])); // Gross but necessary; if the input is totally zero and we set SO or LT, // or even just add the (1<<32), GT will suddenly end up set without us @@ -603,7 +603,7 @@ void JitArm64::crXXX(UGeckoInstruction inst) } ORR(XA, XA, 32, 0, true); // XA | 1<<32 - STR(INDEX_UNSIGNED, XB, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * field); + STR(INDEX_UNSIGNED, XB, PPC_REG, PPCSTATE_OFF(cr_val[field])); gpr.Unlock(WA); gpr.Unlock(WB); @@ -653,7 +653,7 @@ void JitArm64::mtcrf(UGeckoInstruction inst) } LDR(XA, XB, ArithOption(XA, true)); - STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * i); + STR(INDEX_UNSIGNED, XA, PPC_REG, PPCSTATE_OFF(cr_val[i])); } } gpr.Unlock(WA, WB); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp index 7c47e7a2b6..078dd877ad 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp @@ -629,7 +629,7 @@ void JitArm64::GenMfcr() const u8* start = GetCodePtr(); for (int i = 0; i < 8; i++) { - LDR(INDEX_UNSIGNED, X1, PPC_REG, PPCSTATE_OFF(cr_val) + 8 * i); + LDR(INDEX_UNSIGNED, X1, PPC_REG, PPCSTATE_OFF(cr_val[i])); // SO if (i == 0) From 0a3e5a0fe8a4bf7a6c1fd77a5253d9eec0b0582d Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 28 Oct 2016 08:38:19 +0200 Subject: [PATCH 6/7] JitArm64: srawix cleanups. --- .../PowerPC/JitArm64/JitArm64_Integer.cpp | 79 +++++++++++++------ 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index dc2c3917b2..1daecfd7e0 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -576,6 +576,7 @@ void JitArm64::srawix(UGeckoInstruction inst) int a = inst.RA; int s = inst.RS; int amount = inst.SH; + bool inplace_carry = MergeAllowedNextInstructions(1) && js.op[1].wantsCAInFlags; if (gpr.IsImm(s)) { @@ -587,31 +588,7 @@ void JitArm64::srawix(UGeckoInstruction inst) else ComputeCarry(false); } - else if (amount != 0) - { - gpr.BindToRegister(a, a == s); - ARM64Reg RA = gpr.R(a); - ARM64Reg RS = gpr.R(s); - ARM64Reg WA; - - if (js.op->wantsCA) - { - WA = gpr.GetReg(); - ORR(WA, WSP, RS, ArithOption(RS, ST_LSL, 32 - amount)); - } - ORR(RA, WSP, RS, ArithOption(RS, ST_ASR, amount)); - if (inst.Rc) - ComputeRC(RA, 0); - - if (js.op->wantsCA) - { - ANDS(WSP, WA, RA); - CSINC(WA, WSP, WSP, CC_EQ); - STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - gpr.Unlock(WA); - } - } - else + else if (amount == 0) { gpr.BindToRegister(a, a == s); ARM64Reg RA = gpr.R(a); @@ -619,6 +596,47 @@ void JitArm64::srawix(UGeckoInstruction inst) MOV(RA, RS); ComputeCarry(false); } + else + { + gpr.BindToRegister(a, a == s); + ARM64Reg RA = gpr.R(a); + ARM64Reg RS = gpr.R(s); + + if (js.op->wantsCA) + { + ARM64Reg WA = gpr.GetReg(); + ARM64Reg dest = inplace_carry ? WA : WSP; + if (a != s) + { + ASR(RA, RS, amount); + ANDS(dest, RA, RS, ArithOption(RS, ST_LSL, 32 - amount)); + } + else + { + LSL(WA, RS, 32 - amount); + ASR(RA, RS, amount); + ANDS(dest, WA, RA); + } + if (inplace_carry) + { + CMP(dest, 1); + ComputeCarry(); + } + else + { + CSINC(WA, WSP, WSP, CC_EQ); + STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + } + gpr.Unlock(WA); + } + else + { + ASR(RA, RS, amount); + } + + if (inst.Rc) + ComputeRC(RA, 0); + } } void JitArm64::addic(UGeckoInstruction inst) @@ -1266,6 +1284,7 @@ void JitArm64::srawx(UGeckoInstruction inst) JITDISABLE(bJITIntegerOff); int a = inst.RA, b = inst.RB, s = inst.RS; + bool inplace_carry = MergeAllowedNextInstructions(1) && js.op[1].wantsCAInFlags; if (gpr.IsImm(b) && gpr.IsImm(s)) { @@ -1337,7 +1356,15 @@ void JitArm64::srawx(UGeckoInstruction inst) SetJumpTarget(end); MOV(gpr.R(a), WB); - STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + if (inplace_carry) + { + CMP(WA, 1); + ComputeCarry(); + } + else + { + STRB(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + } gpr.Unlock(WA, WB, WC); } From 5a8c52ce3a7200ab7014973cc9d1e60a00240a57 Mon Sep 17 00:00:00 2001 From: degasus Date: Tue, 1 Nov 2016 11:53:22 +0100 Subject: [PATCH 7/7] JitArm64: Fix srawx. --- Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index 1daecfd7e0..124f354184 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -1305,10 +1305,16 @@ void JitArm64::srawx(UGeckoInstruction inst) ComputeRC(gpr.GetImm(a), 0); return; } - else if (gpr.IsImm(b) && (gpr.GetImm(b) & 0x20) == 0 && !js.op->wantsCA) + + if (gpr.IsImm(b) && !js.op->wantsCA) { + int amount = gpr.GetImm(b); + if (amount & 0x20) + amount = 0x1F; + else + amount &= 0x1F; gpr.BindToRegister(a, a == s); - ASR(gpr.R(a), gpr.R(a), gpr.GetImm(b) & 0x1F); + ASR(gpr.R(a), gpr.R(s), amount); } else if (!js.op->wantsCA) {