ir: Add A64-specific opcodes for getting and setting raw NZCV values

This will be necessary to implement the flag manipulation and flag
format instructions.
This commit is contained in:
Lioncash 2019-03-06 13:54:09 -05:00 committed by MerryMage
parent 4f937c1ee1
commit 597a8be5d5
5 changed files with 29 additions and 0 deletions

View file

@ -368,6 +368,21 @@ void A64EmitX64::EmitA64GetCFlag(A64EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
void A64EmitX64::EmitA64GetNZCVRaw(A64EmitContext& ctx, IR::Inst* inst) {
const Xbyak::Reg32 nzcv_raw = ctx.reg_alloc.ScratchGpr().cvt32();
code.mov(nzcv_raw, dword[r15 + offsetof(A64JitState, CPSR_nzcv)]);
ctx.reg_alloc.DefineValue(inst, nzcv_raw);
}
void A64EmitX64::EmitA64SetNZCVRaw(A64EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg32 nzcv_raw = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
code.and_(nzcv_raw, 0xF0000000);
code.mov(dword[r15 + offsetof(A64JitState, CPSR_nzcv)], nzcv_raw);
}
void A64EmitX64::EmitA64SetNZCV(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetNZCV(A64EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 to_store = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); Xbyak::Reg32 to_store = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();

View file

@ -29,6 +29,14 @@ IR::U1 IREmitter::GetCFlag() {
return Inst<IR::U1>(Opcode::A64GetCFlag); return Inst<IR::U1>(Opcode::A64GetCFlag);
} }
IR::U32 IREmitter::GetNZCVRaw() {
return Inst<IR::U32>(Opcode::A64GetNZCVRaw);
}
void IREmitter::SetNZCVRaw(IR::U32 value) {
Inst(Opcode::A64SetNZCVRaw, value);
}
void IREmitter::SetNZCV(const IR::NZCV& nzcv) { void IREmitter::SetNZCV(const IR::NZCV& nzcv) {
Inst(Opcode::A64SetNZCV, nzcv); Inst(Opcode::A64SetNZCV, nzcv);
} }

View file

@ -36,6 +36,8 @@ public:
void SetCheckBit(const IR::U1& value); void SetCheckBit(const IR::U1& value);
IR::U1 GetCFlag(); IR::U1 GetCFlag();
IR::U32 GetNZCVRaw();
void SetNZCVRaw(IR::U32 value);
void SetNZCV(const IR::NZCV& nzcv); void SetNZCV(const IR::NZCV& nzcv);
void OrQC(const IR::U1& value); void OrQC(const IR::U1& value);

View file

@ -124,6 +124,7 @@ bool Inst::ReadsFromCPSR() const {
case Opcode::A32GetVFlag: case Opcode::A32GetVFlag:
case Opcode::A32GetGEFlags: case Opcode::A32GetGEFlags:
case Opcode::A64GetCFlag: case Opcode::A64GetCFlag:
case Opcode::A64GetNZCVRaw:
case Opcode::ConditionalSelect32: case Opcode::ConditionalSelect32:
case Opcode::ConditionalSelect64: case Opcode::ConditionalSelect64:
case Opcode::ConditionalSelectNZCV: case Opcode::ConditionalSelectNZCV:
@ -146,6 +147,7 @@ bool Inst::WritesToCPSR() const {
case Opcode::A32OrQFlag: case Opcode::A32OrQFlag:
case Opcode::A32SetGEFlags: case Opcode::A32SetGEFlags:
case Opcode::A32SetGEFlagsCompressed: case Opcode::A32SetGEFlagsCompressed:
case Opcode::A64SetNZCVRaw:
case Opcode::A64SetNZCV: case Opcode::A64SetNZCV:
return true; return true;

View file

@ -38,6 +38,8 @@ A32OPC(SetFpscrNZCV, Void, NZCV
// A64 Context getters/setters // A64 Context getters/setters
A64OPC(SetCheckBit, Void, U1 ) A64OPC(SetCheckBit, Void, U1 )
A64OPC(GetCFlag, U1, ) A64OPC(GetCFlag, U1, )
A64OPC(GetNZCVRaw, U32, )
A64OPC(SetNZCVRaw, Void, U32 )
A64OPC(SetNZCV, Void, NZCV ) A64OPC(SetNZCV, Void, NZCV )
A64OPC(GetW, U32, A64Reg ) A64OPC(GetW, U32, A64Reg )
A64OPC(GetX, U64, A64Reg ) A64OPC(GetX, U64, A64Reg )