From 597a8be5d59f55bbb138d8fa4dde9f65b7f7ddd3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 6 Mar 2019 13:54:09 -0500 Subject: [PATCH] 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. --- src/backend/x64/a64_emit_x64.cpp | 15 +++++++++++++++ src/frontend/A64/ir_emitter.cpp | 8 ++++++++ src/frontend/A64/ir_emitter.h | 2 ++ src/frontend/ir/microinstruction.cpp | 2 ++ src/frontend/ir/opcodes.inc | 2 ++ 5 files changed, 29 insertions(+) diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index a73cceb2..27dd1d76 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -368,6 +368,21 @@ void A64EmitX64::EmitA64GetCFlag(A64EmitContext& ctx, IR::Inst* inst) { 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) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 to_store = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); diff --git a/src/frontend/A64/ir_emitter.cpp b/src/frontend/A64/ir_emitter.cpp index 3a274b96..ef949d8c 100644 --- a/src/frontend/A64/ir_emitter.cpp +++ b/src/frontend/A64/ir_emitter.cpp @@ -29,6 +29,14 @@ IR::U1 IREmitter::GetCFlag() { return Inst(Opcode::A64GetCFlag); } +IR::U32 IREmitter::GetNZCVRaw() { + return Inst(Opcode::A64GetNZCVRaw); +} + +void IREmitter::SetNZCVRaw(IR::U32 value) { + Inst(Opcode::A64SetNZCVRaw, value); +} + void IREmitter::SetNZCV(const IR::NZCV& nzcv) { Inst(Opcode::A64SetNZCV, nzcv); } diff --git a/src/frontend/A64/ir_emitter.h b/src/frontend/A64/ir_emitter.h index 9983f4b4..ac56448d 100644 --- a/src/frontend/A64/ir_emitter.h +++ b/src/frontend/A64/ir_emitter.h @@ -36,6 +36,8 @@ public: void SetCheckBit(const IR::U1& value); IR::U1 GetCFlag(); + IR::U32 GetNZCVRaw(); + void SetNZCVRaw(IR::U32 value); void SetNZCV(const IR::NZCV& nzcv); void OrQC(const IR::U1& value); diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index c3849bab..10257e54 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -124,6 +124,7 @@ bool Inst::ReadsFromCPSR() const { case Opcode::A32GetVFlag: case Opcode::A32GetGEFlags: case Opcode::A64GetCFlag: + case Opcode::A64GetNZCVRaw: case Opcode::ConditionalSelect32: case Opcode::ConditionalSelect64: case Opcode::ConditionalSelectNZCV: @@ -146,6 +147,7 @@ bool Inst::WritesToCPSR() const { case Opcode::A32OrQFlag: case Opcode::A32SetGEFlags: case Opcode::A32SetGEFlagsCompressed: + case Opcode::A64SetNZCVRaw: case Opcode::A64SetNZCV: return true; diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 256eeba0..1705334c 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -38,6 +38,8 @@ A32OPC(SetFpscrNZCV, Void, NZCV // A64 Context getters/setters A64OPC(SetCheckBit, Void, U1 ) A64OPC(GetCFlag, U1, ) +A64OPC(GetNZCVRaw, U32, ) +A64OPC(SetNZCVRaw, Void, U32 ) A64OPC(SetNZCV, Void, NZCV ) A64OPC(GetW, U32, A64Reg ) A64OPC(GetX, U64, A64Reg )