diff --git a/dlls/wow64cpu/cpu.c b/dlls/wow64cpu/cpu.c
index 4a49989ee57..7c89fc34364 100644
--- a/dlls/wow64cpu/cpu.c
+++ b/dlls/wow64cpu/cpu.c
@@ -40,10 +40,35 @@ struct thunk_32to64
     DWORD addr;
     WORD  cs;
 };
+struct thunk_32to64_rosetta2_workaround
+{
+    BYTE  lcall;  /* call far, absolute indirect */
+    BYTE  modrm;  /* address=disp32, opcode=3 */
+    DWORD op;
+    DWORD addr;
+    WORD  cs;
+
+    BYTE add;
+    BYTE add_modrm;
+    BYTE add_op;
+
+    BYTE jmp;
+    BYTE jmp_modrm;
+    DWORD jmp_op;
+    ULONG64 jmp_addr;
+};
 struct thunk_opcodes
 {
-    struct thunk_32to64 syscall_thunk;
-    struct thunk_32to64 unix_thunk;
+    union
+    {
+        struct thunk_32to64 syscall_thunk;
+        struct thunk_32to64_rosetta2_workaround syscall_thunk_rosetta;
+    };
+    union
+    {
+        struct thunk_32to64 unix_thunk;
+        struct thunk_32to64_rosetta2_workaround unix_thunk_rosetta;
+    };
 };
 #pragma pack(pop)
 
@@ -58,6 +83,19 @@ static USHORT fs32_sel;
 
 void **__wine_unix_call_dispatcher = NULL;
 
+BOOL use_rosetta2_workaround;
+
+static BOOL is_rosetta2(void)
+{
+    char buffer[64];
+    NTSTATUS status = NtQuerySystemInformation( SystemProcessorBrandString, buffer, sizeof(buffer), NULL );
+
+    if (status || !strstr( buffer, "VirtualApple" ))
+        return FALSE;
+
+    return TRUE;
+}
+
 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved )
 {
     if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst );
