diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 82c9821a949..1d0a1461fb2 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2678,6 +2678,15 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) #ifdef __APPLE__ +/* CW Hack 24265 */ +extern void __restore_mxcsr_thunk(void); +__ASM_GLOBAL_FUNC( __restore_mxcsr_thunk, + "pushq %rcx\n\t" + "movq %gs:0x30,%rcx\n\t" + "ldmxcsr 0x33c(%rcx)\n\t" /* amd64_thread_data()->mxcsr */ + "popq %rcx\n\t" + "jmp " __ASM_LOCAL_LABEL("__wine_syscall_dispatcher_prolog_end") ); + /********************************************************************** * sigsys_handler * @@ -2705,6 +2714,27 @@ static void sigsys_handler( int signal, siginfo_t *siginfo, void *sigcontext ) frame->restore_flags |= CONTEXT_CONTROL; } RIP_sig(ucontext) = (ULONG64)__wine_syscall_dispatcher_prolog_end_ptr; + + /* CW Hack 24265 */ + if (is_rosetta2 && FPU_sig(ucontext)) + { + XMM_SAVE_AREA32 fpu; + unsigned int direct_mxcsr; + __asm__ volatile( "stmxcsr %0" : "=m" (direct_mxcsr) ); + memcpy( &fpu, FPU_sig(ucontext), sizeof(fpu) ); + + if (direct_mxcsr != fpu.MxCsr) + { + fpu.MxCsr = direct_mxcsr; + memcpy( FPU_sig(ucontext), &fpu, sizeof(fpu) ); + + /* On the M3, Rosetta will restore mxcsr to the initial, incorrect + value from the sigcontext, even if we change it. So we jump to a + thunk that restores the value from amd64_thread_data. */ + amd64_thread_data()->mxcsr = direct_mxcsr; + RIP_sig(ucontext) = (ULONG64)__restore_mxcsr_thunk; + } + } } #endif