1 #include "armv5te/os/os.h"
2 
3 #define WIN32_LEAN_AND_MEAN
4 #include <assert.h>
5 #include <conio.h>
6 #include <windows.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <fcntl.h>
10 #include <share.h>
11 
12 #include "armv5te/emu.h"
13 #include "armv5te/mmu.h"
14 
os_reserve(size_t size)15 void *os_reserve(size_t size)
16 {
17     return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
18 }
19 
os_free(void * ptr,size_t size)20 void os_free(void *ptr, size_t size)
21 {
22     (void) size;
23     VirtualFree(ptr, 0, MEM_RELEASE);
24 }
25 
26 #if OS_HAS_PAGEFAULT_HANDLER
os_commit(void * addr,size_t size)27 void *os_commit(void *addr, size_t size)
28 {
29     return VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE);
30 }
31 
os_sparse_commit(void * page,size_t size)32 void *os_sparse_commit(void *page, size_t size)
33 {
34     return VirtualAlloc(page, size, MEM_COMMIT, PAGE_READWRITE);
35 }
36 
os_sparse_decommit(void * page,size_t size)37 void os_sparse_decommit(void *page, size_t size)
38 {
39     VirtualFree(page, size, MEM_DECOMMIT);
40     return;
41 }
42 #endif
43 
os_alloc_executable(size_t size)44 void *os_alloc_executable(size_t size)
45 {
46     return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
47 }
48 
49 #if OS_HAS_PAGEFAULT_HANDLER
addr_cache_exception(PEXCEPTION_RECORD er,void * x,void * y,void * z)50 static int addr_cache_exception(PEXCEPTION_RECORD er, void *x, void *y, void *z) {
51     (void) x; (void) y; (void) z;
52     if (er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
53         if (addr_cache_pagefault((void *)er->ExceptionInformation[1]))
54             return 0; // Continue execution
55     }
56     return 1; // Continue search
57 }
58 #endif
59 
addr_cache_init()60 void addr_cache_init() {
61     // Don't run more than once
62     if(addr_cache)
63         return;
64 
65     DWORD flags = MEM_RESERVE;
66 
67 #if defined(AC_FLAGS)
68     // Commit memory to not trigger segfaults which make debugging a PITA
69     flags |= MEM_COMMIT;
70 #endif
71 
72     addr_cache = VirtualAlloc(NULL, AC_NUM_ENTRIES * sizeof(ac_entry), flags, PAGE_READWRITE);
73     if(!addr_cache){
74        printf("Cant allocate addr_cache!\n");
75        exit(1);
76     }
77 
78 #if !defined(AC_FLAGS)
79     unsigned int i;
80     for(unsigned int i = 0; i < AC_NUM_ENTRIES; ++i)
81     {
82         AC_SET_ENTRY_INVALID(addr_cache[i], (i >> 1) << 10)
83     }
84 #else
85     memset(addr_cache, 0xFF, AC_NUM_ENTRIES * sizeof(ac_entry));
86 #endif
87 
88 #if defined(__i386__) && !defined(NO_TRANSLATION)
89     // Relocate the assembly code that wants addr_cache at a fixed address
90     extern DWORD *ac_reloc_start[] __asm__("ac_reloc_start"), *ac_reloc_end[] __asm__("ac_reloc_end");
91     DWORD **reloc;
92     for (reloc = ac_reloc_start; reloc != ac_reloc_end; reloc++) {
93         DWORD prot;
94         VirtualProtect(*reloc, 4, PAGE_EXECUTE_READWRITE, &prot);
95         **reloc += (DWORD)addr_cache;
96         VirtualProtect(*reloc, 4, prot, &prot);
97     }
98 #endif
99 }
100 
101 #if OS_HAS_PAGEFAULT_HANDLER
os_faulthandler_arm(os_exception_frame_t * frame)102 void os_faulthandler_arm(os_exception_frame_t *frame)
103 {
104     assert(frame->prev == NULL);
105 
106     frame->function = (void *)addr_cache_exception;
107     asm ("movl %%fs:(%1), %0" : "=r" (frame->prev) : "r" (0));
108     asm ("movl %0, %%fs:(%1)" : : "r" (frame), "r" (0));
109 }
110 
os_faulthandler_unarm(os_exception_frame_t * frame)111 void os_faulthandler_unarm(os_exception_frame_t *frame)
112 {
113     assert(frame->prev != NULL);
114 
115     asm ("movl %0, %%fs:(%1)" : : "r" (frame->prev), "r" (0));
116     frame->prev = NULL;
117 }
118 #endif
119 
addr_cache_deinit()120 void addr_cache_deinit() {
121     if(!addr_cache)
122         return;
123 
124 #if defined(__i386__) && !defined(NO_TRANSLATION)
125     // Undo the relocations
126     extern DWORD *ac_reloc_start[] __asm__("ac_reloc_start"), *ac_reloc_end[] __asm__("ac_reloc_end");
127     DWORD **reloc;
128     for (reloc = ac_reloc_start; reloc != ac_reloc_end; reloc++)
129         **reloc -= (DWORD)addr_cache;
130 #endif
131 
132     VirtualFree(addr_cache, 0, MEM_RELEASE);
133     addr_cache = NULL;
134 }
135