diff --git a/src/backend/A64/a32_emit_a64.cpp b/src/backend/A64/a32_emit_a64.cpp index c22bcabd..25483e05 100644 --- a/src/backend/A64/a32_emit_a64.cpp +++ b/src/backend/A64/a32_emit_a64.cpp @@ -551,6 +551,12 @@ void A32EmitA64::EmitA32SetZFlag(A32EmitContext& ctx, IR::Inst* inst) { code.STR(INDEX_UNSIGNED, nzcv, X28, offsetof(A32JitState, CPSR_nzcv)); } +void A32EmitA64::EmitA32SetCheckBit(A32EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + const ARM64Reg to_store = DecodeReg(ctx.reg_alloc.UseGpr(args[0])); + code.STRB(INDEX_UNSIGNED, to_store, X28, offsetof(A32JitState, check_bit)); +} + void A32EmitA64::EmitA32GetCFlag(A32EmitContext& ctx, IR::Inst* inst) { Arm64Gen::ARM64Reg result = DecodeReg(ctx.reg_alloc.ScratchGpr()); code.LDR(INDEX_UNSIGNED, result, X28, offsetof(A32JitState, CPSR_nzcv)); @@ -1355,8 +1361,13 @@ void A32EmitA64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor EmitTerminal(terminal.then_, initial_location); } -void A32EmitA64::EmitTerminalImpl(IR::Term::CheckBit, IR::LocationDescriptor) { - ASSERT_MSG(false, "Term::CheckBit should never be emitted by the A32 frontend"); +void A32EmitA64::EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) { + FixupBranch fail; + code.LDRB(INDEX_UNSIGNED, DecodeReg(code.ABI_SCRATCH1), X28, offsetof(A32JitState, check_bit)); + fail = code.CBZ(DecodeReg(code.ABI_SCRATCH1)); + EmitTerminal(terminal.then_, initial_location); + code.SetJumpTarget(fail); + EmitTerminal(terminal.else_, initial_location); } void A32EmitA64::EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) { diff --git a/src/backend/A64/a32_jitstate.h b/src/backend/A64/a32_jitstate.h index 0af16273..6967a97b 100644 --- a/src/backend/A64/a32_jitstate.h +++ b/src/backend/A64/a32_jitstate.h @@ -51,6 +51,7 @@ struct A32JitState { s64 cycles_to_run = 0; s64 cycles_remaining = 0; bool halt_requested = false; + bool check_bit = false; // Exclusive state static constexpr u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; diff --git a/src/backend/A64/opcodes.inc b/src/backend/A64/opcodes.inc index 1e16736e..a8646602 100644 --- a/src/backend/A64/opcodes.inc +++ b/src/backend/A64/opcodes.inc @@ -5,6 +5,7 @@ OPCODE(Identity, Opaque, Opaq OPCODE(Breakpoint, Void, ) // A32 Context getters/setters +A32OPC(SetCheckBit, Void, U1 ) A32OPC(GetRegister, U32, A32Reg ) A32OPC(GetExtendedRegister32, U32, A32ExtReg ) A32OPC(GetExtendedRegister64, U64, A32ExtReg )