diff --git a/src/backend_x64/block_of_code.cpp b/src/backend_x64/block_of_code.cpp index 3bb8945e..2aa6210d 100644 --- a/src/backend_x64/block_of_code.cpp +++ b/src/backend_x64/block_of_code.cpp @@ -85,22 +85,22 @@ void BlockOfCode::RunCode(JitState* jit_state, size_t cycles_to_run) const { run_code(jit_state); } -void BlockOfCode::ReturnFromRunCode(bool MXCSR_switch) { +void BlockOfCode::ReturnFromRunCode(bool mxcsr_already_exited) { size_t index = 0; - if (!MXCSR_switch) - index |= NO_SWITCH_MXCSR; + if (mxcsr_already_exited) + index |= MXCSR_ALREADY_EXITED; jmp(return_from_run_code[index]); } -void BlockOfCode::ForceReturnFromRunCode(bool MXCSR_switch) { +void BlockOfCode::ForceReturnFromRunCode(bool mxcsr_already_exited) { size_t index = FORCE_RETURN; - if (!MXCSR_switch) - index |= NO_SWITCH_MXCSR; + if (mxcsr_already_exited) + index |= MXCSR_ALREADY_EXITED; jmp(return_from_run_code[index]); } void BlockOfCode::GenRunCode() { - Xbyak::Label loop; + Xbyak::Label loop, enter_mxcsr_then_loop; align(); run_code = getCurr(); @@ -119,22 +119,23 @@ void BlockOfCode::GenRunCode() { mov(r15, ABI_PARAM1); + L(enter_mxcsr_then_loop); + SwitchMxcsrOnEntry(); L(loop); mov(ABI_PARAM1, u64(lookup_block_arg)); CallFunction(lookup_block); - SwitchMxcsrOnEntry(); jmp(ABI_RETURN); // Return from run code variants - const auto emit_return_from_run_code = [this, &loop](bool no_mxcsr_switch, bool force_return){ - if (!no_mxcsr_switch) { - SwitchMxcsrOnExit(); - } - + const auto emit_return_from_run_code = [this, &loop, &enter_mxcsr_then_loop](bool mxcsr_already_exited, bool force_return){ if (!force_return) { cmp(qword[r15 + offsetof(JitState, cycles_remaining)], 0); - jg(loop); + jg(mxcsr_already_exited ? enter_mxcsr_then_loop : loop); + } + + if (!mxcsr_already_exited) { + SwitchMxcsrOnExit(); } mov(ABI_PARAM1, qword[r15 + offsetof(JitState, cycles_to_run)]); @@ -150,7 +151,7 @@ void BlockOfCode::GenRunCode() { emit_return_from_run_code(false, false); align(); - return_from_run_code[NO_SWITCH_MXCSR] = getCurr(); + return_from_run_code[MXCSR_ALREADY_EXITED] = getCurr(); emit_return_from_run_code(true, false); align(); @@ -158,7 +159,7 @@ void BlockOfCode::GenRunCode() { emit_return_from_run_code(false, true); align(); - return_from_run_code[NO_SWITCH_MXCSR | FORCE_RETURN] = getCurr(); + return_from_run_code[MXCSR_ALREADY_EXITED | FORCE_RETURN] = getCurr(); emit_return_from_run_code(true, true); } diff --git a/src/backend_x64/block_of_code.h b/src/backend_x64/block_of_code.h index a1cf4055..d2dd2182 100644 --- a/src/backend_x64/block_of_code.h +++ b/src/backend_x64/block_of_code.h @@ -34,9 +34,9 @@ public: /// Runs emulated code for approximately `cycles_to_run` cycles. void RunCode(JitState* jit_state, size_t cycles_to_run) const; /// Code emitter: Returns to dispatcher - void ReturnFromRunCode(bool MXCSR_switch = true); + void ReturnFromRunCode(bool mxcsr_already_exited = false); /// Code emitter: Returns to dispatcher, forces return to host - void ForceReturnFromRunCode(bool MXCSR_switch = true); + void ForceReturnFromRunCode(bool mxcsr_already_exited = false); /// Code emitter: Makes guest MXCSR the current MXCSR void SwitchMxcsrOnEntry(); /// Code emitter: Makes saved host MXCSR the current MXCSR @@ -145,7 +145,7 @@ private: using RunCodeFuncType = void(*)(JitState*); RunCodeFuncType run_code = nullptr; - static constexpr size_t NO_SWITCH_MXCSR = 1 << 0; + static constexpr size_t MXCSR_ALREADY_EXITED = 1 << 0; static constexpr size_t FORCE_RETURN = 1 << 1; std::array return_from_run_code; void GenRunCode(); diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index f027417a..2c84ce7c 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -3371,7 +3371,7 @@ void EmitX64::EmitTerminal(IR::Term::Interpret terminal, IR::LocationDescriptor code->mov(MJitStateReg(Arm::Reg::PC), code->ABI_PARAM1.cvt32()); code->SwitchMxcsrOnExit(); code->CallFunction(cb.InterpreterFallback); - code->ReturnFromRunCode(false); // TODO: Check cycles + code->ReturnFromRunCode(true); // TODO: Check cycles } void EmitX64::EmitTerminal(IR::Term::ReturnToDispatch, IR::LocationDescriptor) {