about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-05-26 23:12:44 +0200
committerGitHub <noreply@github.com>2025-05-26 23:12:44 +0200
commit1f46ca81af53d1e7177d52af58ec8eeae2a35e80 (patch)
treeb33b4067fae9c1f580d87f4cbfca1bd73a26be35
parent77c2683762e3995bf7d598bcfea695a202e5d34f (diff)
parent8dbeee5dcb3a36b13989a1a634387ea486cc727f (diff)
downloadbox64-1f46ca81af53d1e7177d52af58ec8eeae2a35e80.tar.gz
box64-1f46ca81af53d1e7177d52af58ec8eeae2a35e80.zip
Merge pull request #2675 from AndreRH/wowbox64
wow64 final (dont squash) 
-rw-r--r--wow64/compiler.h39
-rw-r--r--wow64/wowbox64.c83
2 files changed, 119 insertions, 3 deletions
diff --git a/wow64/compiler.h b/wow64/compiler.h
index a7bf71a7..eac844e5 100644
--- a/wow64/compiler.h
+++ b/wow64/compiler.h
@@ -9,16 +9,55 @@
 #define WOW64_TLS_MAX_NUMBER (19)
 #define WOW64_CPURESERVED_FLAG_RESET_STATE (1)
 
+typedef enum _MEMORY_INFORMATION_CLASS {
+    MemoryBasicInformation,
+    MemoryWorkingSetInformation,
+    MemoryMappedFilenameInformation,
+    MemoryRegionInformation,
+    MemoryWorkingSetExInformation,
+    MemorySharedCommitInformation,
+    MemoryImageInformation,
+    MemoryRegionInformationEx,
+    MemoryPrivilegedBasicInformation,
+    MemoryEnclaveImageInformation,
+    MemoryBasicInformationCapped,
+    MemoryPhysicalContiguityInformation,
+    MemoryBadInformation,
+    MemoryBadInformationAllProcesses,
+} MEMORY_INFORMATION_CLASS;
+
 typedef struct _WOW64_CPURESERVED
 {
     USHORT Flags;
     USHORT Machine;
 } WOW64_CPURESERVED;
 
+typedef struct _XMM_SAVE_AREA32 {
+    WORD  ControlWord;
+    WORD  StatusWord;
+    BYTE  TagWord;
+    BYTE  Reserved1;
+    WORD  ErrorOpcode;
+    DWORD ErrorOffset;
+    WORD  ErrorSelector;
+    WORD  Reserved2;
+    DWORD DataOffset;
+    WORD  DataSelector;
+    WORD  Reserved3;
+    DWORD MxCsr;
+    DWORD MxCsr_Mask;
+    M128A FloatRegisters[8];
+    M128A XmmRegisters[16];
+    BYTE  Reserved4[96];
+} XMM_SAVE_AREA32;
+
+#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )
+
 NTSTATUS WINAPI RtlWow64GetCurrentCpuArea(USHORT *, void **, void **);
 NTSTATUS  WINAPI Wow64SystemServiceEx(UINT, UINT*);
 NTSYSAPI NTSTATUS WINAPI LdrGetDllHandle(LPCWSTR, ULONG, const UNICODE_STRING*, HMODULE*);
 NTSYSAPI NTSTATUS WINAPI NtContinue(PCONTEXT, BOOLEAN);
+NTSYSAPI NTSTATUS WINAPI NtQueryVirtualMemory(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS, PVOID, SIZE_T, SIZE_T*);
 NTSYSAPI void* WINAPI RtlFindExportedRoutineByName(HMODULE, const char*);
 NTSYSAPI void DECLSPEC_NORETURN WINAPI RtlRaiseStatus(NTSTATUS);
 
diff --git a/wow64/wowbox64.c b/wow64/wowbox64.c
index 67cac41b..8177681b 100644
--- a/wow64/wowbox64.c
+++ b/wow64/wowbox64.c
@@ -51,6 +51,10 @@ static UINT16 DECLSPEC_ALIGN(4096) unxcode[4096/sizeof(UINT16)];
 typedef UINT64 unixlib_handle_t;
 NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * );
 
