[dynarmic] UseScratchGpr for path with immediate additions; lea materialisation with in-range s32 immediate (+immediate carry) (#2958)
Allows regalloc to more aggressively take on registers for immediate codepath; also uses lea for stc/adc (since carry can equate +1 in some cases) Signed-off-by: lizzie lizzie@eden-emu.dev Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2958 Reviewed-by: DraVee <dravee@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
c87986b276
commit
d0af14632e
|
|
@ -910,15 +910,15 @@ static Xbyak::Reg8 DoCarry(BlockOfCode& code, RegAlloc& reg_alloc, Argument& car
|
||||||
|
|
||||||
// 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) {
|
if (nzcv_out) {
|
||||||
return Xbyak::Reg64{-1};
|
const Xbyak::Reg64 nzcv = reg_alloc.ScratchGpr(code, HostLoc::RAX);
|
||||||
|
code.xor_(nzcv.cvt32(), nzcv.cvt32());
|
||||||
|
return nzcv;
|
||||||
}
|
}
|
||||||
const Xbyak::Reg64 nzcv = reg_alloc.ScratchGpr(code, HostLoc::RAX);
|
return Xbyak::Reg64{-1};
|
||||||
code.xor_(nzcv.cvt32(), nzcv.cvt32());
|
|
||||||
return nzcv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -929,19 +929,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(code, args[0]).changeBit(bitsize);
|
Xbyak::Reg const result = ctx.reg_alloc.UseScratchGpr(code, args[0]).changeBit(bitsize);
|
||||||
const Xbyak::Reg result = ctx.reg_alloc.ScratchGpr(code).changeBit(bitsize);
|
code.lea(result, code.ptr[result + args[1].GetImmediateS32()]);
|
||||||
|
|
||||||
code.lea(result, code.ptr[op1 + args[1].GetImmediateS32()]);
|
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(code, inst, result);
|
ctx.reg_alloc.DefineValue(code, inst, result);
|
||||||
} else {
|
} else {
|
||||||
const Xbyak::Reg op1 = ctx.reg_alloc.UseGpr(code, args[0]).changeBit(bitsize);
|
Xbyak::Reg const result = ctx.reg_alloc.UseScratchGpr(code, args[0]).changeBit(bitsize);
|
||||||
const Xbyak::Reg op2 = ctx.reg_alloc.UseGpr(code, args[1]).changeBit(bitsize);
|
Xbyak::Reg const op2 = ctx.reg_alloc.UseGpr(code, args[1]).changeBit(bitsize);
|
||||||
const Xbyak::Reg result = ctx.reg_alloc.ScratchGpr(code).changeBit(bitsize);
|
code.lea(result, code.ptr[result + op2]);
|
||||||
|
|
||||||
code.lea(result, code.ptr[op1 + op2]);
|
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(code, inst, result);
|
ctx.reg_alloc.DefineValue(code, inst, result);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -956,8 +950,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()) {
|
||||||
code.stc();
|
// In range for a valid LEA materialisation
|
||||||
code.adc(result, op_arg);
|
auto const in_range = s32(op_arg) >= -0x7ffffffe && s32(op_arg) <= 0x7ffffffe;
|
||||||
|
if (in_range && (carry_inst || nzcv_inst || overflow_inst)) {
|
||||||
|
code.stc();
|
||||||
|
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…
Reference in New Issue