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);
|
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) {
|
void EmitX64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(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) {
|
NZCV IREmitter::NZCVFromPackedFlags(const U32& a) {
|
||||||
return Inst<NZCV>(Opcode::NZCVFromPackedFlags, a);
|
return Inst<NZCV>(Opcode::NZCVFromPackedFlags, a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ public:
|
||||||
NZCV ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b);
|
NZCV ConditionalSelect(Cond cond, const NZCV& a, const NZCV& b);
|
||||||
U32U64 ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b);
|
U32U64 ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b);
|
||||||
|
|
||||||
|
U1 GetCFlagFromNZCV(const NZCV& nzcv);
|
||||||
NZCV NZCVFromPackedFlags(const U32& a);
|
NZCV NZCVFromPackedFlags(const U32& a);
|
||||||
// This pseudo-instruction may only be added to instructions that support it.
|
// This pseudo-instruction may only be added to instructions that support it.
|
||||||
NZCV NZCVFrom(const Value& value);
|
NZCV NZCVFrom(const Value& value);
|
||||||
|
|
|
@ -92,6 +92,7 @@ OPCODE(GetNZFromOp, NZCV, Opaq
|
||||||
OPCODE(GetUpperFromOp, U128, Opaque )
|
OPCODE(GetUpperFromOp, U128, Opaque )
|
||||||
OPCODE(GetLowerFromOp, U128, Opaque )
|
OPCODE(GetLowerFromOp, U128, Opaque )
|
||||||
|
|
||||||
|
OPCODE(GetCFlagFromNZCV, U1, NZCV )
|
||||||
OPCODE(NZCVFromPackedFlags, NZCV, U32 )
|
OPCODE(NZCVFromPackedFlags, NZCV, U32 )
|
||||||
|
|
||||||
// Calculations
|
// Calculations
|
||||||
|
|
|
@ -182,6 +182,14 @@ void A32GetSetElimination(IR::Block& block, A32GetSetEliminationOptions opt) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::Opcode::A32GetCFlag: {
|
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);
|
do_get(cpsr_info.c, inst);
|
||||||
// ensure source is not deleted
|
// ensure source is not deleted
|
||||||
cpsr_info.nzc = {};
|
cpsr_info.nzc = {};
|
||||||
|
|
Loading…
Reference in a new issue