diff --git a/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/backend/x64/a32_emit_x64.cpp index e2c56b21..37f97207 100644 --- a/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -541,6 +541,12 @@ void A32EmitX64::EmitA32SetCpsr(A32EmitContext& ctx, IR::Inst* inst) { } void A32EmitX64::EmitA32SetCpsrNZCV(A32EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + const Xbyak::Reg32 to_store = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); + code.mov(dword[r15 + offsetof(A32JitState, cpsr_nzcv)], to_store); +} + +void A32EmitX64::EmitA32SetCpsrNZCVRaw(A32EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (args[0].IsImmediate()) { const u32 imm = args[0].GetImmediateU32(); diff --git a/src/dynarmic/frontend/A32/ir_emitter.cpp b/src/dynarmic/frontend/A32/ir_emitter.cpp index 9839beca..c948a78f 100644 --- a/src/dynarmic/frontend/A32/ir_emitter.cpp +++ b/src/dynarmic/frontend/A32/ir_emitter.cpp @@ -141,10 +141,14 @@ void IREmitter::SetCpsr(const IR::U32& value) { Inst(Opcode::A32SetCpsr, value); } -void IREmitter::SetCpsrNZCV(const IR::U32& value) { +void IREmitter::SetCpsrNZCV(const IR::NZCV& value) { Inst(Opcode::A32SetCpsrNZCV, value); } +void IREmitter::SetCpsrNZCVRaw(const IR::U32& value) { + Inst(Opcode::A32SetCpsrNZCVRaw, value); +} + void IREmitter::SetCpsrNZCVQ(const IR::U32& value) { Inst(Opcode::A32SetCpsrNZCVQ, value); } @@ -153,6 +157,10 @@ void IREmitter::SetCheckBit(const IR::U1& value) { Inst(Opcode::A32SetCheckBit, value); } +IR::U1 IREmitter::GetOverflowFrom(const IR::Value& value) { + return Inst(Opcode::GetOverflowFromOp, value); +} + IR::U1 IREmitter::GetCFlag() { return Inst(Opcode::A32GetCFlag); } diff --git a/src/dynarmic/frontend/A32/ir_emitter.h b/src/dynarmic/frontend/A32/ir_emitter.h index 80bcf6b9..9377a5c8 100644 --- a/src/dynarmic/frontend/A32/ir_emitter.h +++ b/src/dynarmic/frontend/A32/ir_emitter.h @@ -55,9 +55,11 @@ public: IR::U32 GetCpsr(); void SetCpsr(const IR::U32& value); - void SetCpsrNZCV(const IR::U32& value); + void SetCpsrNZCV(const IR::NZCV& value); + void SetCpsrNZCVRaw(const IR::U32& value); void SetCpsrNZCVQ(const IR::U32& value); void SetCheckBit(const IR::U1& value); + IR::U1 GetOverflowFrom(const IR::Value& value); IR::U1 GetCFlag(); void SetNFlag(const IR::U1& value); void SetZFlag(const IR::U1& value); diff --git a/src/dynarmic/frontend/A32/translate/impl/coprocessor.cpp b/src/dynarmic/frontend/A32/translate/impl/coprocessor.cpp index 63a233f0..402efd4b 100644 --- a/src/dynarmic/frontend/A32/translate/impl/coprocessor.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/coprocessor.cpp @@ -102,7 +102,7 @@ bool TranslatorVisitor::arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, si ir.SetRegister(t, word); } else { const auto new_cpsr_nzcv = ir.And(word, ir.Imm32(0xF0000000)); - ir.SetCpsrNZCV(new_cpsr_nzcv); + ir.SetCpsrNZCVRaw(new_cpsr_nzcv); } } return true; diff --git a/src/dynarmic/frontend/A32/translate/impl/data_processing.cpp b/src/dynarmic/frontend/A32/translate/impl/data_processing.cpp index ef038d2b..c6fa5300 100644 --- a/src/dynarmic/frontend/A32/translate/impl/data_processing.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/data_processing.cpp @@ -21,17 +21,14 @@ bool TranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, return UnpredictableInstruction(); } - ir.ALUWritePC(result.result); + ir.ALUWritePC(result); ir.SetTerm(IR::Term::ReturnToDispatch{}); return false; } - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } @@ -50,17 +47,14 @@ bool TranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5 return UnpredictableInstruction(); } - ir.ALUWritePC(result.result); + ir.ALUWritePC(result); ir.SetTerm(IR::Term::ReturnToDispatch{}); return false; } - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; @@ -81,12 +75,9 @@ bool TranslatorVisitor::arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, Shif const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in); const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag()); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; @@ -106,17 +97,14 @@ bool TranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, return UnpredictableInstruction(); } - ir.ALUWritePC(result.result); + ir.ALUWritePC(result); ir.SetTerm(IR::Term::ReturnToDispatch{}); return false; } - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; @@ -136,17 +124,14 @@ bool TranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5 return UnpredictableInstruction(); } - ir.ALUWritePC(result.result); + ir.ALUWritePC(result); ir.SetTerm(IR::Term::ReturnToDispatch{}); return false; } - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; @@ -167,12 +152,9 @@ bool TranslatorVisitor::arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, Shif const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in); const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; @@ -354,10 +336,7 @@ bool TranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8) { const u32 imm32 = ArmExpandImm(rotate, imm8); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); return true; } @@ -370,10 +349,7 @@ bool TranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shi const auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag()); const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0)); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); return true; } @@ -392,10 +368,7 @@ bool TranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Re const auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in); const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0)); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/multiply.cpp b/src/dynarmic/frontend/A32/translate/impl/multiply.cpp index 3af0600d..0c497a87 100644 --- a/src/dynarmic/frontend/A32/translate/impl/multiply.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/multiply.cpp @@ -260,10 +260,10 @@ bool TranslatorVisitor::arm_SMLAxy(Cond cond, Reg d, Reg a, Reg m, bool M, bool const IR::U32 m16 = M ? ir.ArithmeticShiftRight(m32, ir.Imm8(16), ir.Imm1(0)).result : ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32)); const IR::U32 product = ir.Mul(n16, m16); - const auto result_overflow = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); + const auto result = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -306,10 +306,10 @@ bool TranslatorVisitor::arm_SMLAWy(Cond cond, Reg d, Reg a, Reg m, bool M, Reg n } const IR::U64 m16 = ir.SignExtendWordToLong(ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32))); const auto product = ir.LeastSignificantWord(ir.LogicalShiftRight(ir.Mul(n32, m16), ir.Imm8(16))); - const auto result_overflow = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); + const auto result = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -352,7 +352,7 @@ bool TranslatorVisitor::arm_SMMLA(Cond cond, Reg d, Reg a, Reg m, bool R, Reg n) const auto result_carry = ir.MostSignificantWord(temp); auto result = result_carry.result; if (R) { - result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry).result; + result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry); } ir.SetRegister(d, result); @@ -376,7 +376,7 @@ bool TranslatorVisitor::arm_SMMLS(Cond cond, Reg d, Reg a, Reg m, bool R, Reg n) const auto result_carry = ir.MostSignificantWord(temp); auto result = result_carry.result; if (R) { - result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry).result; + result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry); } ir.SetRegister(d, result); @@ -399,7 +399,7 @@ bool TranslatorVisitor::arm_SMMUL(Cond cond, Reg d, Reg m, bool R, Reg n) { const auto result_carry = ir.MostSignificantWord(product); auto result = result_carry.result; if (R) { - result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry).result; + result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry); } ir.SetRegister(d, result); @@ -435,11 +435,11 @@ bool TranslatorVisitor::arm_SMLAD(Cond cond, Reg d, Reg a, Reg m, bool M, Reg n) const IR::U32 product_hi = ir.Mul(n_hi, m_hi); const IR::U32 addend = ir.GetRegister(a); - auto result_overflow = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); - ir.OrQFlag(result_overflow.overflow); - result_overflow = ir.AddWithCarry(result_overflow.result, addend, ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + auto result = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); + ir.OrQFlag(ir.GetOverflowFrom(result)); + result = ir.AddWithCarry(result, addend, ir.Imm1(0)); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -507,10 +507,10 @@ bool TranslatorVisitor::arm_SMLSD(Cond cond, Reg d, Reg a, Reg m, bool M, Reg n) const IR::U32 product_hi = ir.Mul(n_hi, m_hi); const IR::U32 addend = ir.GetRegister(a); const IR::U32 product = ir.Sub(product_lo, product_hi); - auto result_overflow = ir.AddWithCarry(product, addend, ir.Imm1(0)); + auto result = ir.AddWithCarry(product, addend, ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -572,10 +572,10 @@ bool TranslatorVisitor::arm_SMUAD(Cond cond, Reg d, Reg m, bool M, Reg n) { const IR::U32 product_lo = ir.Mul(n_lo, m_lo); const IR::U32 product_hi = ir.Mul(n_hi, m_hi); - const auto result_overflow = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); + const auto result = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/parallel.cpp b/src/dynarmic/frontend/A32/translate/impl/parallel.cpp index 8f036c6c..921c8b12 100644 --- a/src/dynarmic/frontend/A32/translate/impl/parallel.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/parallel.cpp @@ -194,7 +194,7 @@ bool TranslatorVisitor::arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n) { const auto tmp = ir.PackedAbsDiffSumS8(ir.GetRegister(n), ir.GetRegister(m)); const auto result = ir.AddWithCarry(ir.GetRegister(a), tmp, ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp index 6e2899d2..f2e2aa8c 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp @@ -62,12 +62,9 @@ bool TranslatorVisitor::thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) { bool TranslatorVisitor::thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) { const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (!ir.current_location.IT().IsInITBlock()) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } @@ -93,12 +90,9 @@ bool TranslatorVisitor::thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d) { const u32 imm32 = imm3.ZeroExtend(); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (!ir.current_location.IT().IsInITBlock()) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } @@ -153,12 +147,9 @@ bool TranslatorVisitor::thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8) { const Reg n = d_n; const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (!ir.current_location.IT().IsInITBlock()) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } @@ -270,12 +261,9 @@ bool TranslatorVisitor::thumb16_ADC_reg(Reg m, Reg d_n) { const auto aspr_c = ir.GetCFlag(); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), aspr_c); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (!ir.current_location.IT().IsInITBlock()) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } @@ -350,10 +338,7 @@ bool TranslatorVisitor::thumb16_CMP_reg_t1(Reg m, Reg n) { // CMN , bool TranslatorVisitor::thumb16_CMN_reg(Reg m, Reg n) { const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0)); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); return true; } @@ -430,12 +415,12 @@ bool TranslatorVisitor::thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0)); if (d == Reg::PC) { ir.UpdateUpperLocationDescriptor(); - ir.ALUWritePC(result.result); + ir.ALUWritePC(result); // Return to dispatch as we can't predict what PC is going to be. Stop compilation. ir.SetTerm(IR::Term::FastDispatchHint{}); return false; } else { - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); return true; } } @@ -672,7 +657,7 @@ bool TranslatorVisitor::thumb16_ADD_sp_t1(Reg d, Imm<8> imm8) { const u32 imm32 = imm8.ZeroExtend() << 2; const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); return true; } @@ -682,7 +667,7 @@ bool TranslatorVisitor::thumb16_ADD_sp_t2(Imm<7> imm7) { const Reg d = Reg::SP; const auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_coprocessor.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_coprocessor.cpp index 23cf5fa8..71f108f9 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_coprocessor.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_coprocessor.cpp @@ -67,7 +67,7 @@ bool TranslatorVisitor::thumb32_MRC(bool two, size_t opc1, CoprocReg CRn, Reg t, ir.SetRegister(t, word); } else { const auto new_cpsr_nzcv = ir.And(word, ir.Imm32(0xF0000000)); - ir.SetCpsrNZCV(new_cpsr_nzcv); + ir.SetCpsrNZCVRaw(new_cpsr_nzcv); } return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp index f7c710c7..5b5c30ba 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp @@ -166,10 +166,7 @@ bool TranslatorVisitor::thumb32_CMN_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm const auto imm32 = ThumbExpandImm(i, imm3, imm8); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); return true; } @@ -182,12 +179,9 @@ bool TranslatorVisitor::thumb32_ADD_imm_1(Imm<1> i, bool S, Reg n, Imm<3> imm3, const auto imm32 = ThumbExpandImm(i, imm3, imm8); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } @@ -200,12 +194,9 @@ bool TranslatorVisitor::thumb32_ADC_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Re const auto imm32 = ThumbExpandImm(i, imm3, imm8); const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag()); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp index ffe5e56d..d836cad9 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp @@ -85,7 +85,7 @@ bool TranslatorVisitor::thumb32_ADD_imm_2(Imm<1> imm1, Reg n, Imm<3> imm3, Reg d const auto reg_n = ir.GetRegister(n); const auto result = ir.AddWithCarry(reg_n, ir.Imm32(imm), ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp index 82a25fad..13c84c5c 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp @@ -178,10 +178,7 @@ bool TranslatorVisitor::thumb32_CMN_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftTy const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0)); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); return true; } @@ -194,12 +191,9 @@ bool TranslatorVisitor::thumb32_ADD_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2 const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } @@ -211,12 +205,9 @@ bool TranslatorVisitor::thumb32_ADC_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2 const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); const auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag()); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); if (S) { - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + ir.SetCpsrNZCV(ir.NZCVFrom(result)); } return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/thumb32_multiply.cpp b/src/dynarmic/frontend/A32/translate/impl/thumb32_multiply.cpp index bcbcf73c..6db559d1 100644 --- a/src/dynarmic/frontend/A32/translate/impl/thumb32_multiply.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/thumb32_multiply.cpp @@ -68,12 +68,12 @@ bool TranslatorVisitor::thumb32_SMLAD(Reg n, Reg a, Reg d, bool X, Reg m) { const IR::U32 product_hi = ir.Mul(n_hi, m_hi); const IR::U32 addend = ir.GetRegister(a); - auto result_overflow = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); - ir.OrQFlag(result_overflow.overflow); - result_overflow = ir.AddWithCarry(result_overflow.result, addend, ir.Imm1(0)); + auto result = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); + ir.OrQFlag(ir.GetOverflowFrom(result)); + result = ir.AddWithCarry(result, addend, ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -97,10 +97,10 @@ bool TranslatorVisitor::thumb32_SMLSD(Reg n, Reg a, Reg d, bool X, Reg m) { const IR::U32 product_hi = ir.Mul(n_hi, m_hi); const IR::U32 addend = ir.GetRegister(a); const IR::U32 product = ir.Sub(product_lo, product_hi); - auto result_overflow = ir.AddWithCarry(product, addend, ir.Imm1(0)); + auto result = ir.AddWithCarry(product, addend, ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -116,10 +116,10 @@ bool TranslatorVisitor::thumb32_SMLAXY(Reg n, Reg a, Reg d, bool N, bool M, Reg const IR::U32 m16 = M ? ir.ArithmeticShiftRight(m32, ir.Imm8(16), ir.Imm1(0)).result : ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32)); const IR::U32 product = ir.Mul(n16, m16); - const auto result_overflow = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); + const auto result = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -135,7 +135,7 @@ bool TranslatorVisitor::thumb32_SMMLA(Reg n, Reg a, Reg d, bool R, Reg m) { const auto result_carry = ir.MostSignificantWord(temp); auto result = result_carry.result; if (R) { - result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry).result; + result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry); } ir.SetRegister(d, result); @@ -154,7 +154,7 @@ bool TranslatorVisitor::thumb32_SMMLS(Reg n, Reg a, Reg d, bool R, Reg m) { const auto result_carry = ir.MostSignificantWord(temp); auto result = result_carry.result; if (R) { - result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry).result; + result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry); } ir.SetRegister(d, result); @@ -172,7 +172,7 @@ bool TranslatorVisitor::thumb32_SMMUL(Reg n, Reg d, bool R, Reg m) { const auto result_carry = ir.MostSignificantWord(product); auto result = result_carry.result; if (R) { - result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry).result; + result = ir.AddWithCarry(result, ir.Imm32(0), result_carry.carry); } ir.SetRegister(d, result); @@ -197,10 +197,10 @@ bool TranslatorVisitor::thumb32_SMUAD(Reg n, Reg d, bool M, Reg m) { const IR::U32 product_lo = ir.Mul(n_lo, m_lo); const IR::U32 product_hi = ir.Mul(n_hi, m_hi); - const auto result_overflow = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); + const auto result = ir.AddWithCarry(product_lo, product_hi, ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -257,10 +257,10 @@ bool TranslatorVisitor::thumb32_SMLAWY(Reg n, Reg a, Reg d, bool M, Reg m) { } const IR::U64 m16 = ir.SignExtendWordToLong(ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32))); const auto product = ir.LeastSignificantWord(ir.LogicalShiftRight(ir.Mul(n32, m16), ir.Imm8(16))); - const auto result_overflow = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); + const auto result = ir.AddWithCarry(product, ir.GetRegister(a), ir.Imm1(0)); - ir.SetRegister(d, result_overflow.result); - ir.OrQFlag(result_overflow.overflow); + ir.SetRegister(d, result); + ir.OrQFlag(ir.GetOverflowFrom(result)); return true; } @@ -305,7 +305,7 @@ bool TranslatorVisitor::thumb32_USADA8(Reg n, Reg a, Reg d, Reg m) { const auto tmp = ir.PackedAbsDiffSumS8(reg_n, reg_m); const auto result = ir.AddWithCarry(reg_a, tmp, ir.Imm1(0)); - ir.SetRegister(d, result.result); + ir.SetRegister(d, result); return true; } diff --git a/src/dynarmic/frontend/A32/translate/impl/vfp.cpp b/src/dynarmic/frontend/A32/translate/impl/vfp.cpp index c3622533..0ca54108 100644 --- a/src/dynarmic/frontend/A32/translate/impl/vfp.cpp +++ b/src/dynarmic/frontend/A32/translate/impl/vfp.cpp @@ -1155,7 +1155,7 @@ bool TranslatorVisitor::vfp_VMRS(Cond cond, Reg t) { if (t == Reg::R15) { // This encodes ASPR_nzcv access const auto nzcv = ir.GetFpscrNZCV(); - ir.SetCpsrNZCV(nzcv); + ir.SetCpsrNZCVRaw(nzcv); } else { ir.SetRegister(t, ir.GetFpscr()); } diff --git a/src/dynarmic/ir/ir_emitter.cpp b/src/dynarmic/ir/ir_emitter.cpp index 2f289d67..66591c50 100644 --- a/src/dynarmic/ir/ir_emitter.cpp +++ b/src/dynarmic/ir/ir_emitter.cpp @@ -240,13 +240,6 @@ U32U64 IREmitter::RotateRightMasked(const U32U64& value_in, const U32U64& shift_ } } -ResultAndCarryAndOverflow IREmitter::AddWithCarry(const U32& a, const U32& b, const U1& carry_in) { - const auto result = Inst(Opcode::Add32, a, b, carry_in); - const auto carry_out = Inst(Opcode::GetCarryFromOp, result); - const auto overflow = Inst(Opcode::GetOverflowFromOp, result); - return {result, carry_out, overflow}; -} - U32U64 IREmitter::AddWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in) { ASSERT(a.GetType() == b.GetType()); if (a.GetType() == Type::U32) { diff --git a/src/dynarmic/ir/ir_emitter.h b/src/dynarmic/ir/ir_emitter.h index caba937d..12c489d1 100644 --- a/src/dynarmic/ir/ir_emitter.h +++ b/src/dynarmic/ir/ir_emitter.h @@ -134,7 +134,6 @@ public: U32U64 ArithmeticShiftRightMasked(const U32U64& value_in, const U32U64& shift_amount); U32U64 RotateRightMasked(const U32U64& value_in, const U32U64& shift_amount); ResultAndCarry RotateRightExtended(const U32& value_in, const U1& carry_in); - ResultAndCarryAndOverflow AddWithCarry(const U32& a, const U32& b, const U1& carry_in); ResultAndCarryAndOverflow SubWithCarry(const U32& a, const U32& b, const U1& carry_in); U32U64 AddWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in); U32U64 SubWithCarry(const U32U64& a, const U32U64& b, const U1& carry_in); diff --git a/src/dynarmic/ir/microinstruction.cpp b/src/dynarmic/ir/microinstruction.cpp index a499c327..858c5bc2 100644 --- a/src/dynarmic/ir/microinstruction.cpp +++ b/src/dynarmic/ir/microinstruction.cpp @@ -176,6 +176,7 @@ bool Inst::ReadsFromCPSR() const { bool Inst::WritesToCPSR() const { switch (op) { case Opcode::A32SetCpsr: + case Opcode::A32SetCpsrNZCVRaw: case Opcode::A32SetCpsrNZCV: case Opcode::A32SetCpsrNZCVQ: case Opcode::A32SetNFlag: diff --git a/src/dynarmic/ir/opcodes.inc b/src/dynarmic/ir/opcodes.inc index f8995b19..be0cda9e 100644 --- a/src/dynarmic/ir/opcodes.inc +++ b/src/dynarmic/ir/opcodes.inc @@ -17,7 +17,8 @@ A32OPC(SetExtendedRegister64, Void, A32E A32OPC(SetVector, Void, A32ExtReg, U128 ) A32OPC(GetCpsr, U32, ) A32OPC(SetCpsr, Void, U32 ) -A32OPC(SetCpsrNZCV, Void, U32 ) +A32OPC(SetCpsrNZCV, Void, NZCV ) +A32OPC(SetCpsrNZCVRaw, Void, U32 ) A32OPC(SetCpsrNZCVQ, Void, U32 ) A32OPC(GetNFlag, U1, ) A32OPC(SetNFlag, Void, U1 )