Convert NZCV to C flag where able
This commit is contained in:
parent
6bcc424e1a
commit
a2b3199adf
5 changed files with 30 additions and 0 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
Loading…
Reference in a new issue