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