Revision 0ecfa993 linux-user/main.c
b/linux-user/main.c | ||
---|---|---|
21 | 21 |
#include <stdio.h> |
22 | 22 |
#include <stdarg.h> |
23 | 23 |
#include <errno.h> |
24 |
#include <unistd.h> |
|
24 | 25 |
|
25 | 26 |
#include "gemu.h" |
26 | 27 |
|
27 |
#include "i386/hsw_interp.h"
|
|
28 |
#include "cpu-i386.h"
|
|
28 | 29 |
|
29 | 30 |
unsigned long x86_stack_size; |
30 | 31 |
unsigned long stktop; |
... | ... | |
38 | 39 |
va_end(ap); |
39 | 40 |
} |
40 | 41 |
|
41 |
/* virtual x86 CPU stuff */ |
|
42 |
|
|
43 |
extern int invoke_code16(Interp_ENV *, int, int); |
|
44 |
extern int invoke_code32(Interp_ENV *, int); |
|
45 |
extern char *e_print_cpuemu_regs(ENVPARAMS, int is32); |
|
46 |
extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32); |
|
47 |
extern void init_npu(void); |
|
48 |
|
|
49 |
Interp_ENV env_global; |
|
50 |
Interp_ENV *envp_global; |
|
51 |
|
|
52 |
QWORD EMUtime = 0; |
|
53 |
|
|
54 |
int CEmuStat = 0; |
|
55 |
|
|
56 |
long instr_count; |
|
57 |
|
|
58 |
/* who will initialize this? */ |
|
59 |
unsigned long io_bitmap[IO_BITMAP_SIZE+1]; |
|
60 |
|
|
61 |
/* debug flag, 0=disable 1..9=level */ |
|
62 |
int d_emu = 0; |
|
63 |
|
|
64 |
unsigned long CRs[5] = |
|
65 |
{ |
|
66 |
0x00000013, /* valid bits: 0xe005003f */ |
|
67 |
0x00000000, /* invalid */ |
|
68 |
0x00000000, |
|
69 |
0x00000000, |
|
70 |
0x00000000 |
|
71 |
}; |
|
72 |
|
|
73 |
/* |
|
74 |
* DR0-3 = linear address of breakpoint 0-3 |
|
75 |
* DR4=5 = reserved |
|
76 |
* DR6 b0-b3 = BP active |
|
77 |
* b13 = BD |
|
78 |
* b14 = BS |
|
79 |
* b15 = BT |
|
80 |
* DR7 b0-b1 = G:L bp#0 |
|
81 |
* b2-b3 = G:L bp#1 |
|
82 |
* b4-b5 = G:L bp#2 |
|
83 |
* b6-b7 = G:L bp#3 |
|
84 |
* b8-b9 = GE:LE |
|
85 |
* b13 = GD |
|
86 |
* b16-19= LLRW bp#0 LL=00(1),01(2),11(4) |
|
87 |
* b20-23= LLRW bp#1 RW=00(x),01(w),11(rw) |
|
88 |
* b24-27= LLRW bp#2 |
|
89 |
* b28-31= LLRW bp#3 |
|
90 |
*/ |
|
91 |
unsigned long DRs[8] = |
|
92 |
{ |
|
93 |
0x00000000, |
|
94 |
0x00000000, |
|
95 |
0x00000000, |
|
96 |
0x00000000, |
|
97 |
0xffff1ff0, |
|
98 |
0x00000400, |
|
99 |
0xffff1ff0, |
|
100 |
0x00000400 |
|
101 |
}; |
|
102 |
|
|
103 |
unsigned long TRs[2] = |
|
104 |
{ |
|
105 |
0x00000000, |
|
106 |
0x00000000 |
|
107 |
}; |
|
108 |
|
|
109 |
void FatalAppExit(UINT wAction, LPCSTR lpText) |
|
110 |
{ |
|
111 |
fprintf(stderr, "Fatal error '%s' in CPU\n", lpText); |
|
112 |
exit(1); |
|
113 |
} |
|
114 |
|
|
115 |
int e_debug_check(unsigned char *PC) |
|
116 |
{ |
|
117 |
register unsigned long d7 = DRs[7]; |
|
118 |
|
|
119 |
if (d7&0x03) { |
|
120 |
if (d7&0x30000) return 0; /* only execute(00) bkp */ |
|
121 |
if ((long)PC==DRs[0]) { |
|
122 |
e_printf("DBRK: DR0 hit at %p\n",PC); |
|
123 |
DRs[6] |= 1; |
|
124 |
return 1; |
|
125 |
} |
|
126 |
} |
|
127 |
if (d7&0x0c) { |
|
128 |
if (d7&0x300000) return 0; |
|
129 |
if ((long)PC==DRs[1]) { |
|
130 |
e_printf("DBRK: DR1 hit at %p\n",PC); |
|
131 |
DRs[6] |= 2; |
|
132 |
return 1; |
|
133 |
} |
|
134 |
} |
|
135 |
if (d7&0x30) { |
|
136 |
if (d7&0x3000000) return 0; |
|
137 |
if ((long)PC==DRs[2]) { |
|
138 |
e_printf("DBRK: DR2 hit at %p\n",PC); |
|
139 |
DRs[6] |= 4; |
|
140 |
return 1; |
|
141 |
} |
|
142 |
} |
|
143 |
if (d7&0xc0) { |
|
144 |
if (d7&0x30000000) return 0; |
|
145 |
if ((long)PC==DRs[3]) { |
|
146 |
e_printf("DBRK: DR3 hit at %p\n",PC); |
|
147 |
DRs[6] |= 8; |
|
148 |
return 1; |
|
149 |
} |
|
150 |
} |
|
151 |
return 0; |
|
152 |
} |
|
153 |
|
|
154 |
/* Debug stuff */ |
|
155 |
void logstr(unsigned long mask, const char *fmt,...) |
|
156 |
{ |
|
157 |
va_list ap; |
|
158 |
|
|
159 |
va_start(ap, fmt); |
|
160 |
vfprintf(stderr, fmt, ap); |
|
161 |
va_end(ap); |
|
162 |
} |
|
163 |
|
|
164 |
/* unconditional message into debug log and stderr */ |
|
165 |
#undef error |
|
166 |
void error(const char *fmt, ...) |
|
167 |
{ |
|
168 |
va_list ap; |
|
169 |
|
|
170 |
va_start(ap, fmt); |
|
171 |
vfprintf(stderr, fmt, ap); |
|
172 |
va_end(ap); |
|
173 |
exit(1); |
|
174 |
} |
|
175 |
|
|
176 |
int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write) |
|
177 |
{ |
|
178 |
fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d", |
|
179 |
is_write ? "write" : "read", port, value, size); |
|
180 |
return value; |
|
181 |
} |
|
182 |
|
|
183 |
void LogProcName(WORD wSel, WORD wOff, WORD wAction) |
|
184 |
{ |
|
185 |
|
|
186 |
} |
|
187 |
|
|
188 |
void INT_handler(int num, void *env) |
|
189 |
{ |
|
190 |
fprintf(stderr, "EM86: int %d\n", num); |
|
191 |
} |
|
192 |
|
|
193 | 42 |
/***********************************************************/ |
194 |
/* new CPU core */
|
|
43 |
/* CPUX86 core interface */
|
|
195 | 44 |
|
196 | 45 |
void cpu_x86_outb(int addr, int val) |
197 | 46 |
{ |
... | ... | |
245 | 94 |
const char *filename; |
246 | 95 |
struct target_pt_regs regs1, *regs = ®s1; |
247 | 96 |
struct image_info info1, *info = &info1; |
248 |
Interp_ENV *env;
|
|
97 |
CPUX86State *env;
|
|
249 | 98 |
|
250 | 99 |
if (argc <= 1) |
251 | 100 |
usage(); |
... | ... | |
277 | 126 |
target_set_brk((char *)info->brk); |
278 | 127 |
syscall_init(); |
279 | 128 |
|
280 |
env = &env_global; |
|
281 |
envp_global = env; |
|
282 |
memset(env, 0, sizeof(Interp_ENV)); |
|
283 |
|
|
284 |
env->rax.e = regs->eax; |
|
285 |
env->rbx.e = regs->ebx; |
|
286 |
env->rcx.e = regs->ecx; |
|
287 |
env->rdx.e = regs->edx; |
|
288 |
env->rsi.esi = regs->esi; |
|
289 |
env->rdi.edi = regs->edi; |
|
290 |
env->rbp.ebp = regs->ebp; |
|
291 |
env->rsp.esp = regs->esp; |
|
292 |
env->cs.cs = __USER_CS; |
|
293 |
env->ds.ds = __USER_DS; |
|
294 |
env->es.es = __USER_DS; |
|
295 |
env->ss.ss = __USER_DS; |
|
296 |
env->fs.fs = __USER_DS; |
|
297 |
env->gs.gs = __USER_DS; |
|
298 |
env->trans_addr = regs->eip; |
|
129 |
env = cpu_x86_init(); |
|
130 |
|
|
131 |
env->regs[R_EAX] = regs->eax; |
|
132 |
env->regs[R_EBX] = regs->ebx; |
|
133 |
env->regs[R_ECX] = regs->ecx; |
|
134 |
env->regs[R_EDX] = regs->edx; |
|
135 |
env->regs[R_ESI] = regs->esi; |
|
136 |
env->regs[R_EDI] = regs->edi; |
|
137 |
env->regs[R_EBP] = regs->ebp; |
|
138 |
env->regs[R_ESP] = regs->esp; |
|
139 |
env->segs[R_CS] = __USER_CS; |
|
140 |
env->segs[R_DS] = __USER_DS; |
|
141 |
env->segs[R_ES] = __USER_DS; |
|
142 |
env->segs[R_SS] = __USER_DS; |
|
143 |
env->segs[R_FS] = __USER_DS; |
|
144 |
env->segs[R_GS] = __USER_DS; |
|
145 |
env->pc = regs->eip; |
|
299 | 146 |
|
147 |
#if 0 |
|
300 | 148 |
LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32; |
301 | 149 |
LDT[__USER_CS >> 3].dwSelLimit = 0xfffff; |
302 | 150 |
LDT[__USER_CS >> 3].lpSelBase = NULL; |
... | ... | |
304 | 152 |
LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32; |
305 | 153 |
LDT[__USER_DS >> 3].dwSelLimit = 0xfffff; |
306 | 154 |
LDT[__USER_DS >> 3].lpSelBase = NULL; |
307 |
init_npu(); |
|
308 |
build_decode_tables(); |
|
155 |
#endif |
|
309 | 156 |
|
310 | 157 |
for(;;) { |
311 | 158 |
int err; |
312 | 159 |
uint8_t *pc; |
313 |
|
|
314 |
err = invoke_code32(env, -1); |
|
315 |
env->trans_addr = env->return_addr; |
|
316 |
pc = env->seg_regs[0] + env->trans_addr; |
|
160 |
|
|
161 |
err = cpu_x86_exec(env); |
|
317 | 162 |
switch(err) { |
318 | 163 |
case EXCP0D_GPF: |
164 |
pc = (uint8_t *)env->pc; |
|
319 | 165 |
if (pc[0] == 0xcd && pc[1] == 0x80) { |
320 | 166 |
/* syscall */ |
321 |
env->trans_addr += 2;
|
|
322 |
env->rax.e = do_syscall(env->rax.e,
|
|
323 |
env->rbx.e,
|
|
324 |
env->rcx.e,
|
|
325 |
env->rdx.e,
|
|
326 |
env->rsi.esi,
|
|
327 |
env->rdi.edi,
|
|
328 |
env->rbp.ebp);
|
|
167 |
env->pc += 2;
|
|
168 |
env->regs[R_EAX] = do_syscall(env->regs[R_EAX],
|
|
169 |
env->regs[R_EBX],
|
|
170 |
env->regs[R_ECX],
|
|
171 |
env->regs[R_EDX],
|
|
172 |
env->regs[R_ESI],
|
|
173 |
env->regs[R_EDI],
|
|
174 |
env->regs[R_EBP]);
|
|
329 | 175 |
} else { |
330 | 176 |
goto trap_error; |
331 | 177 |
} |
332 | 178 |
break; |
333 | 179 |
default: |
334 | 180 |
trap_error: |
335 |
fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err); |
|
336 |
#ifndef NO_TRACE_MSGS |
|
337 |
d_emu = 9; |
|
338 |
fprintf(stderr, "%s\n%s\n", |
|
339 |
e_print_cpuemu_regs(env, 1), |
|
340 |
e_emu_disasm(env,pc,1)); |
|
341 |
#endif |
|
181 |
fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n", |
|
182 |
(long)env->pc, err); |
|
342 | 183 |
abort(); |
343 | 184 |
} |
344 | 185 |
} |
Also available in: Unified diff