From f0ebdf278cf59eb90a56a159c374028eef059253 Mon Sep 17 00:00:00 2001 From: Merry Date: Fri, 20 Jan 2023 11:47:49 +0000 Subject: [PATCH] backend/x64: Improve verbose debugging output --- src/dynarmic/backend/x64/a32_emit_x64.cpp | 2 +- src/dynarmic/backend/x64/a32_interface.cpp | 1 + src/dynarmic/backend/x64/a64_emit_x64.cpp | 2 +- src/dynarmic/backend/x64/emit_x64.cpp | 34 ++++++++----- src/dynarmic/backend/x64/emit_x64.h | 2 +- .../backend/x64/emit_x64_data_processing.cpp | 16 ------ src/dynarmic/backend/x64/emit_x64_packed.cpp | 11 ---- .../backend/x64/emit_x64_saturation.cpp | 3 -- src/dynarmic/backend/x64/emit_x64_vector.cpp | 14 ----- src/dynarmic/backend/x64/reg_alloc.cpp | 29 +++++++++-- src/dynarmic/backend/x64/reg_alloc.h | 7 ++- .../backend/x64/verbose_debugging_output.cpp | 51 ++++++++++++++----- .../backend/x64/verbose_debugging_output.h | 2 +- tests/test_generator.cpp | 1 + 14 files changed, 97 insertions(+), 78 deletions(-) diff --git a/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/backend/x64/a32_emit_x64.cpp index 52c4a15c..0a08e7ef 100644 --- a/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -148,7 +148,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) { reg_alloc.EndOfAllocScope(); if (conf.very_verbose_debugging_output) { - EmitVerboseDebuggingOutput(reg_alloc); + EmitVerboseDebuggingOutput(reg_alloc, block); } } diff --git a/src/dynarmic/backend/x64/a32_interface.cpp b/src/dynarmic/backend/x64/a32_interface.cpp index e671c192..e428672f 100644 --- a/src/dynarmic/backend/x64/a32_interface.cpp +++ b/src/dynarmic/backend/x64/a32_interface.cpp @@ -183,6 +183,7 @@ private: Optimization::ConstantPropagation(ir_block); Optimization::DeadCodeElimination(ir_block); } + Optimization::IdentityRemovalPass(ir_block); Optimization::VerificationPass(ir_block); return emitter.Emit(ir_block); } diff --git a/src/dynarmic/backend/x64/a64_emit_x64.cpp b/src/dynarmic/backend/x64/a64_emit_x64.cpp index dd45049a..3cadcf8c 100644 --- a/src/dynarmic/backend/x64/a64_emit_x64.cpp +++ b/src/dynarmic/backend/x64/a64_emit_x64.cpp @@ -119,7 +119,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) { ctx.reg_alloc.EndOfAllocScope(); if (conf.very_verbose_debugging_output) { - EmitVerboseDebuggingOutput(reg_alloc); + EmitVerboseDebuggingOutput(reg_alloc, block); } } diff --git a/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/backend/x64/emit_x64.cpp index 22ed7e3d..229c4f18 100644 --- a/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/backend/x64/emit_x64.cpp @@ -103,7 +103,7 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, I code.mov(dword[r15 + code.GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32()); } -void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) { +void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc, const IR::Block& block) { code.sub(rsp, sizeof(RegisterData)); for (int i = 0; i < 16; i++) { if (rsp.getIdx() == i) { @@ -117,7 +117,7 @@ void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) { code.lea(rax, ptr[rsp + sizeof(RegisterData) + offsetof(StackLayout, spill)]); code.mov(xword[rsp + offsetof(RegisterData, spill)], rax); - reg_alloc.EmitVerboseDebuggingOutput(); + reg_alloc.EmitVerboseDebuggingOutput(block); for (int i = 0; i < 16; i++) { if (rsp.getIdx() == i) { @@ -143,27 +143,32 @@ void EmitX64::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) { PushRSBHelper(loc_desc_reg, index_reg, IR::LocationDescriptor{unique_hash_of_target}); } -void EmitX64::EmitGetCarryFromOp(EmitContext&, IR::Inst*) { - ASSERT_MSG(false, "should never happen"); +void EmitX64::EmitGetCarryFromOp(EmitContext& ctx, IR::Inst* inst) { + ctx.reg_alloc.RegisterPseudoOperation(inst); } -void EmitX64::EmitGetOverflowFromOp(EmitContext&, IR::Inst*) { - ASSERT_MSG(false, "should never happen"); +void EmitX64::EmitGetOverflowFromOp(EmitContext& ctx, IR::Inst* inst) { + ctx.reg_alloc.RegisterPseudoOperation(inst); } -void EmitX64::EmitGetGEFromOp(EmitContext&, IR::Inst*) { - ASSERT_MSG(false, "should never happen"); +void EmitX64::EmitGetGEFromOp(EmitContext& ctx, IR::Inst* inst) { + ctx.reg_alloc.RegisterPseudoOperation(inst); } -void EmitX64::EmitGetUpperFromOp(EmitContext&, IR::Inst*) { - ASSERT_MSG(false, "should never happen"); +void EmitX64::EmitGetUpperFromOp(EmitContext& ctx, IR::Inst* inst) { + ctx.reg_alloc.RegisterPseudoOperation(inst); } -void EmitX64::EmitGetLowerFromOp(EmitContext&, IR::Inst*) { - ASSERT_MSG(false, "should never happen"); +void EmitX64::EmitGetLowerFromOp(EmitContext& ctx, IR::Inst* inst) { + ctx.reg_alloc.RegisterPseudoOperation(inst); } void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) { + if (ctx.reg_alloc.IsValueLive(inst)) { + ctx.reg_alloc.RegisterPseudoOperation(inst); + return; + } + auto args = ctx.reg_alloc.GetArgumentInfo(inst); const int bitsize = [&] { @@ -190,6 +195,11 @@ void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) { + if (ctx.reg_alloc.IsValueLive(inst)) { + ctx.reg_alloc.RegisterPseudoOperation(inst); + return; + } + auto args = ctx.reg_alloc.GetArgumentInfo(inst); const int bitsize = [&] { diff --git a/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/backend/x64/emit_x64.h index fcf51a6c..c1921a9a 100644 --- a/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/backend/x64/emit_x64.h @@ -108,7 +108,7 @@ protected: BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size); void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target); - void EmitVerboseDebuggingOutput(RegAlloc& reg_alloc); + void EmitVerboseDebuggingOutput(RegAlloc& reg_alloc, const IR::Block& block); // Terminal instruction emitters void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); diff --git a/src/dynarmic/backend/x64/emit_x64_data_processing.cpp b/src/dynarmic/backend/x64/emit_x64_data_processing.cpp index 97bbdf52..396d3118 100644 --- a/src/dynarmic/backend/x64/emit_x64_data_processing.cpp +++ b/src/dynarmic/backend/x64/emit_x64_data_processing.cpp @@ -71,7 +71,6 @@ void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) { const Xbyak::Reg64 carry = ctx.reg_alloc.ScratchGpr(); code.setc(carry.cvt8()); ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); } ctx.reg_alloc.DefineValue(inst, result); @@ -332,7 +331,6 @@ void EmitX64::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) { } ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } else { ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); @@ -350,7 +348,6 @@ void EmitX64::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) { code.shr(result.cvt64(), 32); ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } } @@ -469,7 +466,6 @@ void EmitX64::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) { } ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } else { ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); @@ -486,7 +482,6 @@ void EmitX64::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) { code.setc(carry.cvt8()); ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } } @@ -603,7 +598,6 @@ void EmitX64::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) { } ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } else { ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); @@ -620,7 +614,6 @@ void EmitX64::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) { code.setc(carry.cvt8()); ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } } @@ -718,7 +711,6 @@ void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) { } ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } else { ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); @@ -737,7 +729,6 @@ void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) { code.L(end); ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); ctx.reg_alloc.DefineValue(inst, result); } } @@ -788,7 +779,6 @@ void EmitX64::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) { code.setc(carry); ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); } ctx.reg_alloc.DefineValue(inst, result); @@ -974,17 +964,14 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit code.lahf(); code.seto(code.al); ctx.reg_alloc.DefineValue(nzcv_inst, nzcv); - ctx.EraseInstruction(nzcv_inst); } if (carry_inst) { code.setc(carry); ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); } if (overflow_inst) { code.seto(overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow); - ctx.EraseInstruction(overflow_inst); } ctx.reg_alloc.DefineValue(inst, result); @@ -1064,7 +1051,6 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit code.lahf(); code.seto(code.al); ctx.reg_alloc.DefineValue(nzcv_inst, nzcv); - ctx.EraseInstruction(nzcv_inst); } if (carry_inst) { if (invert_output_carry) { @@ -1073,12 +1059,10 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit code.setc(carry); } ctx.reg_alloc.DefineValue(carry_inst, carry); - ctx.EraseInstruction(carry_inst); } if (overflow_inst) { code.seto(overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow); - ctx.EraseInstruction(overflow_inst); } if (!is_cmp) { ctx.reg_alloc.DefineValue(inst, result); diff --git a/src/dynarmic/backend/x64/emit_x64_packed.cpp b/src/dynarmic/backend/x64/emit_x64_packed.cpp index 7a710cd0..4cfad5ff 100644 --- a/src/dynarmic/backend/x64/emit_x64_packed.cpp +++ b/src/dynarmic/backend/x64/emit_x64_packed.cpp @@ -33,7 +33,6 @@ void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) { code.pxor(xmm_ge, ones); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); } ctx.reg_alloc.DefineValue(inst, xmm_a); @@ -56,7 +55,6 @@ void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) { code.pcmpgtb(xmm_ge, xmm0); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); } code.paddb(xmm_a, xmm_b); @@ -86,7 +84,6 @@ void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) { code.pxor(xmm_ge, ones); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); } else { const Xbyak::Xmm tmp_a = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm tmp_b = ctx.reg_alloc.ScratchXmm(); @@ -99,7 +96,6 @@ void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) { code.pcmpgtw(tmp_b, tmp_a); // *Signed* comparison! ctx.reg_alloc.DefineValue(ge_inst, tmp_b); - ctx.EraseInstruction(ge_inst); } } @@ -123,7 +119,6 @@ void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) { code.pcmpgtw(xmm_ge, xmm0); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); } code.paddw(xmm_a, xmm_b); @@ -146,7 +141,6 @@ void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) { code.pcmpeqb(xmm_ge, xmm_a); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); } code.psubb(xmm_a, xmm_b); @@ -171,7 +165,6 @@ void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) { code.pcmpgtb(xmm_ge, xmm0); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); } code.psubb(xmm_a, xmm_b); @@ -205,7 +198,6 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) { code.psubw(xmm_a, xmm_b); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); ctx.reg_alloc.DefineValue(inst, xmm_a); return; } @@ -226,7 +218,6 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) { code.psubw(xmm_a, xmm_b); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); ctx.reg_alloc.DefineValue(inst, xmm_a); } @@ -247,7 +238,6 @@ void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) { code.pcmpgtw(xmm_ge, xmm0); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); - ctx.EraseInstruction(ge_inst); } code.psubw(xmm_a, xmm_b); @@ -554,7 +544,6 @@ static void EmitPackedSubAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst code.or_(ge_sum, ge_diff); ctx.reg_alloc.DefineValue(ge_inst, ge_sum); - ctx.EraseInstruction(ge_inst); } if (is_halving) { diff --git a/src/dynarmic/backend/x64/emit_x64_saturation.cpp b/src/dynarmic/backend/x64/emit_x64_saturation.cpp index 707d99eb..24fb895b 100644 --- a/src/dynarmic/backend/x64/emit_x64_saturation.cpp +++ b/src/dynarmic/backend/x64/emit_x64_saturation.cpp @@ -64,7 +64,6 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) if constexpr (has_overflow_inst) { if (const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)) { ctx.reg_alloc.DefineValue(overflow_inst, overflow); - ctx.EraseInstruction(overflow_inst); } } else { code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8()); @@ -155,7 +154,6 @@ void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) { code.seta(overflow.cvt8()); ctx.reg_alloc.DefineValue(overflow_inst, overflow); - ctx.EraseInstruction(overflow_inst); } ctx.reg_alloc.DefineValue(inst, result); @@ -185,7 +183,6 @@ void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) { code.seta(overflow.cvt8()); ctx.reg_alloc.DefineValue(overflow_inst, overflow); - ctx.EraseInstruction(overflow_inst); } ctx.reg_alloc.DefineValue(inst, result); diff --git a/src/dynarmic/backend/x64/emit_x64_vector.cpp b/src/dynarmic/backend/x64/emit_x64_vector.cpp index 852ac742..4191f73c 100644 --- a/src/dynarmic/backend/x64/emit_x64_vector.cpp +++ b/src/dynarmic/backend/x64/emit_x64_vector.cpp @@ -3633,7 +3633,6 @@ void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) { } ctx.reg_alloc.DefineValue(upper_inst, result); - ctx.EraseInstruction(upper_inst); } if (lower_inst) { @@ -3645,7 +3644,6 @@ void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) { code.pmullw(result, y); } ctx.reg_alloc.DefineValue(lower_inst, result); - ctx.EraseInstruction(lower_inst); } } @@ -3663,7 +3661,6 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) { code.vpmulld(result, x, y); ctx.reg_alloc.DefineValue(lower_inst, result); - ctx.EraseInstruction(lower_inst); return; } @@ -3675,7 +3672,6 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm(); code.vpmulld(lower_result, x, y); ctx.reg_alloc.DefineValue(lower_inst, lower_result); - ctx.EraseInstruction(lower_inst); } const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); @@ -3687,7 +3683,6 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) { code.shufps(result, x, 0b11011101); ctx.reg_alloc.DefineValue(upper_inst, result); - ctx.EraseInstruction(upper_inst); return; } @@ -3730,11 +3725,9 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) { if (upper_inst) { ctx.reg_alloc.DefineValue(upper_inst, upper_result); - ctx.EraseInstruction(upper_inst); } if (lower_inst) { ctx.reg_alloc.DefineValue(lower_inst, lower_result); - ctx.EraseInstruction(lower_inst); } } @@ -5139,7 +5132,6 @@ void EmitX64::EmitVectorUnsignedMultiply16(EmitContext& ctx, IR::Inst* inst) { } ctx.reg_alloc.DefineValue(upper_inst, result); - ctx.EraseInstruction(upper_inst); } if (lower_inst) { @@ -5151,7 +5143,6 @@ void EmitX64::EmitVectorUnsignedMultiply16(EmitContext& ctx, IR::Inst* inst) { code.pmullw(result, y); } ctx.reg_alloc.DefineValue(lower_inst, result); - ctx.EraseInstruction(lower_inst); } } @@ -5169,7 +5160,6 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) { code.vpmulld(result, x, y); ctx.reg_alloc.DefineValue(lower_inst, result); - ctx.EraseInstruction(lower_inst); return; } @@ -5181,7 +5171,6 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm(); code.vpmulld(lower_result, x, y); ctx.reg_alloc.DefineValue(lower_inst, lower_result); - ctx.EraseInstruction(lower_inst); } const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); @@ -5193,7 +5182,6 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) { code.shufps(result, x, 0b11011101); ctx.reg_alloc.DefineValue(upper_inst, result); - ctx.EraseInstruction(upper_inst); return; } @@ -5224,11 +5212,9 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) { if (upper_inst) { ctx.reg_alloc.DefineValue(upper_inst, upper_result); - ctx.EraseInstruction(upper_inst); } if (lower_inst) { ctx.reg_alloc.DefineValue(lower_inst, lower_result); - ctx.EraseInstruction(lower_inst); } } diff --git a/src/dynarmic/backend/x64/reg_alloc.cpp b/src/dynarmic/backend/x64/reg_alloc.cpp index d37269a3..31764398 100644 --- a/src/dynarmic/backend/x64/reg_alloc.cpp +++ b/src/dynarmic/backend/x64/reg_alloc.cpp @@ -17,6 +17,7 @@ #include "dynarmic/backend/x64/abi.h" #include "dynarmic/backend/x64/stack_layout.h" #include "dynarmic/backend/x64/verbose_debugging_output.h" +#include "dynarmic/ir/basic_block.h" namespace Dynarmic::Backend::X64 { @@ -157,12 +158,14 @@ void HostLocInfo::AddValue(IR::Inst* inst) { max_bit_width = std::max(max_bit_width, GetBitWidth(inst->GetType())); } -void HostLocInfo::EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index) const { +void HostLocInfo::EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index, const IR::Block& block) const { using namespace Xbyak::util; for (IR::Inst* value : values) { + const auto inst_offset = std::distance(block.begin(), IR::Block::const_iterator(value)); code.mov(code.ABI_PARAM1, rsp); code.mov(code.ABI_PARAM2, host_loc_index); - code.mov(code.ABI_PARAM3, mcl::bit_cast(value)); + code.mov(code.ABI_PARAM3, mcl::bit_cast(inst_offset)); + code.mov(code.ABI_PARAM4, GetBitWidth(value->GetType())); code.CallFunction(PrintVerboseDebuggingOutputLine); } } @@ -271,6 +274,24 @@ RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) { return ret; } +void RegAlloc::RegisterPseudoOperation(IR::Inst* inst) { + ASSERT(IsValueLive(inst)); + + for (size_t i = 0; i < inst->NumArgs(); i++) { + const IR::Value arg = inst->GetArg(i); + if (!arg.IsImmediate() && !IsValuelessType(arg.GetType())) { + if (const auto loc = ValueLocation(arg.GetInst())) { + // May not necessarily have a value (e.g. CMP variant of Sub32). + LocInfo(*loc).AddArgReference(); + } + } + } +} + +bool RegAlloc::IsValueLive(IR::Inst* inst) const { + return !!ValueLocation(inst); +} + Xbyak::Reg64 RegAlloc::UseGpr(Argument& arg) { ASSERT(!arg.allocated); arg.allocated = true; @@ -494,9 +515,9 @@ void RegAlloc::AssertNoMoreUses() { ASSERT(std::all_of(hostloc_info.begin(), hostloc_info.end(), [](const auto& i) { return i.IsEmpty(); })); } -void RegAlloc::EmitVerboseDebuggingOutput() { +void RegAlloc::EmitVerboseDebuggingOutput(const IR::Block& block) { for (size_t i = 0; i < hostloc_info.size(); i++) { - hostloc_info[i].EmitVerboseDebuggingOutput(code, i); + hostloc_info[i].EmitVerboseDebuggingOutput(code, i, block); } } diff --git a/src/dynarmic/backend/x64/reg_alloc.h b/src/dynarmic/backend/x64/reg_alloc.h index b6cdf796..957c2b2a 100644 --- a/src/dynarmic/backend/x64/reg_alloc.h +++ b/src/dynarmic/backend/x64/reg_alloc.h @@ -23,6 +23,7 @@ namespace Dynarmic::IR { enum class AccType; +class Block; } // namespace Dynarmic::IR namespace Dynarmic::Backend::X64 { @@ -48,7 +49,7 @@ public: void AddValue(IR::Inst* inst); - void EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index) const; + void EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index, const IR::Block& block) const; private: // Current instruction state @@ -110,6 +111,8 @@ public: explicit RegAlloc(BlockOfCode& code, std::vector gpr_order, std::vector xmm_order); ArgumentInfo GetArgumentInfo(IR::Inst* inst); + void RegisterPseudoOperation(IR::Inst* inst); + bool IsValueLive(IR::Inst* inst) const; Xbyak::Reg64 UseGpr(Argument& arg); Xbyak::Xmm UseXmm(Argument& arg); @@ -145,7 +148,7 @@ public: void AssertNoMoreUses(); - void EmitVerboseDebuggingOutput(); + void EmitVerboseDebuggingOutput(const IR::Block& block); private: friend struct Argument; diff --git a/src/dynarmic/backend/x64/verbose_debugging_output.cpp b/src/dynarmic/backend/x64/verbose_debugging_output.cpp index 7c862783..3378786c 100644 --- a/src/dynarmic/backend/x64/verbose_debugging_output.cpp +++ b/src/dynarmic/backend/x64/verbose_debugging_output.cpp @@ -5,25 +5,52 @@ #include "dynarmic/backend/x64/verbose_debugging_output.h" +#include + #include #include "dynarmic/backend/x64/hostloc.h" namespace Dynarmic::Backend::X64 { -void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, u64 inst_addr) { - if (HostLocIsGPR(hostloc)) { - const u64 value = reg_data.gprs[HostLocToReg64(hostloc).getIdx()]; - fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, 0, value); - } else if (HostLocIsXMM(hostloc)) { - const Vector value = reg_data.xmms[HostLocToXmm(hostloc).getIdx()]; - fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]); - } else if (HostLocIsSpill(hostloc)) { - const Vector value = (*reg_data.spill)[static_cast(hostloc) - static_cast(HostLoc::FirstSpill)]; - fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]); - } else { - fmt::print("dynarmic debug: Invalid hostloc\n"); +void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, size_t inst_index, size_t bitsize) { + fmt::print("dynarmic debug: %{:05} = ", inst_index); + + Vector value = [&]() -> Vector { + if (HostLocIsGPR(hostloc)) { + return {reg_data.gprs[HostLocToReg64(hostloc).getIdx()], 0}; + } else if (HostLocIsXMM(hostloc)) { + return reg_data.xmms[HostLocToXmm(hostloc).getIdx()]; + } else if (HostLocIsSpill(hostloc)) { + return (*reg_data.spill)[static_cast(hostloc) - static_cast(HostLoc::FirstSpill)]; + } else { + fmt::print("invalid hostloc! "); + return {0, 0}; + } + }(); + + switch (bitsize) { + case 8: + fmt::print("{:02x}", value[0] & 0xff); + break; + case 16: + fmt::print("{:04x}", value[0] & 0xffff); + break; + case 32: + fmt::print("{:08x}", value[0] & 0xffffffff); + break; + case 64: + fmt::print("{:016x}", value[0]); + break; + case 128: + fmt::print("{:016x}{:016x}", value[1], value[0]); + break; + default: + fmt::print("invalid bitsize!"); + break; } + + fmt::print("\n"); } } // namespace Dynarmic::Backend::X64 diff --git a/src/dynarmic/backend/x64/verbose_debugging_output.h b/src/dynarmic/backend/x64/verbose_debugging_output.h index 95be7edf..412ce061 100644 --- a/src/dynarmic/backend/x64/verbose_debugging_output.h +++ b/src/dynarmic/backend/x64/verbose_debugging_output.h @@ -31,6 +31,6 @@ struct alignas(16) RegisterData { # pragma warning(pop) #endif -void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, u64 inst_addr); +void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, size_t inst_index, size_t bitsize); } // namespace Dynarmic::Backend::X64 diff --git a/tests/test_generator.cpp b/tests/test_generator.cpp index 00bfd73c..024db15c 100644 --- a/tests/test_generator.cpp +++ b/tests/test_generator.cpp @@ -663,6 +663,7 @@ static std::optional str2sz(char const* s) { int main(int argc, char* argv[]) { if (argc != 5) { fmt::print("Usage: {} \n", argv[0]); + return 1; } const auto seed = str2sz(argv[2]);