Commit bc8a22cc307ebd9a2577c8fffcb90000724f72f3
1 parent
f631ef9b
better vm86 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@69 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
239 additions
and
89 deletions
Changelog
1 | +version 0.1.4: | |
2 | + | |
3 | + - more accurate VM86 emulation (can launch small DOS 16 bit | |
4 | + executables in wine). | |
5 | + - fixed push/pop fs/gs | |
6 | + - added iret instruction. | |
7 | + | |
8 | +version 0.1.3: | |
9 | + | |
10 | + - S390 support (Ulrich Weigand) | |
11 | + - glibc 2.3.x compile fix (Ulrich Weigand) | |
12 | + - socketcall endian fix (Ulrich Weigand) | |
13 | + - struct sockaddr endian fix (Ulrich Weigand) | |
14 | + - sendmsg/recvmsg endian fix (Ulrich Weigand) | |
15 | + - execve endian fix (Ulrich Weigand) | |
16 | + - fdset endian fix (Ulrich Weigand) | |
17 | + - partial setsockopt syscall support (Ulrich Weigand) | |
18 | + - more accurate pushf/popf emulation | |
19 | + - first partial vm86() syscall support (can be used with runcom example). | |
20 | + - added bound, cmpxchg8b, cpuid instructions | |
21 | + - added 16 bit addressing support/override for string operations | |
22 | + - poll() fix | |
23 | + | |
24 | +version 0.1.2: | |
25 | + | |
26 | + - compile fixes | |
27 | + - xlat instruction | |
28 | + - xchg instruction memory lock | |
29 | + - added simple vm86 example (not working with QEMU yet). The 54 byte | |
30 | + DOS executable 'pi_10.com' program was released by Bertram | |
31 | + Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html). | |
32 | + | |
1 | 33 | version 0.1.1: |
2 | 34 | |
3 | 35 | - glibc 2.2 compilation fixes |
4 | 36 | - added -s and -L options |
5 | 37 | - binary distribution of x86 glibc and wine |
38 | + - big endian fixes in ELF loader and getdents. | |
6 | 39 | |
7 | 40 | version 0.1: |
8 | 41 | ... | ... |
TODO
1 | +- fix thread locks | |
2 | +- fix thread stack liberation | |
3 | +- fix x86 stack allocation | |
1 | 4 | - optimize translated cache chaining (DLL PLT-like system) |
2 | 5 | - more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit |
3 | 6 | issues, fix 16 bit uid issues) |
4 | 7 | - finish signal handing (fp87 state, more siginfo conversions) |
5 | 8 | - verify thread support (clone() and various locks) |
6 | -- vm86 syscall support | |
7 | 9 | - overrides/16bit for string ops |
8 | 10 | - make it self runnable (use same trick as ld.so : include its own relocator and libc) |
9 | -- improved 16 bit support | |
10 | 11 | - fix FPU exceptions (in particular: gen_op_fpush not before mem load) | ... | ... |
cpu-i386.h
... | ... | @@ -68,24 +68,24 @@ |
68 | 68 | #define VIP_MASK 0x00100000 |
69 | 69 | #define ID_MASK 0x00200000 |
70 | 70 | |
71 | -#define EXCP00_DIVZ 1 | |
72 | -#define EXCP01_SSTP 2 | |
73 | -#define EXCP02_NMI 3 | |
74 | -#define EXCP03_INT3 4 | |
75 | -#define EXCP04_INTO 5 | |
76 | -#define EXCP05_BOUND 6 | |
77 | -#define EXCP06_ILLOP 7 | |
78 | -#define EXCP07_PREX 8 | |
79 | -#define EXCP08_DBLE 9 | |
80 | -#define EXCP09_XERR 10 | |
81 | -#define EXCP0A_TSS 11 | |
82 | -#define EXCP0B_NOSEG 12 | |
83 | -#define EXCP0C_STACK 13 | |
84 | -#define EXCP0D_GPF 14 | |
85 | -#define EXCP0E_PAGE 15 | |
86 | -#define EXCP10_COPR 17 | |
87 | -#define EXCP11_ALGN 18 | |
88 | -#define EXCP12_MCHK 19 | |
71 | +#define EXCP00_DIVZ 0 | |
72 | +#define EXCP01_SSTP 1 | |
73 | +#define EXCP02_NMI 2 | |
74 | +#define EXCP03_INT3 3 | |
75 | +#define EXCP04_INTO 4 | |
76 | +#define EXCP05_BOUND 5 | |
77 | +#define EXCP06_ILLOP 6 | |
78 | +#define EXCP07_PREX 7 | |
79 | +#define EXCP08_DBLE 8 | |
80 | +#define EXCP09_XERR 9 | |
81 | +#define EXCP0A_TSS 10 | |
82 | +#define EXCP0B_NOSEG 11 | |
83 | +#define EXCP0C_STACK 12 | |
84 | +#define EXCP0D_GPF 13 | |
85 | +#define EXCP0E_PAGE 14 | |
86 | +#define EXCP10_COPR 16 | |
87 | +#define EXCP11_ALGN 17 | |
88 | +#define EXCP12_MCHK 18 | |
89 | 89 | |
90 | 90 | #define EXCP_INTERRUPT 256 /* async interruption */ |
91 | 91 | ... | ... |
linux-user/main.c
... | ... | @@ -106,77 +106,172 @@ uint64_t gdt_table[6]; |
106 | 106 | |
107 | 107 | //#define DEBUG_VM86 |
108 | 108 | |
109 | +static inline int is_revectored(int nr, struct target_revectored_struct *bitmap) | |
110 | +{ | |
111 | + return (tswap32(bitmap->__map[nr >> 5]) >> (nr & 0x1f)) & 1; | |
112 | +} | |
113 | + | |
114 | +static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) | |
115 | +{ | |
116 | + return (uint8_t *)((seg << 4) + (reg & 0xffff)); | |
117 | +} | |
118 | + | |
119 | +static inline void pushw(CPUX86State *env, int val) | |
120 | +{ | |
121 | + env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | | |
122 | + ((env->regs[R_ESP] - 2) & 0xffff); | |
123 | + *(uint16_t *)seg_to_linear(env->segs[R_SS], env->regs[R_ESP]) = val; | |
124 | +} | |
125 | + | |
126 | +static inline unsigned int get_vflags(CPUX86State *env) | |
127 | +{ | |
128 | + unsigned int eflags; | |
129 | + eflags = env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); | |
130 | + if (eflags & VIF_MASK) | |
131 | + eflags |= IF_MASK; | |
132 | + return eflags; | |
133 | +} | |
134 | + | |
135 | +void save_v86_state(CPUX86State *env) | |
136 | +{ | |
137 | + TaskState *ts = env->opaque; | |
138 | +#ifdef DEBUG_VM86 | |
139 | + printf("save_v86_state\n"); | |
140 | +#endif | |
141 | + | |
142 | + /* put the VM86 registers in the userspace register structure */ | |
143 | + ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]); | |
144 | + ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]); | |
145 | + ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]); | |
146 | + ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]); | |
147 | + ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]); | |
148 | + ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]); | |
149 | + ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]); | |
150 | + ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]); | |
151 | + ts->target_v86->regs.eip = tswap32(env->eip); | |
152 | + ts->target_v86->regs.cs = tswap16(env->segs[R_CS]); | |
153 | + ts->target_v86->regs.ss = tswap16(env->segs[R_SS]); | |
154 | + ts->target_v86->regs.ds = tswap16(env->segs[R_DS]); | |
155 | + ts->target_v86->regs.es = tswap16(env->segs[R_ES]); | |
156 | + ts->target_v86->regs.fs = tswap16(env->segs[R_FS]); | |
157 | + ts->target_v86->regs.gs = tswap16(env->segs[R_GS]); | |
158 | + ts->target_v86->regs.eflags = tswap32(env->eflags); | |
159 | + | |
160 | + /* restore 32 bit registers */ | |
161 | + env->regs[R_EAX] = ts->vm86_saved_regs.eax; | |
162 | + env->regs[R_EBX] = ts->vm86_saved_regs.ebx; | |
163 | + env->regs[R_ECX] = ts->vm86_saved_regs.ecx; | |
164 | + env->regs[R_EDX] = ts->vm86_saved_regs.edx; | |
165 | + env->regs[R_ESI] = ts->vm86_saved_regs.esi; | |
166 | + env->regs[R_EDI] = ts->vm86_saved_regs.edi; | |
167 | + env->regs[R_EBP] = ts->vm86_saved_regs.ebp; | |
168 | + env->regs[R_ESP] = ts->vm86_saved_regs.esp; | |
169 | + env->eflags = ts->vm86_saved_regs.eflags; | |
170 | + env->eip = ts->vm86_saved_regs.eip; | |
171 | + | |
172 | + cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs); | |
173 | + cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss); | |
174 | + cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds); | |
175 | + cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es); | |
176 | + cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs); | |
177 | + cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs); | |
178 | +} | |
179 | + | |
180 | +/* return from vm86 mode to 32 bit. The vm86() syscall will return | |
181 | + 'retval' */ | |
182 | +static inline void return_to_32bit(CPUX86State *env, int retval) | |
183 | +{ | |
184 | +#ifdef DEBUG_VM86 | |
185 | + printf("return_to_32bit: ret=0x%x\n", retval); | |
186 | +#endif | |
187 | + save_v86_state(env); | |
188 | + env->regs[R_EAX] = retval; | |
189 | +} | |
190 | + | |
191 | +/* handle VM86 interrupt (NOTE: the CPU core currently does not | |
192 | + support TSS interrupt revectoring, so this code is always executed) */ | |
193 | +static void do_int(CPUX86State *env, int intno) | |
194 | +{ | |
195 | + TaskState *ts = env->opaque; | |
196 | + uint32_t *int_ptr, segoffs; | |
197 | + | |
198 | + if (env->segs[R_CS] == TARGET_BIOSSEG) | |
199 | + goto cannot_handle; /* XXX: I am not sure this is really useful */ | |
200 | + if (is_revectored(intno, &ts->target_v86->int_revectored)) | |
201 | + goto cannot_handle; | |
202 | + if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff, | |
203 | + &ts->target_v86->int21_revectored)) | |
204 | + goto cannot_handle; | |
205 | + int_ptr = (uint32_t *)(intno << 2); | |
206 | + segoffs = tswap32(*int_ptr); | |
207 | + if ((segoffs >> 16) == TARGET_BIOSSEG) | |
208 | + goto cannot_handle; | |
209 | +#ifdef DEBUG_VM86 | |
210 | + printf("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n", | |
211 | + intno, segoffs >> 16, segoffs & 0xffff); | |
212 | +#endif | |
213 | + /* save old state */ | |
214 | + pushw(env, get_vflags(env)); | |
215 | + pushw(env, env->segs[R_CS]); | |
216 | + pushw(env, env->eip); | |
217 | + /* goto interrupt handler */ | |
218 | + env->eip = segoffs & 0xffff; | |
219 | + cpu_x86_load_seg(env, R_CS, segoffs >> 16); | |
220 | + env->eflags &= ~(VIF_MASK | TF_MASK); | |
221 | + return; | |
222 | + cannot_handle: | |
223 | +#ifdef DEBUG_VM86 | |
224 | + printf("VM86: return to 32 bits int 0x%x\n", intno); | |
225 | +#endif | |
226 | + return_to_32bit(env, TARGET_VM86_INTx | (intno << 8)); | |
227 | +} | |
228 | + | |
109 | 229 | void cpu_loop(struct CPUX86State *env) |
110 | 230 | { |
111 | - int err; | |
231 | + int trapnr; | |
112 | 232 | uint8_t *pc; |
113 | 233 | target_siginfo_t info; |
114 | 234 | |
115 | 235 | for(;;) { |
116 | - err = cpu_x86_exec(env); | |
236 | + trapnr = cpu_x86_exec(env); | |
117 | 237 | pc = env->seg_cache[R_CS].base + env->eip; |
118 | - switch(err) { | |
238 | + switch(trapnr) { | |
119 | 239 | case EXCP0D_GPF: |
120 | 240 | if (env->eflags & VM_MASK) { |
121 | - TaskState *ts; | |
122 | - int ret; | |
123 | 241 | #ifdef DEBUG_VM86 |
124 | - printf("VM86 exception %04x:%08x %02x\n", | |
125 | - env->segs[R_CS], env->eip, pc[0]); | |
242 | + printf("VM86 exception %04x:%08x %02x %02x\n", | |
243 | + env->segs[R_CS], env->eip, pc[0], pc[1]); | |
126 | 244 | #endif |
127 | 245 | /* VM86 mode */ |
128 | - ts = env->opaque; | |
129 | - | |
130 | - /* XXX: add all cases */ | |
131 | 246 | switch(pc[0]) { |
132 | 247 | case 0xcd: /* int */ |
133 | 248 | env->eip += 2; |
134 | - ret = TARGET_VM86_INTx | (pc[1] << 8); | |
249 | + do_int(env, pc[1]); | |
250 | + break; | |
251 | + case 0x66: | |
252 | + switch(pc[1]) { | |
253 | + case 0xfb: /* sti */ | |
254 | + case 0x9d: /* popf */ | |
255 | + case 0xcf: /* iret */ | |
256 | + env->eip += 2; | |
257 | + return_to_32bit(env, TARGET_VM86_STI); | |
258 | + break; | |
259 | + default: | |
260 | + goto vm86_gpf; | |
261 | + } | |
262 | + break; | |
263 | + case 0xfb: /* sti */ | |
264 | + case 0x9d: /* popf */ | |
265 | + case 0xcf: /* iret */ | |
266 | + env->eip++; | |
267 | + return_to_32bit(env, TARGET_VM86_STI); | |
135 | 268 | break; |
136 | 269 | default: |
270 | + vm86_gpf: | |
137 | 271 | /* real VM86 GPF exception */ |
138 | - ret = TARGET_VM86_UNKNOWN; | |
272 | + return_to_32bit(env, TARGET_VM86_UNKNOWN); | |
139 | 273 | break; |
140 | 274 | } |
141 | -#ifdef DEBUG_VM86 | |
142 | - printf("ret=0x%x\n", ret); | |
143 | -#endif | |
144 | - /* put the VM86 registers in the userspace register structure */ | |
145 | - ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]); | |
146 | - ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]); | |
147 | - ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]); | |
148 | - ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]); | |
149 | - ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]); | |
150 | - ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]); | |
151 | - ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]); | |
152 | - ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]); | |
153 | - ts->target_v86->regs.eip = tswap32(env->eip); | |
154 | - ts->target_v86->regs.cs = tswap16(env->segs[R_CS]); | |
155 | - ts->target_v86->regs.ss = tswap16(env->segs[R_SS]); | |
156 | - ts->target_v86->regs.ds = tswap16(env->segs[R_DS]); | |
157 | - ts->target_v86->regs.es = tswap16(env->segs[R_ES]); | |
158 | - ts->target_v86->regs.fs = tswap16(env->segs[R_FS]); | |
159 | - ts->target_v86->regs.gs = tswap16(env->segs[R_GS]); | |
160 | - | |
161 | - /* restore 32 bit registers */ | |
162 | - env->regs[R_EBX] = ts->vm86_saved_regs.ebx; | |
163 | - env->regs[R_ECX] = ts->vm86_saved_regs.ecx; | |
164 | - env->regs[R_EDX] = ts->vm86_saved_regs.edx; | |
165 | - env->regs[R_ESI] = ts->vm86_saved_regs.esi; | |
166 | - env->regs[R_EDI] = ts->vm86_saved_regs.edi; | |
167 | - env->regs[R_EBP] = ts->vm86_saved_regs.ebp; | |
168 | - env->regs[R_ESP] = ts->vm86_saved_regs.esp; | |
169 | - env->eflags = ts->vm86_saved_regs.eflags; | |
170 | - env->eip = ts->vm86_saved_regs.eip; | |
171 | - | |
172 | - cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs); | |
173 | - cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss); | |
174 | - cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds); | |
175 | - cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es); | |
176 | - cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs); | |
177 | - cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs); | |
178 | - | |
179 | - env->regs[R_EAX] = ret; | |
180 | 275 | } else { |
181 | 276 | if (pc[0] == 0xcd && pc[1] == 0x80) { |
182 | 277 | /* syscall */ |
... | ... | @@ -200,20 +295,28 @@ void cpu_loop(struct CPUX86State *env) |
200 | 295 | } |
201 | 296 | break; |
202 | 297 | case EXCP00_DIVZ: |
203 | - /* division by zero */ | |
204 | - info.si_signo = SIGFPE; | |
205 | - info.si_errno = 0; | |
206 | - info.si_code = TARGET_FPE_INTDIV; | |
207 | - info._sifields._sigfault._addr = env->eip; | |
208 | - queue_signal(info.si_signo, &info); | |
298 | + if (env->eflags & VM_MASK) { | |
299 | + do_int(env, trapnr); | |
300 | + } else { | |
301 | + /* division by zero */ | |
302 | + info.si_signo = SIGFPE; | |
303 | + info.si_errno = 0; | |
304 | + info.si_code = TARGET_FPE_INTDIV; | |
305 | + info._sifields._sigfault._addr = env->eip; | |
306 | + queue_signal(info.si_signo, &info); | |
307 | + } | |
209 | 308 | break; |
210 | 309 | case EXCP04_INTO: |
211 | 310 | case EXCP05_BOUND: |
212 | - info.si_signo = SIGSEGV; | |
213 | - info.si_errno = 0; | |
214 | - info.si_code = 0; | |
215 | - info._sifields._sigfault._addr = 0; | |
216 | - queue_signal(info.si_signo, &info); | |
311 | + if (env->eflags & VM_MASK) { | |
312 | + do_int(env, trapnr); | |
313 | + } else { | |
314 | + info.si_signo = SIGSEGV; | |
315 | + info.si_errno = 0; | |
316 | + info.si_code = 0; | |
317 | + info._sifields._sigfault._addr = 0; | |
318 | + queue_signal(info.si_signo, &info); | |
319 | + } | |
217 | 320 | break; |
218 | 321 | case EXCP06_ILLOP: |
219 | 322 | info.si_signo = SIGILL; |
... | ... | @@ -226,8 +329,8 @@ void cpu_loop(struct CPUX86State *env) |
226 | 329 | /* just indicate that signals should be handled asap */ |
227 | 330 | break; |
228 | 331 | default: |
229 | - fprintf(stderr, "0x%08lx: Unknown exception CPU %d, aborting\n", | |
230 | - (long)pc, err); | |
332 | + fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", | |
333 | + (long)pc, trapnr); | |
231 | 334 | abort(); |
232 | 335 | } |
233 | 336 | process_pending_signals(env); | ... | ... |
linux-user/qemu.h
linux-user/signal.c
... | ... | @@ -198,7 +198,7 @@ void __attribute((noreturn)) force_sig(int sig) |
198 | 198 | { |
199 | 199 | int host_sig; |
200 | 200 | host_sig = target_to_host_signal(sig); |
201 | - fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n", | |
201 | + fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", | |
202 | 202 | sig, strsignal(host_sig)); |
203 | 203 | #if 1 |
204 | 204 | _exit(-host_sig); |
... | ... | @@ -223,7 +223,7 @@ int queue_signal(int sig, target_siginfo_t *info) |
223 | 223 | target_ulong handler; |
224 | 224 | |
225 | 225 | #if defined(DEBUG_SIGNAL) |
226 | - fprintf(stderr, "queue_sigal: sig=%d\n", | |
226 | + fprintf(stderr, "queue_signal: sig=%d\n", | |
227 | 227 | sig); |
228 | 228 | #endif |
229 | 229 | k = &sigact_table[sig - 1]; |
... | ... | @@ -317,7 +317,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, |
317 | 317 | if (sig < 1 || sig > TARGET_NSIG) |
318 | 318 | return; |
319 | 319 | #if defined(DEBUG_SIGNAL) |
320 | - fprintf(stderr, "gemu: got signal %d\n", sig); | |
320 | + fprintf(stderr, "qemu: got signal %d\n", sig); | |
321 | 321 | dump_regs(puc); |
322 | 322 | #endif |
323 | 323 | host_to_target_siginfo_noswap(&tinfo, info); |
... | ... | @@ -538,7 +538,6 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
538 | 538 | /* non-iBCS2 extensions.. */ |
539 | 539 | err |= __put_user(mask, &sc->oldmask); |
540 | 540 | err |= __put_user(/*current->thread.cr2*/ 0, &sc->cr2); |
541 | - | |
542 | 541 | return err; |
543 | 542 | } |
544 | 543 | |
... | ... | @@ -859,7 +858,7 @@ void process_pending_signals(void *cpu_env) |
859 | 858 | |
860 | 859 | handle_signal: |
861 | 860 | #ifdef DEBUG_SIGNAL |
862 | - fprintf(stderr, "gemu: process signal %d\n", sig); | |
861 | + fprintf(stderr, "qemu: process signal %d\n", sig); | |
863 | 862 | #endif |
864 | 863 | /* dequeue signal */ |
865 | 864 | q = k->first; |
... | ... | @@ -893,6 +892,14 @@ void process_pending_signals(void *cpu_env) |
893 | 892 | end of the signal execution (see do_sigreturn) */ |
894 | 893 | host_to_target_sigset(&target_old_set, &old_set); |
895 | 894 | |
895 | + /* if the CPU is in VM86 mode, we restore the 32 bit values */ | |
896 | +#ifdef TARGET_I386 | |
897 | + { | |
898 | + CPUX86State *env = cpu_env; | |
899 | + if (env->eflags & VM_MASK) | |
900 | + save_v86_state(env); | |
901 | + } | |
902 | +#endif | |
896 | 903 | /* prepare the stack frame of the virtual CPU */ |
897 | 904 | if (k->sa.sa_flags & TARGET_SA_SIGINFO) |
898 | 905 | setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env); | ... | ... |
syscall-i386.h
... | ... | @@ -755,6 +755,11 @@ struct target_modify_ldt_ldt_s { |
755 | 755 | unsigned int flags; |
756 | 756 | }; |
757 | 757 | |
758 | + | |
759 | +/* vm86 defines */ | |
760 | + | |
761 | +#define TARGET_BIOSSEG 0x0f000 | |
762 | + | |
758 | 763 | #define TARGET_VM86_SIGNAL 0 /* return due to signal */ |
759 | 764 | #define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ |
760 | 765 | #define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */ | ... | ... |