diff --git a/src/dynarmic/backend/arm64/a32_address_space.cpp b/src/dynarmic/backend/arm64/a32_address_space.cpp index a8f89a83..686a45d5 100644 --- a/src/dynarmic/backend/arm64/a32_address_space.cpp +++ b/src/dynarmic/backend/arm64/a32_address_space.cpp @@ -166,6 +166,27 @@ void A32AddressSpace::EmitPrelude() { code.BR(X0); + prelude_info.step_code = code.ptr(); + ABI_PushRegisters(code, ABI_CALLEE_SAVE | (1 << 30), sizeof(StackLayout)); + + code.MOV(Xstate, X1); + code.MOV(Xhalt, X2); + + code.LDR(Wscratch0, Xstate, offsetof(A32JitState, upper_location_descriptor)); + code.AND(Wscratch0, Wscratch0, 0xffff0000); + code.MRS(Xscratch1, oaknut::SystemReg::FPCR); + code.STR(Wscratch1, SP, offsetof(StackLayout, save_host_fpcr)); + code.MSR(oaknut::SystemReg::FPCR, Xscratch0); + + oaknut::Label step_hr_loop; + code.l(step_hr_loop); + code.LDAXR(Wscratch0, Xhalt); + code.ORR(Wscratch0, Wscratch0, static_cast(HaltReason::Step)); + code.STLXR(Wscratch1, Wscratch0, Xhalt); + code.CBNZ(Wscratch1, step_hr_loop); + + code.BR(X0); + prelude_info.return_from_run_code = code.ptr(); code.LDR(Wscratch0, SP, offsetof(StackLayout, save_host_fpcr)); diff --git a/src/dynarmic/backend/arm64/a32_core.h b/src/dynarmic/backend/arm64/a32_core.h index 10ec3d7b..86f6f284 100644 --- a/src/dynarmic/backend/arm64/a32_core.h +++ b/src/dynarmic/backend/arm64/a32_core.h @@ -19,6 +19,12 @@ public: const auto entry_point = process.GetOrEmit(location_descriptor); return process.prelude_info.run_code(entry_point, &thread_ctx, halt_reason); } + + HaltReason Step(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { + const auto location_descriptor = A32::LocationDescriptor{thread_ctx.GetLocationDescriptor()}.SetSingleStepping(true); + const auto entry_point = process.GetOrEmit(location_descriptor); + return process.prelude_info.step_code(entry_point, &thread_ctx, halt_reason); + } }; } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/a32_interface.cpp b/src/dynarmic/backend/arm64/a32_interface.cpp index 74ed9cdc..69e65abb 100644 --- a/src/dynarmic/backend/arm64/a32_interface.cpp +++ b/src/dynarmic/backend/arm64/a32_interface.cpp @@ -79,11 +79,11 @@ struct Jit::Impl final { jit_interface->is_executing = false; }; - ASSERT_FALSE("Unimplemented"); + HaltReason hr = core.Step(current_address_space, current_state, &halt_reason); PerformRequestedCacheInvalidation(); - return HaltReason{}; + return hr; } void ClearCache() { diff --git a/src/dynarmic/backend/arm64/emit_arm64_a32.cpp b/src/dynarmic/backend/arm64/emit_arm64_a32.cpp index 5d0ce01e..415e9b55 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_a32.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_a32.cpp @@ -61,8 +61,8 @@ void EmitSetUpperLocationDescriptor(oaknut::CodeGenerator& code, EmitContext& ct void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location); - code.MOV(Xscratch0, terminal.next.Value()); - code.STUR(Xscratch0, Xstate, offsetof(A32JitState, regs) + sizeof(u32) * 15); + code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC()); + code.STR(Wscratch0, Xstate, offsetof(A32JitState, regs) + sizeof(u32) * 15); EmitRelocation(code, ctx, LinkTarget::ReturnFromRunCode); // TODO: Implement LinkBlock optimization @@ -71,8 +71,8 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Li void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location); - code.MOV(Xscratch0, terminal.next.Value()); - code.STUR(Xscratch0, Xstate, offsetof(A32JitState, regs) + sizeof(u32) * 15); + code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC()); + code.STR(Wscratch0, Xstate, offsetof(A32JitState, regs) + sizeof(u32) * 15); EmitRelocation(code, ctx, LinkTarget::ReturnFromRunCode); // TODO: Implement LinkBlockFast optimization