IR: Add IR instruction NZCVFromPackedFlags
This instruction expects NZCV to be in the high bits. i.e.: The positions they were in PSTATE.
This commit is contained in:
parent
0bb4474fb9
commit
8931ee346b
4 changed files with 30 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
|||
#include "backend_x64/block_of_code.h"
|
||||
#include "backend_x64/emit_x64.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/bit_util.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/variant_util.h"
|
||||
#include "frontend/ir/basic_block.h"
|
||||
|
@ -130,6 +131,28 @@ void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
|
|||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||
}
|
||||
|
||||
void EmitX64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
if (args[0].IsImmediate()) {
|
||||
Xbyak::Reg32 nzcv = ctx.reg_alloc.ScratchGpr().cvt32();
|
||||
u32 value = 0;
|
||||
value |= Common::Bit<31>(args[0].GetImmediateU32()) ? (1 << 15) : 0;
|
||||
value |= Common::Bit<30>(args[0].GetImmediateU32()) ? (1 << 14) : 0;
|
||||
value |= Common::Bit<29>(args[0].GetImmediateU32()) ? (1 << 8) : 0;
|
||||
value |= Common::Bit<28>(args[0].GetImmediateU32()) ? (1 << 0) : 0;
|
||||
code->mov(nzcv, value);
|
||||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||
} else {
|
||||
Xbyak::Reg32 nzcv = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
|
||||
// TODO: Optimize
|
||||
code->shr(nzcv, 28);
|
||||
code->imul(nzcv, nzcv, 0b00010000'10000001);
|
||||
code->and_(nzcv.cvt8(), 1);
|
||||
ctx.reg_alloc.DefineValue(inst, nzcv);
|
||||
}
|
||||
}
|
||||
|
||||
void EmitX64::EmitAddCycles(size_t cycles) {
|
||||
ASSERT(cycles < std::numeric_limits<u32>::max());
|
||||
code->sub(qword[r15 + code->GetJitStateInfo().offsetof_cycles_remaining], static_cast<u32>(cycles));
|
||||
|
|
|
@ -107,6 +107,10 @@ U32U64 IREmitter::ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b)
|
|||
}
|
||||
}
|
||||
|
||||
NZCV IREmitter::NZCVFromPackedFlags(const U32& a) {
|
||||
return Inst<NZCV>(Opcode::NZCVFromPackedFlags, a);
|
||||
}
|
||||
|
||||
NZCV IREmitter::NZCVFrom(const Value& value) {
|
||||
return Inst<NZCV>(Opcode::GetNZCVFromOp, value);
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ public:
|
|||
U64 ConditionalSelect(Cond cond, const U64& a, const U64& b);
|
||||
U32U64 ConditionalSelect(Cond cond, const U32U64& a, const U32U64& b);
|
||||
|
||||
NZCV NZCVFromPackedFlags(const U32& a);
|
||||
// This pseudo-instruction may only be added to instructions that support it.
|
||||
NZCV NZCVFrom(const Value& value);
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ OPCODE(GetOverflowFromOp, T::U1, T::U32
|
|||
OPCODE(GetGEFromOp, T::U32, T::U32 )
|
||||
OPCODE(GetNZCVFromOp, T::NZCVFlags, T::Opaque )
|
||||
|
||||
OPCODE(NZCVFromPackedFlags, T::NZCVFlags, T::U32 )
|
||||
|
||||
// Calculations
|
||||
OPCODE(Pack2x32To1x64, T::U64, T::U32, T::U32 )
|
||||
OPCODE(LeastSignificantWord, T::U32, T::U64 )
|
||||
|
|
Loading…
Reference in a new issue