@@ -211,7 +249,21 @@ __ASM_GLOBAL_FUNC( syscall_32to64,
                    "movl %edx,4(%rsp)\n\t"
                    "movl 0xc4(%r13),%r14d\n\t"  /* context->Esp */
                    "xchgq %r14,%rsp\n\t"
-                   "ljmp *(%r14)\n"
+
+                   /* CW HACK 20760:
+                    * When running under Rosetta 2, use lretq instead of ljmp to work around a SIGUSR1 race condition.
+                    */
+                   "cmpl $0, " __ASM_NAME("use_rosetta2_workaround") "\n\t"
+                   "jne syscall_32to64_rosetta2_workaround\n\t"
+                   "ljmp *(%r14)\n\t"
+                   "syscall_32to64_rosetta2_workaround:\n\t"
+                   "subq $0x10,%rsp\n\t"
+                   "movl 4(%r14),%edx\n\t"
+                   "movq %rdx,0x8(%rsp)\n\t"
+                   "movl 0(%r14),%edx\n\t"
+                   "movq %rdx,(%rsp)\n\t"
+                   "lretq\n"
+
                    ".Lsyscall_32to64_return:\n\t"
                    "movq %rsp,%r14\n\t"
                    "movl 0xa8(%r13),%edx\n\t"   /* context->Edx */
@@ -271,7 +323,20 @@ __ASM_GLOBAL_FUNC( unix_call_32to64,
                    "movl %edx,4(%rsp)\n\t"
                    "movl 0xc4(%r13),%r14d\n\t"  /* context->Esp */
                    "xchgq %r14,%rsp\n\t"
-                   "ljmp *(%r14)" )
+
+                   /* CW HACK 20760:
+                    * When running under Rosetta 2, use lretq instead of ljmp to work around a SIGUSR1 race condition.
+                    */
+                   "cmpl $0, " __ASM_NAME("use_rosetta2_workaround") "\n\t"
+                   "jne unix_call_32to64_rosetta2_workaround\n\t"
+                   "ljmp *(%r14)\n\t"
+                   "unix_call_32to64_rosetta2_workaround:\n\t"
+                   "subq $0x10,%rsp\n\t"
+                   "movl 4(%r14),%edx\n\t"
+                   "movq %rdx,0x8(%rsp)\n\t"
+                   "movl 0(%r14),%edx\n\t"
+                   "movq %rdx,(%rsp)\n\t"
+                   "lretq" )
 
 
 /**********************************************************************
@@ -322,6 +387,8 @@ NTSTATUS WINAPI BTCpuProcessInit(void)
 
     wow64info->CpuFlags |= WOW64_CPUFLAGS_MSFT64;
 
+    use_rosetta2_workaround = is_rosetta2();
+
     LdrGetDllHandle( NULL, 0, &str, &module );
     p__wine_unix_call_dispatcher = RtlFindExportedRoutineByName( module, "__wine_unix_call_dispatcher" );
     __wine_unix_call_dispatcher = *p__wine_unix_call_dispatcher;
@@ -336,17 +403,65 @@ NTSTATUS WINAPI BTCpuProcessInit(void)
     cs32_sel = context_i386.SegCs;
     ss32_sel = context_i386.SegSs;
 
-    thunk->syscall_thunk.ljmp  = 0xff;
-    thunk->syscall_thunk.modrm = 0x2d;
-    thunk->syscall_thunk.op    = PtrToUlong( &thunk->syscall_thunk.addr );
-    thunk->syscall_thunk.addr  = PtrToUlong( syscall_32to64 );
-    thunk->syscall_thunk.cs    = cs64_sel;
-
-    thunk->unix_thunk.ljmp  = 0xff;
-    thunk->unix_thunk.modrm = 0x2d;
-    thunk->unix_thunk.op    = PtrToUlong( &thunk->unix_thunk.addr );
-    thunk->unix_thunk.addr  = PtrToUlong( unix_call_32to64 );
-    thunk->unix_thunk.cs    = cs64_sel;
+    /* CW HACK 20760 */
+    if (use_rosetta2_workaround)
+    {
+        thunk->syscall_thunk_rosetta.lcall     = 0xff;
+        thunk->syscall_thunk_rosetta.modrm     = 0x1d;
+        thunk->syscall_thunk_rosetta.op        = PtrToUlong( &thunk->syscall_thunk_rosetta.addr );
+        thunk->syscall_thunk_rosetta.addr      = PtrToUlong( &thunk->syscall_thunk_rosetta.add );
+        thunk->syscall_thunk_rosetta.cs        = cs64_sel;
+
+        /* We are now in 64-bit. */
+        /* add $0x08,%esp to remove the addr/segment pushed on the stack by the lcall */
+        thunk->syscall_thunk_rosetta.add       = 0x83;
+        thunk->syscall_thunk_rosetta.add_modrm = 0xc4;
+        thunk->syscall_thunk_rosetta.add_op    = 0x08;
+
+        /* jmp to syscall_32to64 */
+        thunk->syscall_thunk_rosetta.jmp       = 0xff;
+        thunk->syscall_thunk_rosetta.jmp_modrm = 0x25;
+        thunk->syscall_thunk_rosetta.jmp_op    = 0x00;
+        thunk->syscall_thunk_rosetta.jmp_addr  = PtrToUlong( syscall_32to64 );
+    }
+    else
+    {
+        thunk->syscall_thunk.ljmp  = 0xff;
+        thunk->syscall_thunk.modrm = 0x2d;
+        thunk->syscall_thunk.op    = PtrToUlong( &thunk->syscall_thunk.addr );
+        thunk->syscall_thunk.addr  = PtrToUlong( syscall_32to64 );
+        thunk->syscall_thunk.cs    = cs64_sel;
+    }
+
+    /* CW HACK 20760 */
+    if (use_rosetta2_workaround)
+    {
+        thunk->unix_thunk_rosetta.lcall     = 0xff;
+        thunk->unix_thunk_rosetta.modrm     = 0x1d;
+        thunk->unix_thunk_rosetta.op        = PtrToUlong( &thunk->unix_thunk_rosetta.addr );
+        thunk->unix_thunk_rosetta.addr      = PtrToUlong( &thunk->unix_thunk_rosetta.add );
+        thunk->unix_thunk_rosetta.cs        = cs64_sel;
+
+        /* We are now in 64-bit. */
+        /* add $0x08,%esp to remove the addr/segment pushed on the stack by the lcall */
+        thunk->unix_thunk_rosetta.add       = 0x83;
+        thunk->unix_thunk_rosetta.add_modrm = 0xc4;
+        thunk->unix_thunk_rosetta.add_op    = 0x08;
+
+        /* jmp to unix_call_32to64 */
+        thunk->unix_thunk_rosetta.jmp       = 0xff;
+        thunk->unix_thunk_rosetta.jmp_modrm = 0x25;
+        thunk->unix_thunk_rosetta.jmp_op    = 0x00;
+        thunk->unix_thunk_rosetta.jmp_addr  = PtrToUlong( unix_call_32to64 );
+    }
+    else
+    {
+        thunk->unix_thunk.ljmp  = 0xff;
+        thunk->unix_thunk.modrm = 0x2d;
+        thunk->unix_thunk.op    = PtrToUlong( &thunk->unix_thunk.addr );
+        thunk->unix_thunk.addr  = PtrToUlong( unix_call_32to64 );
+        thunk->unix_thunk.cs    = cs64_sel;
+    }
 
     NtProtectVirtualMemory( GetCurrentProcess(), (void **)&thunk, &size, PAGE_EXECUTE_READ, &old_prot );
     return STATUS_SUCCESS;
