diff --git a/src/backend_x64/block_of_code.cpp b/src/backend_x64/block_of_code.cpp index d19a8d6c..78b66129 100644 --- a/src/backend_x64/block_of_code.cpp +++ b/src/backend_x64/block_of_code.cpp @@ -40,11 +40,11 @@ size_t BlockOfCode::RunCode(JitState* jit_state, CodePtr basic_block, size_t cyc return cycles_to_run - jit_state->cycles_remaining; // Return number of cycles actually run. } -void BlockOfCode::ReturnFromRunCode() { - STMXCSR(MDisp(R15, offsetof(JitState, guest_MXCSR))); - LDMXCSR(MDisp(R15, offsetof(JitState, save_host_MXCSR))); - MOV(64, R(RSP), MDisp(R15, offsetof(JitState, save_host_RSP))); +void BlockOfCode::ReturnFromRunCode(bool MXCSR_switch) { + if (MXCSR_switch) + SwitchMxcsrOnExit(); + MOV(64, R(RSP), MDisp(R15, offsetof(JitState, save_host_RSP))); ABI_PopRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8); RET(); } @@ -78,10 +78,18 @@ void BlockOfCode::GenRunCode() { MOV(64, R(R15), R(ABI_PARAM1)); MOV(64, MDisp(R15, offsetof(JitState, save_host_RSP)), R(RSP)); + SwitchMxcsrOnEntry(); + JMPptr(R(ABI_PARAM2)); +} + +void BlockOfCode::SwitchMxcsrOnEntry() { STMXCSR(MDisp(R15, offsetof(JitState, save_host_MXCSR))); LDMXCSR(MDisp(R15, offsetof(JitState, guest_MXCSR))); +} - JMPptr(R(ABI_PARAM2)); +void BlockOfCode::SwitchMxcsrOnExit() { + STMXCSR(MDisp(R15, offsetof(JitState, guest_MXCSR))); + LDMXCSR(MDisp(R15, offsetof(JitState, save_host_MXCSR))); } } // namespace BackendX64 diff --git a/src/backend_x64/block_of_code.h b/src/backend_x64/block_of_code.h index a145b65d..e916de36 100644 --- a/src/backend_x64/block_of_code.h +++ b/src/backend_x64/block_of_code.h @@ -20,7 +20,10 @@ public: void ClearCache(bool poison_memory); size_t RunCode(JitState* jit_state, CodePtr basic_block, size_t cycles_to_run) const; - void ReturnFromRunCode(); + void ReturnFromRunCode(bool MXCSR_switch = true); + + void SwitchMxcsrOnEntry(); + void SwitchMxcsrOnExit(); Gen::OpArg MFloatNegativeZero32() const { return Gen::M(const_FloatNegativeZero32); diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 21dbe5af..64f7859c 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -308,11 +308,9 @@ void EmitX64::EmitCallSupervisor(IR::Block&, IR::Inst* inst) { reg_alloc.HostCall(nullptr, imm32); - code->STMXCSR(MDisp(R15, offsetof(JitState, guest_MXCSR))); - code->LDMXCSR(MDisp(R15, offsetof(JitState, save_host_MXCSR))); + code->SwitchMxcsrOnExit(); code->ABI_CallFunction(reinterpret_cast(cb.CallSVC)); - code->STMXCSR(MDisp(R15, offsetof(JitState, save_host_MXCSR))); - code->LDMXCSR(MDisp(R15, offsetof(JitState, guest_MXCSR))); + code->SwitchMxcsrOnEntry(); } void EmitX64::EmitGetCarryFromOp(IR::Block&, IR::Inst*) { @@ -1514,8 +1512,9 @@ void EmitX64::EmitTerminalInterpret(IR::Term::Interpret terminal, Arm::LocationD code->MOV(64, R(ABI_PARAM2), Imm64(reinterpret_cast(jit_interface))); code->MOV(32, MJitStateReg(Arm::Reg::PC), R(ABI_PARAM1)); code->MOV(64, R(RSP), MDisp(R15, offsetof(JitState, save_host_RSP))); + code->SwitchMxcsrOnExit(); code->ABI_CallFunction(reinterpret_cast(cb.InterpreterFallback)); - code->ReturnFromRunCode(); // TODO: Check cycles + code->ReturnFromRunCode(false); // TODO: Check cycles } void EmitX64::EmitTerminalReturnToDispatch(IR::Term::ReturnToDispatch, Arm::LocationDescriptor initial_location) {