about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndré Zwing <nerv@dawncrow.de>2025-05-12 18:28:38 +0200
committerAndré Zwing <nerv@dawncrow.de>2025-05-19 23:46:29 +0200
commite07ec82344dd8d87c1a246bb9cfb4d74b8450842 (patch)
treeaddcceac09adafe4d92980dcbc753c23f4be0627
parent37eb5492ba5d58672620d77e01b1bd497cce00d9 (diff)
downloadbox64-e07ec82344dd8d87c1a246bb9cfb4d74b8450842.tar.gz
box64-e07ec82344dd8d87c1a246bb9cfb4d74b8450842.zip
[WOW64] Implement BTCpuSimulate
-rw-r--r--src/dynarec/arm64/arm64_epilog.S3
-rw-r--r--src/dynarec/arm64/arm64_next.S3
-rw-r--r--src/emu/x64emu_private.h3
-rw-r--r--wow64/compiler.h17
-rw-r--r--wow64/wowbox64.c39
5 files changed, 64 insertions, 1 deletions
diff --git a/src/dynarec/arm64/arm64_epilog.S b/src/dynarec/arm64/arm64_epilog.S
index 57f23200..4a15895b 100644
--- a/src/dynarec/arm64/arm64_epilog.S
+++ b/src/dynarec/arm64/arm64_epilog.S
@@ -19,6 +19,9 @@ arm64_epilog:
     stp     x24, x25, [x0, (8 * 14)]
     stp     x26, x27, [x0, (8 * 16)] // put back reg value in emu, including EIP (so x27 must be EIP now)
     //restore all used register
+#ifdef _WIN32
+    ldr     x18, [x0, 3120]
+#endif
     add     sp, x28, 0
     //vpop     {d8-d15}
     ldp     x19, x20, [sp, (8 * 0)]
diff --git a/src/dynarec/arm64/arm64_next.S b/src/dynarec/arm64/arm64_next.S
index e900fbec..950b7dd3 100644
--- a/src/dynarec/arm64/arm64_next.S
+++ b/src/dynarec/arm64/arm64_next.S
@@ -22,6 +22,9 @@ arm64_next:
     stp     x16, x17, [sp, (8 *  8)]
     stp     x18, x27, [sp, (8 * 10)]    // also save x27(rip) to allow change in LinkNext
 
+#ifdef _WIN32
+    ldr     x18, [x0, 3120]
+#endif
     mov     x2, x30      // "from" is in lr, so put in x2
     add     x3, sp, 8*11    // x3 is address to change rip
     // call the function
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 21f270f1..15e85fa4 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -124,6 +124,9 @@ typedef struct x64emu_s {
     uintptr_t   old_savedsp;
     #endif
 
+    #ifdef _WIN32
+    uint64_t    win64_teb;
+    #endif
     int         type;       // EMUTYPE_xxx define
     #ifdef BOX32
     int         libc_err;   // copy of errno from libc
diff --git a/wow64/compiler.h b/wow64/compiler.h
index 45dfc4ef..9abafa74 100644
--- a/wow64/compiler.h
+++ b/wow64/compiler.h
@@ -1,11 +1,28 @@
 #ifndef __COMPILER_H_
 #define __COMPILER_H_
 
+#include <stdint.h>
+
 /* Things missing from mingw64 right now */
 #define ThreadWow64Context (29)
+#define WOW64_TLS_CPURESERVED (1)
+#define WOW64_TLS_MAX_NUMBER (19)
+
+typedef struct _WOW64_CPURESERVED
+{
+    USHORT Flags;
+    USHORT Machine;
+} WOW64_CPURESERVED;
 
 NTSTATUS WINAPI RtlWow64GetCurrentCpuArea(USHORT *, void **, void **);
 NTSYSAPI NTSTATUS WINAPI LdrGetDllHandle(LPCWSTR, ULONG, const UNICODE_STRING*, HMODULE*);
 NTSYSAPI void* WINAPI RtlFindExportedRoutineByName(HMODULE, const char*);
 
+static inline uintptr_t calculate_fs(void)
+{
+/* until mingw64 has WowTebOffset in the TEB struct */
+uint8_t* teb = (uint8_t*)NtCurrentTeb();
+return (uintptr_t)(teb + *(int32_t*)(teb + 0x180c));
+}
+
 #endif //__COMPILER_H_
diff --git a/wow64/wowbox64.c b/wow64/wowbox64.c
index 20d714c9..8d0097c3 100644
--- a/wow64/wowbox64.c
+++ b/wow64/wowbox64.c
@@ -2,6 +2,7 @@
  * Copyright 2022-2025 André Zwing
  * Copyright 2023 Alexandre Julliard
  */
+#include <stddef.h>
 #include <stdio.h>
 #include <windows.h>
 #include <ntstatus.h>
@@ -16,6 +17,7 @@
 #include "emu/x87emu_private.h"
 #include "x64trace.h"
 #include "box64context.h"
+#include "box64cpu.h"
 #include "wine/debug.h"
 
 uintptr_t box64_pagesize = 4096;
@@ -125,6 +127,11 @@ NTSTATUS WINAPI BTCpuProcessInit(void)
     void **p__wine_unix_call_dispatcher;
     __wine_dbg_output("[BOX64] BTCpuProcessInit\n");
 
+#define STATIC_ASSERT(COND, MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1]
+/* otherwise adjust arm64_epilog.S and arm64_next.S */
+STATIC_ASSERT(offsetof(x64emu_t, win64_teb) == 3120, offset_of_b_must_be_4);
+#undef STATIC_ASSERT
+
     LoadEnvVariables();
 
     memset(bopcode, 0xc3, sizeof(bopcode));
@@ -171,7 +178,37 @@ NTSTATUS WINAPI BTCpuSetContext(HANDLE thread, HANDLE process, void* unknown, WO
 
 void WINAPI BTCpuSimulate(void)
 {
-    // NYI
+    WOW64_CPURESERVED *cpu = NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED];
+    x64emu_t *emu = NtCurrentTeb()->TlsSlots[0]; // FIXME
+    WOW64_CONTEXT *ctx = (WOW64_CONTEXT *)(cpu + 1);
+    CONTEXT entry_context;
+
+    RtlCaptureContext(&entry_context);
+    NtCurrentTeb()->TlsSlots[WOW64_TLS_MAX_NUMBER] = &entry_context;
+
+    R_EAX = ctx->Eax;
+    R_EBX = ctx->Ebx;
+    R_ECX = ctx->Ecx;
+    R_EDX = ctx->Edx;
+    R_ESI = ctx->Esi;
+    R_EDI = ctx->Edi;
+    R_EBP = ctx->Ebp;
+    R_RIP = ctx->Eip;
+    R_ESP = ctx->Esp;
+    R_CS  = ctx->SegCs & 0xffff;
+    R_DS  = ctx->SegDs & 0xffff;
+    R_ES  = ctx->SegEs & 0xffff;
+    R_FS  = ctx->SegFs & 0xffff;
+    R_GS  = ctx->SegGs & 0xffff;
+    R_SS  = ctx->SegSs & 0xffff;
+    emu->eflags.x64 = ctx->EFlags;
+    emu->segs_offs[_FS] = calculate_fs();
+    emu->win64_teb = (uint64_t)NtCurrentTeb();
+
+    if (box64env.dynarec)
+        DynaRun(emu);
+    else
+        Run(emu, 0);
 }
 
 NTSTATUS WINAPI BTCpuThreadInit(void)