Browse Source

[dynarmic] UseScratchGpr for path with immediate additions; lea materialisation with in-range s32 immediate (+immediate carry)

dynarmic-coproc
lizzie 2 months ago
committed by crueter
parent
commit
810ab0c658
  1. 28
      src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp

28
src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp

@ -911,15 +911,15 @@ static Xbyak::Reg8 DoCarry(RegAlloc& reg_alloc, Argument& carry_in, IR::Inst* ca
// AL contains flags (after LAHF + SETO sequence) // AL contains flags (after LAHF + SETO sequence)
static Xbyak::Reg64 DoNZCV(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* nzcv_out) { static Xbyak::Reg64 DoNZCV(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* nzcv_out) {
if (!nzcv_out) {
return Xbyak::Reg64{-1};
}
if (nzcv_out) {
const Xbyak::Reg64 nzcv = reg_alloc.ScratchGpr(HostLoc::RAX); const Xbyak::Reg64 nzcv = reg_alloc.ScratchGpr(HostLoc::RAX);
code.xor_(nzcv.cvt32(), nzcv.cvt32()); code.xor_(nzcv.cvt32(), nzcv.cvt32());
return nzcv; return nzcv;
}
return Xbyak::Reg64{-1};
} }
static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bitsize) {
static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, size_t bitsize) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp); const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp);
@ -930,19 +930,13 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
// Consider using LEA. // Consider using LEA.
if (!carry_inst && !overflow_inst && !nzcv_inst && carry_in.IsImmediate() && !carry_in.GetImmediateU1()) { if (!carry_inst && !overflow_inst && !nzcv_inst && carry_in.IsImmediate() && !carry_in.GetImmediateU1()) {
if (args[1].IsImmediate() && args[1].FitsInImmediateS32()) { if (args[1].IsImmediate() && args[1].FitsInImmediateS32()) {
const Xbyak::Reg op1 = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
const Xbyak::Reg result = ctx.reg_alloc.ScratchGpr().changeBit(bitsize);
code.lea(result, code.ptr[op1 + args[1].GetImmediateS32()]);
const Xbyak::Reg result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(bitsize);
code.lea(result, code.ptr[result + args[1].GetImmediateS32()]);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} else { } else {
const Xbyak::Reg op1 = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
const Xbyak::Reg result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(bitsize);
const Xbyak::Reg op2 = ctx.reg_alloc.UseGpr(args[1]).changeBit(bitsize); const Xbyak::Reg op2 = ctx.reg_alloc.UseGpr(args[1]).changeBit(bitsize);
const Xbyak::Reg result = ctx.reg_alloc.ScratchGpr().changeBit(bitsize);
code.lea(result, code.ptr[op1 + op2]);
code.lea(result, code.ptr[result + op2]);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
return; return;
@ -957,8 +951,14 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
const u32 op_arg = args[1].GetImmediateU32(); const u32 op_arg = args[1].GetImmediateU32();
if (carry_in.IsImmediate()) { if (carry_in.IsImmediate()) {
if (carry_in.GetImmediateU1()) { if (carry_in.GetImmediateU1()) {
// In range for a valid LEA materialisation
auto const in_range = s32(op_arg) >= -0x7ffffffe && s32(op_arg) <= 0x7ffffffe;
if (in_range && (carry_inst || nzcv_inst || overflow_inst)) {
code.stc(); code.stc();
code.adc(result, op_arg); code.adc(result, op_arg);
} else {
code.lea(result, code.ptr[result + op_arg + 1]);
}
} else { } else {
code.add(result, op_arg); code.add(result, op_arg);
} }

Loading…
Cancel
Save