emit_x64_data_processing: EmitSub: Use cmp where possible
This commit is contained in:
parent
e926f0b393
commit
8c4463a0c1
2 changed files with 17 additions and 7 deletions
|
@ -1080,19 +1080,28 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
auto& carry_in = args[2];
|
auto& carry_in = args[2];
|
||||||
|
const bool is_cmp = inst->UseCount() == !!carry_inst + !!overflow_inst + !!nzcv_inst && carry_in.IsImmediate() && carry_in.GetImmediateU1();
|
||||||
|
|
||||||
const Xbyak::Reg64 nzcv = DoNZCV(code, ctx.reg_alloc, nzcv_inst);
|
const Xbyak::Reg64 nzcv = DoNZCV(code, ctx.reg_alloc, nzcv_inst);
|
||||||
const Xbyak::Reg result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(bitsize);
|
const Xbyak::Reg result = (is_cmp ? ctx.reg_alloc.UseGpr(args[0]) : ctx.reg_alloc.UseScratchGpr(args[0])).changeBit(bitsize);
|
||||||
const Xbyak::Reg8 carry = DoCarry(ctx.reg_alloc, carry_in, carry_inst);
|
const Xbyak::Reg8 carry = DoCarry(ctx.reg_alloc, carry_in, carry_inst);
|
||||||
const Xbyak::Reg8 overflow = overflow_inst ? ctx.reg_alloc.ScratchGpr().cvt8() : Xbyak::Reg8{-1};
|
const Xbyak::Reg8 overflow = overflow_inst ? ctx.reg_alloc.ScratchGpr().cvt8() : Xbyak::Reg8{-1};
|
||||||
|
|
||||||
// TODO: Consider using LEA.
|
// TODO: Consider using LEA.
|
||||||
// TODO: Optimize CMP case.
|
|
||||||
// Note that x64 CF is inverse of what the ARM carry flag is here.
|
// Note that x64 CF is inverse of what the ARM carry flag is here.
|
||||||
|
|
||||||
bool invert_output_carry = true;
|
bool invert_output_carry = true;
|
||||||
|
|
||||||
if (args[1].IsImmediate() && args[1].GetType() == IR::Type::U32) {
|
if (is_cmp) {
|
||||||
|
if (args[1].IsImmediate() && args[1].GetType() == IR::Type::U32) {
|
||||||
|
const u32 op_arg = args[1].GetImmediateU32();
|
||||||
|
code.cmp(result, op_arg);
|
||||||
|
} else {
|
||||||
|
OpArg op_arg = ctx.reg_alloc.UseOpArg(args[1]);
|
||||||
|
op_arg.setBit(bitsize);
|
||||||
|
code.cmp(result, *op_arg);
|
||||||
|
}
|
||||||
|
} else if (args[1].IsImmediate() && args[1].GetType() == IR::Type::U32) {
|
||||||
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()) {
|
||||||
|
@ -1146,8 +1155,9 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
|
||||||
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
ctx.reg_alloc.DefineValue(overflow_inst, overflow);
|
||||||
ctx.EraseInstruction(overflow_inst);
|
ctx.EraseInstruction(overflow_inst);
|
||||||
}
|
}
|
||||||
|
if (!is_cmp) {
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitSub32(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitSub32(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ bool TranslatorVisitor::CCMP_reg(bool sf, Reg Rm, Cond cond, Reg Rn, Imm<4> nzcv
|
||||||
const IR::U32U64 operand1 = X(datasize, Rn);
|
const IR::U32U64 operand1 = X(datasize, Rn);
|
||||||
const IR::U32U64 operand2 = X(datasize, Rm);
|
const IR::U32U64 operand2 = X(datasize, Rm);
|
||||||
|
|
||||||
const IR::NZCV then_flags = ir.NZCVFrom(ir.AddWithCarry(operand1, ir.Not(operand2), ir.Imm1(1)));
|
const IR::NZCV then_flags = ir.NZCVFrom(ir.SubWithCarry(operand1, operand2, ir.Imm1(1)));
|
||||||
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags));
|
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags));
|
||||||
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags));
|
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags));
|
||||||
return true;
|
return true;
|
||||||
|
@ -53,7 +53,7 @@ bool TranslatorVisitor::CCMP_imm(bool sf, Imm<5> imm5, Cond cond, Reg Rn, Imm<4>
|
||||||
const IR::U32U64 operand1 = X(datasize, Rn);
|
const IR::U32U64 operand1 = X(datasize, Rn);
|
||||||
const IR::U32U64 operand2 = I(datasize, imm5.ZeroExtend<u32>());
|
const IR::U32U64 operand2 = I(datasize, imm5.ZeroExtend<u32>());
|
||||||
|
|
||||||
const IR::NZCV then_flags = ir.NZCVFrom(ir.AddWithCarry(operand1, ir.Not(operand2), ir.Imm1(1)));
|
const IR::NZCV then_flags = ir.NZCVFrom(ir.SubWithCarry(operand1, operand2, ir.Imm1(1)));
|
||||||
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags));
|
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags));
|
||||||
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags));
|
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags));
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue