backend/x64: Improve verbose debugging output
This commit is contained in:
parent
c0813cf2a5
commit
f0ebdf278c
14 changed files with 97 additions and 78 deletions
|
@ -148,7 +148,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||||
reg_alloc.EndOfAllocScope();
|
reg_alloc.EndOfAllocScope();
|
||||||
|
|
||||||
if (conf.very_verbose_debugging_output) {
|
if (conf.very_verbose_debugging_output) {
|
||||||
EmitVerboseDebuggingOutput(reg_alloc);
|
EmitVerboseDebuggingOutput(reg_alloc, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ private:
|
||||||
Optimization::ConstantPropagation(ir_block);
|
Optimization::ConstantPropagation(ir_block);
|
||||||
Optimization::DeadCodeElimination(ir_block);
|
Optimization::DeadCodeElimination(ir_block);
|
||||||
}
|
}
|
||||||
|
Optimization::IdentityRemovalPass(ir_block);
|
||||||
Optimization::VerificationPass(ir_block);
|
Optimization::VerificationPass(ir_block);
|
||||||
return emitter.Emit(ir_block);
|
return emitter.Emit(ir_block);
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||||
ctx.reg_alloc.EndOfAllocScope();
|
ctx.reg_alloc.EndOfAllocScope();
|
||||||
|
|
||||||
if (conf.very_verbose_debugging_output) {
|
if (conf.very_verbose_debugging_output) {
|
||||||
EmitVerboseDebuggingOutput(reg_alloc);
|
EmitVerboseDebuggingOutput(reg_alloc, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
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));
|
code.sub(rsp, sizeof(RegisterData));
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
if (rsp.getIdx() == 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.lea(rax, ptr[rsp + sizeof(RegisterData) + offsetof(StackLayout, spill)]);
|
||||||
code.mov(xword[rsp + offsetof(RegisterData, spill)], rax);
|
code.mov(xword[rsp + offsetof(RegisterData, spill)], rax);
|
||||||
|
|
||||||
reg_alloc.EmitVerboseDebuggingOutput();
|
reg_alloc.EmitVerboseDebuggingOutput(block);
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
if (rsp.getIdx() == 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});
|
PushRSBHelper(loc_desc_reg, index_reg, IR::LocationDescriptor{unique_hash_of_target});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetCarryFromOp(EmitContext&, IR::Inst*) {
|
void EmitX64::EmitGetCarryFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
ASSERT_MSG(false, "should never happen");
|
ctx.reg_alloc.RegisterPseudoOperation(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetOverflowFromOp(EmitContext&, IR::Inst*) {
|
void EmitX64::EmitGetOverflowFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
ASSERT_MSG(false, "should never happen");
|
ctx.reg_alloc.RegisterPseudoOperation(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetGEFromOp(EmitContext&, IR::Inst*) {
|
void EmitX64::EmitGetGEFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
ASSERT_MSG(false, "should never happen");
|
ctx.reg_alloc.RegisterPseudoOperation(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetUpperFromOp(EmitContext&, IR::Inst*) {
|
void EmitX64::EmitGetUpperFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
ASSERT_MSG(false, "should never happen");
|
ctx.reg_alloc.RegisterPseudoOperation(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetLowerFromOp(EmitContext&, IR::Inst*) {
|
void EmitX64::EmitGetLowerFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
ASSERT_MSG(false, "should never happen");
|
ctx.reg_alloc.RegisterPseudoOperation(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* 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);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
const int bitsize = [&] {
|
const int bitsize = [&] {
|
||||||
|
@ -190,6 +195,11 @@ void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitGetNZCVFromOp(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);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
const int bitsize = [&] {
|
const int bitsize = [&] {
|
||||||
|
|
|
@ -108,7 +108,7 @@ protected:
|
||||||
BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size);
|
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 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
|
// Terminal instruction emitters
|
||||||
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||||
|
|
|
@ -71,7 +71,6 @@ void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) {
|
||||||
const Xbyak::Reg64 carry = ctx.reg_alloc.ScratchGpr();
|
const Xbyak::Reg64 carry = ctx.reg_alloc.ScratchGpr();
|
||||||
code.setc(carry.cvt8());
|
code.setc(carry.cvt8());
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
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.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
} else {
|
} else {
|
||||||
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
|
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);
|
code.shr(result.cvt64(), 32);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
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.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
} else {
|
} else {
|
||||||
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
|
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
|
||||||
|
@ -486,7 +482,6 @@ void EmitX64::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.setc(carry.cvt8());
|
code.setc(carry.cvt8());
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
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.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
} else {
|
} else {
|
||||||
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
|
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
|
||||||
|
@ -620,7 +614,6 @@ void EmitX64::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.setc(carry.cvt8());
|
code.setc(carry.cvt8());
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
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.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
} else {
|
} else {
|
||||||
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
|
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
|
||||||
|
@ -737,7 +729,6 @@ void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.L(end);
|
code.L(end);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,7 +779,6 @@ void EmitX64::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.setc(carry);
|
code.setc(carry);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
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.lahf();
|
||||||
code.seto(code.al);
|
code.seto(code.al);
|
||||||
ctx.reg_alloc.DefineValue(nzcv_inst, nzcv);
|
ctx.reg_alloc.DefineValue(nzcv_inst, nzcv);
|
||||||
ctx.EraseInstruction(nzcv_inst);
|
|
||||||
}
|
}
|
||||||
if (carry_inst) {
|
if (carry_inst) {
|
||||||
code.setc(carry);
|
code.setc(carry);
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
}
|
}
|
||||||
if (overflow_inst) {
|
if (overflow_inst) {
|
||||||
code.seto(overflow);
|
code.seto(overflow);
|
||||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||||
ctx.EraseInstruction(overflow_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
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.lahf();
|
||||||
code.seto(code.al);
|
code.seto(code.al);
|
||||||
ctx.reg_alloc.DefineValue(nzcv_inst, nzcv);
|
ctx.reg_alloc.DefineValue(nzcv_inst, nzcv);
|
||||||
ctx.EraseInstruction(nzcv_inst);
|
|
||||||
}
|
}
|
||||||
if (carry_inst) {
|
if (carry_inst) {
|
||||||
if (invert_output_carry) {
|
if (invert_output_carry) {
|
||||||
|
@ -1073,12 +1059,10 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
|
||||||
code.setc(carry);
|
code.setc(carry);
|
||||||
}
|
}
|
||||||
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
ctx.reg_alloc.DefineValue(carry_inst, carry);
|
||||||
ctx.EraseInstruction(carry_inst);
|
|
||||||
}
|
}
|
||||||
if (overflow_inst) {
|
if (overflow_inst) {
|
||||||
code.seto(overflow);
|
code.seto(overflow);
|
||||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||||
ctx.EraseInstruction(overflow_inst);
|
|
||||||
}
|
}
|
||||||
if (!is_cmp) {
|
if (!is_cmp) {
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
|
|
@ -33,7 +33,6 @@ void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pxor(xmm_ge, ones);
|
code.pxor(xmm_ge, ones);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, xmm_a);
|
ctx.reg_alloc.DefineValue(inst, xmm_a);
|
||||||
|
@ -56,7 +55,6 @@ void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pcmpgtb(xmm_ge, xmm0);
|
code.pcmpgtb(xmm_ge, xmm0);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code.paddb(xmm_a, xmm_b);
|
code.paddb(xmm_a, xmm_b);
|
||||||
|
@ -86,7 +84,6 @@ void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pxor(xmm_ge, ones);
|
code.pxor(xmm_ge, ones);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
} else {
|
} else {
|
||||||
const Xbyak::Xmm tmp_a = ctx.reg_alloc.ScratchXmm();
|
const Xbyak::Xmm tmp_a = ctx.reg_alloc.ScratchXmm();
|
||||||
const Xbyak::Xmm tmp_b = 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!
|
code.pcmpgtw(tmp_b, tmp_a); // *Signed* comparison!
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, tmp_b);
|
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);
|
code.pcmpgtw(xmm_ge, xmm0);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code.paddw(xmm_a, xmm_b);
|
code.paddw(xmm_a, xmm_b);
|
||||||
|
@ -146,7 +141,6 @@ void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pcmpeqb(xmm_ge, xmm_a);
|
code.pcmpeqb(xmm_ge, xmm_a);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code.psubb(xmm_a, xmm_b);
|
code.psubb(xmm_a, xmm_b);
|
||||||
|
@ -171,7 +165,6 @@ void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pcmpgtb(xmm_ge, xmm0);
|
code.pcmpgtb(xmm_ge, xmm0);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code.psubb(xmm_a, xmm_b);
|
code.psubb(xmm_a, xmm_b);
|
||||||
|
@ -205,7 +198,6 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.psubw(xmm_a, xmm_b);
|
code.psubw(xmm_a, xmm_b);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, xmm_a);
|
ctx.reg_alloc.DefineValue(inst, xmm_a);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +218,6 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.psubw(xmm_a, xmm_b);
|
code.psubw(xmm_a, xmm_b);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
ctx.reg_alloc.DefineValue(inst, xmm_a);
|
ctx.reg_alloc.DefineValue(inst, xmm_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +238,6 @@ void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pcmpgtw(xmm_ge, xmm0);
|
code.pcmpgtw(xmm_ge, xmm0);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
code.psubw(xmm_a, xmm_b);
|
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);
|
code.or_(ge_sum, ge_diff);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(ge_inst, ge_sum);
|
ctx.reg_alloc.DefineValue(ge_inst, ge_sum);
|
||||||
ctx.EraseInstruction(ge_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_halving) {
|
if (is_halving) {
|
||||||
|
|
|
@ -64,7 +64,6 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst)
|
||||||
if constexpr (has_overflow_inst) {
|
if constexpr (has_overflow_inst) {
|
||||||
if (const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)) {
|
if (const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)) {
|
||||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||||
ctx.EraseInstruction(overflow_inst);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8());
|
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());
|
code.seta(overflow.cvt8());
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||||
ctx.EraseInstruction(overflow_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
@ -185,7 +183,6 @@ void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.seta(overflow.cvt8());
|
code.seta(overflow.cvt8());
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||||
ctx.EraseInstruction(overflow_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
|
|
@ -3633,7 +3633,6 @@ void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(upper_inst, result);
|
ctx.reg_alloc.DefineValue(upper_inst, result);
|
||||||
ctx.EraseInstruction(upper_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lower_inst) {
|
if (lower_inst) {
|
||||||
|
@ -3645,7 +3644,6 @@ void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pmullw(result, y);
|
code.pmullw(result, y);
|
||||||
}
|
}
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, result);
|
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);
|
code.vpmulld(result, x, y);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, result);
|
ctx.reg_alloc.DefineValue(lower_inst, result);
|
||||||
ctx.EraseInstruction(lower_inst);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3675,7 +3672,6 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm();
|
const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm();
|
||||||
code.vpmulld(lower_result, x, y);
|
code.vpmulld(lower_result, x, y);
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, lower_result);
|
ctx.reg_alloc.DefineValue(lower_inst, lower_result);
|
||||||
ctx.EraseInstruction(lower_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
|
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);
|
code.shufps(result, x, 0b11011101);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(upper_inst, result);
|
ctx.reg_alloc.DefineValue(upper_inst, result);
|
||||||
ctx.EraseInstruction(upper_inst);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3730,11 +3725,9 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
||||||
if (upper_inst) {
|
if (upper_inst) {
|
||||||
ctx.reg_alloc.DefineValue(upper_inst, upper_result);
|
ctx.reg_alloc.DefineValue(upper_inst, upper_result);
|
||||||
ctx.EraseInstruction(upper_inst);
|
|
||||||
}
|
}
|
||||||
if (lower_inst) {
|
if (lower_inst) {
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, lower_result);
|
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.reg_alloc.DefineValue(upper_inst, result);
|
||||||
ctx.EraseInstruction(upper_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lower_inst) {
|
if (lower_inst) {
|
||||||
|
@ -5151,7 +5143,6 @@ void EmitX64::EmitVectorUnsignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.pmullw(result, y);
|
code.pmullw(result, y);
|
||||||
}
|
}
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, result);
|
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);
|
code.vpmulld(result, x, y);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, result);
|
ctx.reg_alloc.DefineValue(lower_inst, result);
|
||||||
ctx.EraseInstruction(lower_inst);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5181,7 +5171,6 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm();
|
const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm();
|
||||||
code.vpmulld(lower_result, x, y);
|
code.vpmulld(lower_result, x, y);
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, lower_result);
|
ctx.reg_alloc.DefineValue(lower_inst, lower_result);
|
||||||
ctx.EraseInstruction(lower_inst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
|
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);
|
code.shufps(result, x, 0b11011101);
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(upper_inst, result);
|
ctx.reg_alloc.DefineValue(upper_inst, result);
|
||||||
ctx.EraseInstruction(upper_inst);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5224,11 +5212,9 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
||||||
if (upper_inst) {
|
if (upper_inst) {
|
||||||
ctx.reg_alloc.DefineValue(upper_inst, upper_result);
|
ctx.reg_alloc.DefineValue(upper_inst, upper_result);
|
||||||
ctx.EraseInstruction(upper_inst);
|
|
||||||
}
|
}
|
||||||
if (lower_inst) {
|
if (lower_inst) {
|
||||||
ctx.reg_alloc.DefineValue(lower_inst, lower_result);
|
ctx.reg_alloc.DefineValue(lower_inst, lower_result);
|
||||||
ctx.EraseInstruction(lower_inst);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "dynarmic/backend/x64/abi.h"
|
#include "dynarmic/backend/x64/abi.h"
|
||||||
#include "dynarmic/backend/x64/stack_layout.h"
|
#include "dynarmic/backend/x64/stack_layout.h"
|
||||||
#include "dynarmic/backend/x64/verbose_debugging_output.h"
|
#include "dynarmic/backend/x64/verbose_debugging_output.h"
|
||||||
|
#include "dynarmic/ir/basic_block.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
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()));
|
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;
|
using namespace Xbyak::util;
|
||||||
for (IR::Inst* value : values) {
|
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_PARAM1, rsp);
|
||||||
code.mov(code.ABI_PARAM2, host_loc_index);
|
code.mov(code.ABI_PARAM2, host_loc_index);
|
||||||
code.mov(code.ABI_PARAM3, mcl::bit_cast<u64>(value));
|
code.mov(code.ABI_PARAM3, mcl::bit_cast<u64>(inst_offset));
|
||||||
|
code.mov(code.ABI_PARAM4, GetBitWidth(value->GetType()));
|
||||||
code.CallFunction(PrintVerboseDebuggingOutputLine);
|
code.CallFunction(PrintVerboseDebuggingOutputLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,6 +274,24 @@ RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
|
||||||
return ret;
|
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) {
|
Xbyak::Reg64 RegAlloc::UseGpr(Argument& arg) {
|
||||||
ASSERT(!arg.allocated);
|
ASSERT(!arg.allocated);
|
||||||
arg.allocated = true;
|
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(); }));
|
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++) {
|
for (size_t i = 0; i < hostloc_info.size(); i++) {
|
||||||
hostloc_info[i].EmitVerboseDebuggingOutput(code, i);
|
hostloc_info[i].EmitVerboseDebuggingOutput(code, i, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
namespace Dynarmic::IR {
|
namespace Dynarmic::IR {
|
||||||
enum class AccType;
|
enum class AccType;
|
||||||
|
class Block;
|
||||||
} // namespace Dynarmic::IR
|
} // namespace Dynarmic::IR
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
@ -48,7 +49,7 @@ public:
|
||||||
|
|
||||||
void AddValue(IR::Inst* inst);
|
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:
|
private:
|
||||||
// Current instruction state
|
// Current instruction state
|
||||||
|
@ -110,6 +111,8 @@ public:
|
||||||
explicit RegAlloc(BlockOfCode& code, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order);
|
explicit RegAlloc(BlockOfCode& code, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order);
|
||||||
|
|
||||||
ArgumentInfo GetArgumentInfo(IR::Inst* inst);
|
ArgumentInfo GetArgumentInfo(IR::Inst* inst);
|
||||||
|
void RegisterPseudoOperation(IR::Inst* inst);
|
||||||
|
bool IsValueLive(IR::Inst* inst) const;
|
||||||
|
|
||||||
Xbyak::Reg64 UseGpr(Argument& arg);
|
Xbyak::Reg64 UseGpr(Argument& arg);
|
||||||
Xbyak::Xmm UseXmm(Argument& arg);
|
Xbyak::Xmm UseXmm(Argument& arg);
|
||||||
|
@ -145,7 +148,7 @@ public:
|
||||||
|
|
||||||
void AssertNoMoreUses();
|
void AssertNoMoreUses();
|
||||||
|
|
||||||
void EmitVerboseDebuggingOutput();
|
void EmitVerboseDebuggingOutput(const IR::Block& block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct Argument;
|
friend struct Argument;
|
||||||
|
|
|
@ -5,25 +5,52 @@
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/verbose_debugging_output.h"
|
#include "dynarmic/backend/x64/verbose_debugging_output.h"
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/hostloc.h"
|
#include "dynarmic/backend/x64/hostloc.h"
|
||||||
|
|
||||||
namespace Dynarmic::Backend::X64 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, u64 inst_addr) {
|
void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, size_t inst_index, size_t bitsize) {
|
||||||
if (HostLocIsGPR(hostloc)) {
|
fmt::print("dynarmic debug: %{:05} = ", inst_index);
|
||||||
const u64 value = reg_data.gprs[HostLocToReg64(hostloc).getIdx()];
|
|
||||||
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, 0, value);
|
Vector value = [&]() -> Vector {
|
||||||
} else if (HostLocIsXMM(hostloc)) {
|
if (HostLocIsGPR(hostloc)) {
|
||||||
const Vector value = reg_data.xmms[HostLocToXmm(hostloc).getIdx()];
|
return {reg_data.gprs[HostLocToReg64(hostloc).getIdx()], 0};
|
||||||
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]);
|
} else if (HostLocIsXMM(hostloc)) {
|
||||||
} else if (HostLocIsSpill(hostloc)) {
|
return reg_data.xmms[HostLocToXmm(hostloc).getIdx()];
|
||||||
const Vector value = (*reg_data.spill)[static_cast<size_t>(hostloc) - static_cast<size_t>(HostLoc::FirstSpill)];
|
} else if (HostLocIsSpill(hostloc)) {
|
||||||
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]);
|
return (*reg_data.spill)[static_cast<size_t>(hostloc) - static_cast<size_t>(HostLoc::FirstSpill)];
|
||||||
} else {
|
} else {
|
||||||
fmt::print("dynarmic debug: Invalid hostloc\n");
|
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
|
} // namespace Dynarmic::Backend::X64
|
||||||
|
|
|
@ -31,6 +31,6 @@ struct alignas(16) RegisterData {
|
||||||
# pragma warning(pop)
|
# pragma warning(pop)
|
||||||
#endif
|
#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
|
} // namespace Dynarmic::Backend::X64
|
||||||
|
|
|
@ -663,6 +663,7 @@ static std::optional<size_t> str2sz(char const* s) {
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc != 5) {
|
if (argc != 5) {
|
||||||
fmt::print("Usage: {} <thumb|arm|a64> <seed> <instruction_count> <iteration_count>\n", argv[0]);
|
fmt::print("Usage: {} <thumb|arm|a64> <seed> <instruction_count> <iteration_count>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto seed = str2sz(argv[2]);
|
const auto seed = str2sz(argv[2]);
|
||||||
|
|
Loading…
Reference in a new issue