+#define ROUND_ADDR(addr,mask) ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask)))
+#define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
+static const UINT_PTR page_mask = 0xfff;
+
 int is_addr_unaligned(uintptr_t addr)
 {
     // FIXME
@@ -86,6 +90,68 @@ static box64context_t box64_context;
 box64context_t *my_context = &box64_context;
 
 
+void fpu_to_box(WOW64_CONTEXT *ctx, x64emu_t *emu)
+{
+    XMM_SAVE_AREA32 *fpu = (XMM_SAVE_AREA32 *)ctx->ExtendedRegisters;
+
+    emu->mxcsr.x32 = fpu->MxCsr;
+    emu->cw.x16 = fpu->ControlWord;
+    emu->sw.x16 = fpu->StatusWord;
+
+    LD2D(&ctx->FloatSave.RegisterArea[ 0], &emu->x87[0]);
+    LD2D(&ctx->FloatSave.RegisterArea[10], &emu->x87[1]);
+    LD2D(&ctx->FloatSave.RegisterArea[20], &emu->x87[2]);
+    LD2D(&ctx->FloatSave.RegisterArea[30], &emu->x87[3]);
+    LD2D(&ctx->FloatSave.RegisterArea[40], &emu->x87[4]);
+    LD2D(&ctx->FloatSave.RegisterArea[50], &emu->x87[5]);
+    LD2D(&ctx->FloatSave.RegisterArea[60], &emu->x87[6]);
+    LD2D(&ctx->FloatSave.RegisterArea[70], &emu->x87[7]);
+    memcpy(emu->xmm, fpu->XmmRegisters, sizeof(emu->xmm));
+}
+
+void box_to_fpu(WOW64_CONTEXT *ctx, x64emu_t *emu)
+{
+    XMM_SAVE_AREA32 *fpu = (XMM_SAVE_AREA32 *)ctx->ExtendedRegisters;
+
+    fpu->MxCsr = emu->mxcsr.x32;
+    fpu->ControlWord = emu->cw.x16;
+    fpu->StatusWord  = emu->sw.x16;
+
+    D2LD(&emu->x87[0], &ctx->FloatSave.RegisterArea[ 0]);
+    D2LD(&emu->x87[1], &ctx->FloatSave.RegisterArea[10]);
+    D2LD(&emu->x87[2], &ctx->FloatSave.RegisterArea[20]);
+    D2LD(&emu->x87[3], &ctx->FloatSave.RegisterArea[30]);
+    D2LD(&emu->x87[4], &ctx->FloatSave.RegisterArea[40]);
+    D2LD(&emu->x87[5], &ctx->FloatSave.RegisterArea[50]);
+    D2LD(&emu->x87[6], &ctx->FloatSave.RegisterArea[60]);
+    D2LD(&emu->x87[7], &ctx->FloatSave.RegisterArea[70]);
+    memcpy(fpu->XmmRegisters, emu->xmm, sizeof(emu->xmm));
+}
+
+static NTSTATUS invalidate_mapped_section( PVOID addr )
+{
+    MEMORY_BASIC_INFORMATION mem_info;
+    SIZE_T size;
+    void* base;
+
+    NTSTATUS ret = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mem_info, sizeof(mem_info), NULL );
+
+    if (!NT_SUCCESS(ret))
+        return ret;
+
+    base = mem_info.AllocationBase;
+    size = (char*)mem_info.BaseAddress + mem_info.RegionSize - (char*)base;
+
+    while (!NtQueryVirtualMemory( NtCurrentProcess(), (char*)base + size, MemoryBasicInformation, &mem_info, sizeof(mem_info), NULL) &&
+           mem_info.AllocationBase == base)
+    {
+        size += mem_info.RegionSize;
+    }
+
+    unprotectDB((uintptr_t)base, (DWORD64)size, 1);
+    return STATUS_SUCCESS;
+}
+
 void WINAPI BTCpuFlushInstructionCache2(LPCVOID addr, SIZE_T size)
 {
     // NYI
@@ -110,17 +176,22 @@ NTSTATUS WINAPI BTCpuGetContext(HANDLE thread, HANDLE process, void* unknown, WO
 
 void WINAPI BTCpuNotifyMemoryFree(PVOID addr, SIZE_T size, ULONG free_type)
 {
-    // NYI
+    if (!size)
+        invalidate_mapped_section( addr );
+    else if (free_type & MEM_DECOMMIT)
+        unprotectDB((uintptr_t)ROUND_ADDR( addr, page_mask ), (DWORD64)ROUND_SIZE( addr, size ), 1);
 }
 
 void WINAPI BTCpuNotifyMemoryProtect(PVOID addr, SIZE_T size, DWORD new_protect)
 {
-    // NYI
+    if (!(new_protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE)))
+        return;
+    unprotectDB((uintptr_t)addr, size, 1);
 }
 
 void WINAPI BTCpuNotifyUnmapViewOfSection(PVOID addr, ULONG flags)
 {
-    // NYI
+    invalidate_mapped_section( addr );
 }
 
 NTSTATUS WINAPI BTCpuProcessInit(void)
@@ -238,6 +309,8 @@ void WINAPI BTCpuSimulate(void)
     emu->segs_offs[_FS] = calculate_fs();
     emu->win64_teb = (uint64_t)NtCurrentTeb();
 
+    fpu_to_box(ctx, emu);
+
     if (box64env.dynarec)
         DynaRun(emu);
     else
@@ -296,6 +369,8 @@ void x86IntImpl(x64emu_t *emu, int code)
         ctx->EFlags = emu->eflags.x64;
         cpu->Flags = 0;
 
+        box_to_fpu(ctx, emu);
+
         if (is_unix_call)
         {
             uintptr_t handle_low = Pop32(emu);
@@ -311,6 +386,8 @@ void x86IntImpl(x64emu_t *emu, int code)
             R_EAX = Wow64SystemServiceEx( id, ULongToPtr(ctx->Esp+4) );
         }
 
+        fpu_to_box(ctx, emu);
+
         R_EBX = ctx->Ebx;
         R_ESI = ctx->Esi;
         R_EDI = ctx->Edi;