diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 5b1c20d7..5733d610 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -260,6 +260,21 @@ void EmitX64::EmitSetVFlag(IR::Block&, IR::Inst* inst) { } } +void EmitX64::EmitOrQFlag(IR::Block&, IR::Inst* inst) { + constexpr size_t flag_bit = 27; + constexpr u32 flag_mask = 1u << flag_bit; + IR::Value arg = inst->GetArg(0); + if (arg.IsImmediate()) { + if (arg.GetU1()) + code->OR(32, MJitStateCpsr(), Imm32(flag_mask)); + } else { + X64Reg to_store = reg_alloc.UseScratchRegister(arg.GetInst(), any_gpr); + + code->SHL(32, R(to_store), Imm8(flag_bit)); + code->OR(32, MJitStateCpsr(), R(to_store)); + } +} + void EmitX64::EmitBXWritePC(IR::Block&, IR::Inst* inst) { const u32 T_bit = 1 << 5; auto arg = inst->GetArg(0); diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 7ae2a262..716c6736 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -118,6 +118,10 @@ void IREmitter::SetVFlag(const IR::Value& value) { Inst(IR::Opcode::SetVFlag, {value}); } +void IREmitter::OrQFlag(const IR::Value& value) { + Inst(IR::Opcode::OrQFlag, {value}); +} + IR::Value IREmitter::Pack2x32To1x64(const IR::Value& lo, const IR::Value& hi) { return Inst(IR::Opcode::Pack2x32To1x64, {lo, hi}); diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index cb121353..544ab42d 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -55,6 +55,7 @@ public: void SetZFlag(const IR::Value& value); void SetCFlag(const IR::Value& value); void SetVFlag(const IR::Value& value); + void OrQFlag(const IR::Value& value); IR::Value Pack2x32To1x64(const IR::Value& lo, const IR::Value& hi); IR::Value LeastSignificantWord(const IR::Value& value); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 3857d351..ec45d734 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -18,6 +18,7 @@ OPCODE(GetCFlag, T::U1, OPCODE(SetCFlag, T::Void, T::U1 ) OPCODE(GetVFlag, T::U1, ) OPCODE(SetVFlag, T::Void, T::U1 ) +OPCODE(OrQFlag, T::Void, T::U1 ) OPCODE(BXWritePC, T::Void, T::U32 ) OPCODE(CallSupervisor, T::Void, T::U32 )