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:
MerryMage 2018-02-03 13:34:40 +00:00
parent 0bb4474fb9
commit 8931ee346b
4 changed files with 30 additions and 0 deletions

View file

@ -9,6 +9,7 @@
#include "backend_x64/block_of_code.h" #include "backend_x64/block_of_code.h"
#include "backend_x64/emit_x64.h" #include "backend_x64/emit_x64.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/variant_util.h" #include "common/variant_util.h"
#include "frontend/ir/basic_block.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); 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) { void EmitX64::EmitAddCycles(size_t cycles) {
ASSERT(cycles < std::numeric_limits<u32>::max()); ASSERT(cycles < std::numeric_limits<u32>::max());
code->sub(qword[r15 + code->GetJitStateInfo().offsetof_cycles_remaining], static_cast<u32>(cycles)); code->sub(qword[r15 + code->GetJitStateInfo().offsetof_cycles_remaining], static_cast<u32>(cycles));

View file

@ -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) { NZCV IREmitter::NZCVFrom(const Value& value) {
return Inst<NZCV>(Opcode::GetNZCVFromOp, value); return Inst<NZCV>(Opcode::GetNZCVFromOp, value);
} }

View file

@ -81,6 +81,7 @@ public:
U64 ConditionalSelect(Cond cond, const U64& a, const U64& b); U64 ConditionalSelect(Cond cond, const U64& a, const U64& b);
U32U64 ConditionalSelect(Cond cond, const U32U64& a, const U32U64& 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. // This pseudo-instruction may only be added to instructions that support it.
NZCV NZCVFrom(const Value& value); NZCV NZCVFrom(const Value& value);

View file

@ -68,6 +68,8 @@ OPCODE(GetOverflowFromOp, T::U1, T::U32
OPCODE(GetGEFromOp, T::U32, T::U32 ) OPCODE(GetGEFromOp, T::U32, T::U32 )
OPCODE(GetNZCVFromOp, T::NZCVFlags, T::Opaque ) OPCODE(GetNZCVFromOp, T::NZCVFlags, T::Opaque )
OPCODE(NZCVFromPackedFlags, T::NZCVFlags, T::U32 )
// Calculations // Calculations
OPCODE(Pack2x32To1x64, T::U64, T::U32, T::U32 ) OPCODE(Pack2x32To1x64, T::U64, T::U32, T::U32 )
OPCODE(LeastSignificantWord, T::U32, T::U64 ) OPCODE(LeastSignificantWord, T::U32, T::U64 )