diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 05ca866e..5ee509ae 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -1674,6 +1674,9 @@ void EmitX64::EmitTerminal(IR::Terminal terminal, Arm::LocationDescriptor initia case 6: EmitTerminalIf(boost::get(terminal), initial_location); return; + case 7: + EmitTerminalCheckHalt(boost::get(terminal), initial_location); + return; default: ASSERT_MSG(0, "Invalid Terminal. Bad programmer."); return; @@ -1776,6 +1779,12 @@ void EmitX64::EmitTerminalIf(IR::Term::If terminal, Arm::LocationDescriptor init EmitTerminal(terminal.then_, initial_location); } +void EmitX64::EmitTerminalCheckHalt(IR::Term::CheckHalt terminal, Arm::LocationDescriptor initial_location) { + code->CMP(8, MDisp(R15, offsetof(JitState, halt_requested)), Imm8(0)); + code->J_CC(CC_NE, code->GetReturnFromRunCodeAddress(), true); + EmitTerminal(terminal.else_, initial_location); +} + void EmitX64::Patch(Arm::LocationDescriptor desc, CodePtr bb) { u8* const save_code_ptr = code->GetWritableCodePtr(); diff --git a/src/backend_x64/emit_x64.h b/src/backend_x64/emit_x64.h index b33125db..2e292d04 100644 --- a/src/backend_x64/emit_x64.h +++ b/src/backend_x64/emit_x64.h @@ -64,6 +64,7 @@ private: void EmitTerminalLinkBlockFast(IR::Term::LinkBlockFast terminal, Arm::LocationDescriptor initial_location); void EmitTerminalPopRSBHint(IR::Term::PopRSBHint terminal, Arm::LocationDescriptor initial_location); void EmitTerminalIf(IR::Term::If terminal, Arm::LocationDescriptor initial_location); + void EmitTerminalCheckHalt(IR::Term::CheckHalt terminal, Arm::LocationDescriptor initial_location); void Patch(Arm::LocationDescriptor desc, CodePtr bb); // Per-block state diff --git a/src/backend_x64/interface_x64.cpp b/src/backend_x64/interface_x64.cpp index 7f48d0e2..a6a2f6c4 100644 --- a/src/backend_x64/interface_x64.cpp +++ b/src/backend_x64/interface_x64.cpp @@ -112,10 +112,10 @@ size_t Jit::Run(size_t cycle_count) { is_executing = true; SCOPE_EXIT({ this->is_executing = false; }); - halt_requested = false; + impl->jit_state.halt_requested = false; size_t cycles_executed = 0; - while (cycles_executed < cycle_count && !halt_requested) { + while (cycles_executed < cycle_count && !impl->jit_state.halt_requested) { cycles_executed += impl->Execute(cycle_count - cycles_executed); } @@ -136,7 +136,7 @@ void Jit::Reset() { void Jit::HaltExecution() { ASSERT(is_executing); - halt_requested = true; + impl->jit_state.halt_requested = true; // TODO: Uh do other stuff to JitState pls. } diff --git a/src/backend_x64/jitstate.h b/src/backend_x64/jitstate.h index b50e5751..8c8f104a 100644 --- a/src/backend_x64/jitstate.h +++ b/src/backend_x64/jitstate.h @@ -32,6 +32,7 @@ struct JitState { u32 guest_MXCSR = 0x00001f80; u32 save_host_MXCSR = 0; s64 cycles_remaining = 0; + bool halt_requested = false; // Exclusive state static constexpr u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; diff --git a/src/frontend/ir/ir.h b/src/frontend/ir/ir.h index d4be966d..14abb50e 100644 --- a/src/frontend/ir/ir.h +++ b/src/frontend/ir/ir.h @@ -166,6 +166,7 @@ struct LinkBlockFast { struct PopRSBHint {}; struct If; +struct CheckHalt; /// A Terminal is the terminal instruction in a MicroBlock. using Terminal = boost::variant< Invalid, @@ -174,7 +175,8 @@ using Terminal = boost::variant< LinkBlock, LinkBlockFast, PopRSBHint, - boost::recursive_wrapper + boost::recursive_wrapper, + boost::recursive_wrapper >; /** @@ -188,6 +190,15 @@ struct If { Terminal else_; }; +/** + * This terminal instruction checks if a halt was requested. If it wasn't, else_ is + * executed. + */ +struct CheckHalt { + CheckHalt(Terminal else_) : else_(else_) {} + Terminal else_; +}; + } // namespace Term using Term::Terminal; diff --git a/src/frontend/translate/translate_arm/exception_generating.cpp b/src/frontend/translate/translate_arm/exception_generating.cpp index 50f83029..a1ce2a82 100644 --- a/src/frontend/translate/translate_arm/exception_generating.cpp +++ b/src/frontend/translate/translate_arm/exception_generating.cpp @@ -17,9 +17,10 @@ bool ArmTranslatorVisitor::arm_SVC(Cond cond, Imm24 imm24) { u32 imm32 = imm24; // SVC # if (ConditionPassed(cond)) { + ir.PushRSB(ir.current_location.AdvancePC(4)); ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4)); ir.CallSupervisor(ir.Imm32(imm32)); - ir.SetTerm(IR::Term::ReturnToDispatch{}); + ir.SetTerm(IR::Term::CheckHalt{IR::Term::PopRSBHint{}}); return false; } return true; diff --git a/src/frontend/translate/translate_thumb.cpp b/src/frontend/translate/translate_thumb.cpp index 701584e9..c77c492c 100644 --- a/src/frontend/translate/translate_thumb.cpp +++ b/src/frontend/translate/translate_thumb.cpp @@ -773,8 +773,9 @@ struct ThumbTranslatorVisitor final { u32 imm32 = imm8; // SVC # ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 2)); + ir.PushRSB(ir.current_location.AdvancePC(2)); ir.CallSupervisor(ir.Imm32(imm32)); - ir.SetTerm(IR::Term::ReturnToDispatch{}); + ir.SetTerm(IR::Term::CheckHalt{IR::Term::PopRSBHint{}}); return false; } diff --git a/src/interface/interface.h b/src/interface/interface.h index 09fa8b5c..b790b110 100644 --- a/src/interface/interface.h +++ b/src/interface/interface.h @@ -99,7 +99,6 @@ public: std::string Disassemble(const Arm::LocationDescriptor& descriptor); private: - bool halt_requested = false; bool is_executing = false; struct Impl;