diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index 26aec5ea..a908b995 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -468,6 +468,21 @@ void A64EmitX64::EmitA64SetFPSR(A64EmitContext& ctx, IR::Inst* inst) { code.ldmxcsr(code.dword[code.r15 + offsetof(A64JitState, guest_MXCSR)]); } +void A64EmitX64::EmitA64OrQC(A64EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + + if (args[0].IsImmediate()) { + if (!args[0].GetImmediateU1()) + return; + + code.mov(code.byte[code.r15 + offsetof(A64JitState, fpsr_qc)], u8(1)); + return; + } + + const Xbyak::Reg8 to_store = ctx.reg_alloc.UseGpr(args[1]).cvt8(); + code.or_(code.byte[code.r15 + offsetof(A64JitState, fpsr_qc)], to_store); +} + void A64EmitX64::EmitA64SetPC(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto addr = qword[r15 + offsetof(A64JitState, pc)]; diff --git a/src/frontend/A64/ir_emitter.cpp b/src/frontend/A64/ir_emitter.cpp index 24703f8c..5a0a850c 100644 --- a/src/frontend/A64/ir_emitter.cpp +++ b/src/frontend/A64/ir_emitter.cpp @@ -33,6 +33,10 @@ void IREmitter::SetNZCV(const IR::NZCV& nzcv) { Inst(Opcode::A64SetNZCV, nzcv); } +void IREmitter::OrQC(const IR::U1& value) { + Inst(Opcode::A64OrQC, value); +} + void IREmitter::CallSupervisor(u32 imm) { Inst(Opcode::A64CallSupervisor, Imm32(imm)); } diff --git a/src/frontend/A64/ir_emitter.h b/src/frontend/A64/ir_emitter.h index 1a47f644..b10eaed7 100644 --- a/src/frontend/A64/ir_emitter.h +++ b/src/frontend/A64/ir_emitter.h @@ -38,6 +38,7 @@ public: void SetCheckBit(const IR::U1& value); IR::U1 GetCFlag(); void SetNZCV(const IR::NZCV& nzcv); + void OrQC(const IR::U1& value); void CallSupervisor(u32 imm); void ExceptionRaised(Exception exception); diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp index 7bc1fd4c..06c8c932 100644 --- a/src/frontend/ir/microinstruction.cpp +++ b/src/frontend/ir/microinstruction.cpp @@ -341,6 +341,7 @@ bool Inst::ReadsFromFPSRCumulativeSaturationBit() const { bool Inst::WritesToFPSRCumulativeSaturationBit() const { switch (op) { + case Opcode::A64OrQC: case Opcode::VectorSignedSaturatedNarrowToSigned16: case Opcode::VectorSignedSaturatedNarrowToSigned32: case Opcode::VectorSignedSaturatedNarrowToSigned64: diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 2cbe0ca2..b09f6ba2 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -59,6 +59,7 @@ A64OPC(SetQ, T::Void, T::A64Vec, A64OPC(SetSP, T::Void, T::U64 ) A64OPC(SetFPCR, T::Void, T::U32 ) A64OPC(SetFPSR, T::Void, T::U32 ) +A64OPC(OrQC, T::Void, T::U1 ) A64OPC(SetPC, T::Void, T::U64 ) A64OPC(CallSupervisor, T::Void, T::U32 ) A64OPC(ExceptionRaised, T::Void, T::U64, T::U64 )