Convert NZCV to C flag where able

This commit is contained in:
Merry 2022-07-23 11:22:48 +01:00
parent 6bcc424e1a
commit a2b3199adf
5 changed files with 30 additions and 0 deletions

View file

@ -188,6 +188,22 @@ void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, nzcv);
}
void EmitX64::EmitGetCFlagFromNZCV(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (args[0].IsImmediate()) {
const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32();
const u32 value = (args[0].GetImmediateU32() >> 8) & 1;
code.mov(result, value);
ctx.reg_alloc.DefineValue(inst, result);
} else {
const Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
code.shr(result, 8);
code.and_(result, 1);
ctx.reg_alloc.DefineValue(inst, result);
}
}
void EmitX64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);

View file

@ -135,6 +135,10 @@ U32U64 IREmitter::ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b)
}
}
U1 IREmitter::GetCFlagFromNZCV(const NZCV& nzcv) {
return Inst<U1>(Opcode::GetCFlagFromNZCV, nzcv);
}
NZCV IREmitter::NZCVFromPackedFlags(const U32& a) {
return Inst<NZCV>(Opcode::NZCVFromPackedFlags, a);
}

View file

@ -101,6 +101,7 @@ public:
NZCV ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b);
U32U64 ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b);
U1 GetCFlagFromNZCV(const NZCV& nzcv);
NZCV NZCVFromPackedFlags(const U32& a);
// This pseudo-instruction may only be added to instructions that support it.
NZCV NZCVFrom(const Value& value);

View file

@ -92,6 +92,7 @@ OPCODE(GetNZFromOp, NZCV, Opaq
OPCODE(GetUpperFromOp, U128, Opaque )
OPCODE(GetLowerFromOp, U128, Opaque )
OPCODE(GetCFlagFromNZCV, U1, NZCV )
OPCODE(NZCVFromPackedFlags, NZCV, U32 )
// Calculations

View file

@ -182,6 +182,14 @@ void A32GetSetElimination(IR::Block& block, A32GetSetEliminationOptions opt) {
break;
}
case IR::Opcode::A32GetCFlag: {
if (cpsr_info.c.register_value.IsEmpty() && cpsr_info.nzcv.register_value.GetType() == IR::Type::NZCVFlags) {
ir.SetInsertionPointBefore(inst);
IR::U1 c = ir.GetCFlagFromNZCV(IR::NZCV{cpsr_info.nzcv.register_value});
inst->ReplaceUsesWith(c);
cpsr_info.c.register_value = c;
break;
}
do_get(cpsr_info.c, inst);
// ensure source is not deleted
cpsr_info.nzc = {};