Commit 838104f60845adfa3ff5ad30e7f3a28c76f42bea

Authored by bellard
1 parent abf28337

removed


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3550 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 0 additions and 1323 deletions
target-i386/translate-copy.c deleted 100644 → 0
1 -/*  
2 - * i386 on i386 translation  
3 - *  
4 - * Copyright (c) 2003 Fabrice Bellard  
5 - *  
6 - * This library is free software; you can redistribute it and/or  
7 - * modify it under the terms of the GNU Lesser General Public  
8 - * License as published by the Free Software Foundation; either  
9 - * version 2 of the License, or (at your option) any later version.  
10 - *  
11 - * This library is distributed in the hope that it will be useful,  
12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of  
13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
14 - * Lesser General Public License for more details.  
15 - *  
16 - * You should have received a copy of the GNU Lesser General Public  
17 - * License along with this library; if not, write to the Free Software  
18 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  
19 - */  
20 -#include "config.h"  
21 -  
22 -#include <stdarg.h>  
23 -#include <stdlib.h>  
24 -#include <stdio.h>  
25 -#include <string.h>  
26 -#include <inttypes.h>  
27 -#include <assert.h>  
28 -  
29 -#include "cpu.h"  
30 -#include "exec-all.h"  
31 -#include "disas.h"  
32 -  
33 -#ifdef USE_CODE_COPY  
34 -  
35 -#include <signal.h>  
36 -#include <sys/mman.h>  
37 -#include <sys/ucontext.h>  
38 -  
39 -extern char exec_loop;  
40 -  
41 -/* operand size */  
42 -enum {  
43 - OT_BYTE = 0,  
44 - OT_WORD,  
45 - OT_LONG,  
46 - OT_QUAD,  
47 -};  
48 -  
49 -#define PREFIX_REPZ 0x01  
50 -#define PREFIX_REPNZ 0x02  
51 -#define PREFIX_LOCK 0x04  
52 -#define PREFIX_DATA 0x08  
53 -#define PREFIX_ADR 0x10  
54 -  
55 -typedef struct DisasContext {  
56 - /* current insn context */  
57 - int override; /* -1 if no override */  
58 - int prefix;  
59 - int aflag, dflag;  
60 - target_ulong pc; /* pc = eip + cs_base */  
61 - int is_jmp; /* 1 = means jump (stop translation), 2 means CPU  
62 - static state change (stop translation) */  
63 - /* code output */  
64 - uint8_t *gen_code_ptr;  
65 - uint8_t *gen_code_start;  
66 -  
67 - /* current block context */  
68 - target_ulong cs_base; /* base of CS segment */  
69 - int pe; /* protected mode */  
70 - int code32; /* 32 bit code segment */  
71 - int f_st; /* currently unused */  
72 - int vm86; /* vm86 mode */  
73 - int cpl;  
74 - int iopl;  
75 - int flags;  
76 - struct TranslationBlock *tb;  
77 -} DisasContext;  
78 -  
79 -#define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)  
80 -  
81 -#define CPU_SEG 0x64 /* fs override */  
82 -  
83 -static inline void gb(DisasContext *s, uint32_t val)  
84 -{  
85 - *s->gen_code_ptr++ = val;  
86 -}  
87 -  
88 -static inline void gw(DisasContext *s, uint32_t val)  
89 -{  
90 - *s->gen_code_ptr++ = val;  
91 - *s->gen_code_ptr++ = val >> 8;  
92 -}  
93 -  
94 -static inline void gl(DisasContext *s, uint32_t val)  
95 -{  
96 - *s->gen_code_ptr++ = val;  
97 - *s->gen_code_ptr++ = val >> 8;  
98 - *s->gen_code_ptr++ = val >> 16;  
99 - *s->gen_code_ptr++ = val >> 24;  
100 -}  
101 -  
102 -static inline void gjmp(DisasContext *s, long val)  
103 -{  
104 - gb(s, 0xe9); /* jmp */  
105 - gl(s, val - (long)(s->gen_code_ptr + 4));  
106 -}  
107 -  
108 -static inline void gen_movl_addr_im(DisasContext *s,  
109 - uint32_t addr, uint32_t val)  
110 -{  
111 - gb(s, CPU_SEG); /* seg movl im, addr */  
112 - gb(s, 0xc7);  
113 - gb(s, 0x05);  
114 - gl(s, addr);  
115 - gl(s, val);  
116 -}  
117 -  
118 -static inline void gen_movw_addr_im(DisasContext *s,  
119 - uint32_t addr, uint32_t val)  
120 -{  
121 - gb(s, CPU_SEG); /* seg movl im, addr */  
122 - gb(s, 0x66);  
123 - gb(s, 0xc7);  
124 - gb(s, 0x05);  
125 - gl(s, addr);  
126 - gw(s, val);  
127 -}  
128 -  
129 -  
130 -static void gen_jmp(DisasContext *s, uint32_t target_eip)  
131 -{  
132 - TranslationBlock *tb = s->tb;  
133 -  
134 - gb(s, 0xe9); /* jmp */  
135 - tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;  
136 - gl(s, 0);  
137 -  
138 - tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;  
139 - gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);  
140 - gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);  
141 - gjmp(s, (long)&exec_loop);  
142 -  
143 - s->is_jmp = 1;  
144 -}  
145 -  
146 -static void gen_jcc(DisasContext *s, int op,  
147 - uint32_t target_eip, uint32_t next_eip)  
148 -{  
149 - TranslationBlock *tb = s->tb;  
150 -  
151 - gb(s, 0x0f); /* jcc */  
152 - gb(s, 0x80 + op);  
153 - tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;  
154 - gl(s, 0);  
155 - gb(s, 0xe9); /* jmp */  
156 - tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;  
157 - gl(s, 0);  
158 -  
159 - tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;  
160 - gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);  
161 - gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);  
162 - gjmp(s, (long)&exec_loop);  
163 -  
164 - tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;  
165 - gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);  
166 - gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);  
167 - gjmp(s, (long)&exec_loop);  
168 -  
169 - s->is_jmp = 1;  
170 -}  
171 -  
172 -static void gen_eob(DisasContext *s)  
173 -{  
174 - gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);  
175 - gjmp(s, (long)&exec_loop);  
176 -  
177 - s->is_jmp = 1;  
178 -}  
179 -  
180 -static inline void gen_lea_modrm(DisasContext *s, int modrm)  
181 -{  
182 - int havesib;  
183 - int base, disp;  
184 - int index;  
185 - int scale;  
186 - int mod, rm, code;  
187 -  
188 - mod = (modrm >> 6) & 3;  
189 - rm = modrm & 7;  
190 -  
191 - if (s->aflag) {  
192 -  
193 - havesib = 0;  
194 - base = rm;  
195 - index = 0;  
196 - scale = 0;  
197 -  
198 - if (base == 4) {  
199 - havesib = 1;  
200 - code = ldub_code(s->pc++);  
201 - scale = (code >> 6) & 3;  
202 - index = (code >> 3) & 7;  
203 - base = code & 7;  
204 - }  
205 -  
206 - switch (mod) {  
207 - case 0:  
208 - if (base == 5) {  
209 - base = -1;  
210 - disp = ldl_code(s->pc);  
211 - s->pc += 4;  
212 - } else {  
213 - disp = 0;  
214 - }  
215 - break;  
216 - case 1:  
217 - disp = (int8_t)ldub_code(s->pc++);  
218 - break;  
219 - default:  
220 - case 2:  
221 - disp = ldl_code(s->pc);  
222 - s->pc += 4;  
223 - break;  
224 - }  
225 -  
226 - } else {  
227 - switch (mod) {  
228 - case 0:  
229 - if (rm == 6) {  
230 - disp = lduw_code(s->pc);  
231 - s->pc += 2;  
232 - } else {  
233 - disp = 0;  
234 - }  
235 - break;  
236 - case 1:  
237 - disp = (int8_t)ldub_code(s->pc++);  
238 - break;  
239 - default:  
240 - case 2:  
241 - disp = lduw_code(s->pc);  
242 - s->pc += 2;  
243 - break;  
244 - }  
245 - }  
246 -}  
247 -  
248 -static inline void parse_modrm(DisasContext *s, int modrm)  
249 -{  
250 - if ((modrm & 0xc0) != 0xc0)  
251 - gen_lea_modrm(s, modrm);  
252 -}  
253 -  
254 -static inline uint32_t insn_get(DisasContext *s, int ot)  
255 -{  
256 - uint32_t ret;  
257 -  
258 - switch(ot) {  
259 - case OT_BYTE:  
260 - ret = ldub_code(s->pc);  
261 - s->pc++;  
262 - break;  
263 - case OT_WORD:  
264 - ret = lduw_code(s->pc);  
265 - s->pc += 2;  
266 - break;  
267 - default:  
268 - case OT_LONG:  
269 - ret = ldl_code(s->pc);  
270 - s->pc += 4;  
271 - break;  
272 - }  
273 - return ret;  
274 -}  
275 -  
276 -/* convert one instruction. s->is_jmp is set if the translation must  
277 - be stopped. */  
278 -static int disas_insn(DisasContext *s)  
279 -{  
280 - target_ulong pc_start, pc_tmp, pc_start_insn;  
281 - int b, prefixes, aflag, dflag, next_eip, val;  
282 - int ot;  
283 - int modrm, mod, op, rm;  
284 -  
285 - pc_start = s->pc;  
286 - prefixes = 0;  
287 - aflag = s->code32;  
288 - dflag = s->code32;  
289 - s->override = -1;  
290 - next_byte:  
291 - b = ldub_code(s->pc);  
292 - s->pc++;  
293 - /* check prefixes */  
294 - switch (b) {  
295 - case 0xf3:  
296 - prefixes |= PREFIX_REPZ;  
297 - goto next_byte;  
298 - case 0xf2:  
299 - prefixes |= PREFIX_REPNZ;  
300 - goto next_byte;  
301 - case 0xf0:  
302 - prefixes |= PREFIX_LOCK;  
303 - goto next_byte;  
304 - case 0x2e:  
305 - s->override = R_CS;  
306 - goto next_byte;  
307 - case 0x36:  
308 - s->override = R_SS;  
309 - goto next_byte;  
310 - case 0x3e:  
311 - s->override = R_DS;  
312 - goto next_byte;  
313 - case 0x26:  
314 - s->override = R_ES;  
315 - goto next_byte;  
316 - case 0x64:  
317 - s->override = R_FS;  
318 - goto next_byte;  
319 - case 0x65:  
320 - s->override = R_GS;  
321 - goto next_byte;  
322 - case 0x66:  
323 - prefixes |= PREFIX_DATA;  
324 - goto next_byte;  
325 - case 0x67:  
326 - prefixes |= PREFIX_ADR;  
327 - goto next_byte;  
328 - }  
329 -  
330 - if (prefixes & PREFIX_DATA)  
331 - dflag ^= 1;  
332 - if (prefixes & PREFIX_ADR)  
333 - aflag ^= 1;  
334 -  
335 - s->prefix = prefixes;  
336 - s->aflag = aflag;  
337 - s->dflag = dflag;  
338 -  
339 - /* lock generation */  
340 - if (prefixes & PREFIX_LOCK)  
341 - goto unsupported_op;  
342 - if (s->override == R_FS || s->override == R_GS || s->override == R_CS)  
343 - goto unsupported_op;  
344 -  
345 - pc_start_insn = s->pc - 1;  
346 - /* now check op code */  
347 - reswitch:  
348 - switch(b) {  
349 - case 0x0f:  
350 - /**************************/  
351 - /* extended op code */  
352 - b = ldub_code(s->pc++) | 0x100;  
353 - goto reswitch;  
354 -  
355 - /**************************/  
356 - /* arith & logic */  
357 - case 0x00 ... 0x05:  
358 - case 0x08 ... 0x0d:  
359 - case 0x10 ... 0x15:  
360 - case 0x18 ... 0x1d:  
361 - case 0x20 ... 0x25:  
362 - case 0x28 ... 0x2d:  
363 - case 0x30 ... 0x35:  
364 - case 0x38 ... 0x3d:  
365 - {  
366 - int f;  
367 - f = (b >> 1) & 3;  
368 -  
369 - if ((b & 1) == 0)  
370 - ot = OT_BYTE;  
371 - else  
372 - ot = dflag ? OT_LONG : OT_WORD;  
373 -  
374 - switch(f) {  
375 - case 0: /* OP Ev, Gv */  
376 - modrm = ldub_code(s->pc++);  
377 - parse_modrm(s, modrm);  
378 - break;  
379 - case 1: /* OP Gv, Ev */  
380 - modrm = ldub_code(s->pc++);  
381 - parse_modrm(s, modrm);  
382 - break;  
383 - case 2: /* OP A, Iv */  
384 - insn_get(s, ot);  
385 - break;  
386 - }  
387 - }  
388 - break;  
389 -  
390 - case 0x80: /* GRP1 */  
391 - case 0x81:  
392 - case 0x82:  
393 - case 0x83:  
394 - {  
395 - if ((b & 1) == 0)  
396 - ot = OT_BYTE;  
397 - else  
398 - ot = dflag ? OT_LONG : OT_WORD;  
399 -  
400 - modrm = ldub_code(s->pc++);  
401 - parse_modrm(s, modrm);  
402 -  
403 - switch(b) {  
404 - default:  
405 - case 0x80:  
406 - case 0x81:  
407 - case 0x82:  
408 - insn_get(s, ot);  
409 - break;  
410 - case 0x83:  
411 - insn_get(s, OT_BYTE);  
412 - break;  
413 - }  
414 - }  
415 - break;  
416 -  
417 - /**************************/  
418 - /* inc, dec, and other misc arith */  
419 - case 0x40 ... 0x47: /* inc Gv */  
420 - break;  
421 - case 0x48 ... 0x4f: /* dec Gv */  
422 - break;  
423 - case 0xf6: /* GRP3 */  
424 - case 0xf7:  
425 - if ((b & 1) == 0)  
426 - ot = OT_BYTE;  
427 - else  
428 - ot = dflag ? OT_LONG : OT_WORD;  
429 -  
430 - modrm = ldub_code(s->pc++);  
431 - op = (modrm >> 3) & 7;  
432 - parse_modrm(s, modrm);  
433 -  
434 - switch(op) {  
435 - case 0: /* test */  
436 - insn_get(s, ot);  
437 - break;  
438 - case 2: /* not */  
439 - break;  
440 - case 3: /* neg */  
441 - break;  
442 - case 4: /* mul */  
443 - break;  
444 - case 5: /* imul */  
445 - break;  
446 - case 6: /* div */  
447 - break;  
448 - case 7: /* idiv */  
449 - break;  
450 - default:  
451 - goto illegal_op;  
452 - }  
453 - break;  
454 -  
455 - case 0xfe: /* GRP4 */  
456 - case 0xff: /* GRP5 */  
457 - if ((b & 1) == 0)  
458 - ot = OT_BYTE;  
459 - else  
460 - ot = dflag ? OT_LONG : OT_WORD;  
461 -  
462 - modrm = ldub_code(s->pc++);  
463 - mod = (modrm >> 6) & 3;  
464 - op = (modrm >> 3) & 7;  
465 - if (op >= 2 && b == 0xfe) {  
466 - goto illegal_op;  
467 - }  
468 - pc_tmp = s->pc;  
469 - parse_modrm(s, modrm);  
470 -  
471 - switch(op) {  
472 - case 0: /* inc Ev */  
473 - break;  
474 - case 1: /* dec Ev */  
475 - break;  
476 - case 2: /* call Ev */  
477 - /* XXX: optimize and handle MEM exceptions specifically  
478 - fs movl %eax, regs[0]  
479 - movl Ev, %eax  
480 - pushl next_eip  
481 - fs movl %eax, eip  
482 - */  
483 - goto unsupported_op;  
484 - case 3: /* lcall Ev */  
485 - goto unsupported_op;  
486 - case 4: /* jmp Ev */  
487 - /* XXX: optimize and handle MEM exceptions specifically  
488 - fs movl %eax, regs[0]  
489 - movl Ev, %eax  
490 - fs movl %eax, eip  
491 - */  
492 - goto unsupported_op;  
493 - case 5: /* ljmp Ev */  
494 - goto unsupported_op;  
495 - case 6: /* push Ev */  
496 - break;  
497 - default:  
498 - goto illegal_op;  
499 - }  
500 - break;  
501 - case 0xa8: /* test eAX, Iv */  
502 - case 0xa9:  
503 - if ((b & 1) == 0)  
504 - ot = OT_BYTE;  
505 - else  
506 - ot = dflag ? OT_LONG : OT_WORD;  
507 - insn_get(s, ot);  
508 - break;  
509 -  
510 - case 0x98: /* CWDE/CBW */  
511 - break;  
512 - case 0x99: /* CDQ/CWD */  
513 - break;  
514 - case 0x1af: /* imul Gv, Ev */  
515 - case 0x69: /* imul Gv, Ev, I */  
516 - case 0x6b:  
517 - ot = dflag ? OT_LONG : OT_WORD;  
518 - modrm = ldub_code(s->pc++);  
519 - parse_modrm(s, modrm);  
520 - if (b == 0x69) {  
521 - insn_get(s, ot);  
522 - } else if (b == 0x6b) {  
523 - insn_get(s, OT_BYTE);  
524 - } else {  
525 - }  
526 - break;  
527 -  
528 - case 0x84: /* test Ev, Gv */  
529 - case 0x85:  
530 -  
531 - case 0x1c0:  
532 - case 0x1c1: /* xadd Ev, Gv */  
533 -  
534 - case 0x1b0:  
535 - case 0x1b1: /* cmpxchg Ev, Gv */  
536 -  
537 - case 0x8f: /* pop Ev */  
538 -  
539 - case 0x88:  
540 - case 0x89: /* mov Gv, Ev */  
541 -  
542 - case 0x8a:  
543 - case 0x8b: /* mov Ev, Gv */  
544 -  
545 - case 0x1b6: /* movzbS Gv, Eb */  
546 - case 0x1b7: /* movzwS Gv, Eb */  
547 - case 0x1be: /* movsbS Gv, Eb */  
548 - case 0x1bf: /* movswS Gv, Eb */  
549 -  
550 - case 0x86:  
551 - case 0x87: /* xchg Ev, Gv */  
552 -  
553 - case 0xd0:  
554 - case 0xd1: /* shift Ev,1 */  
555 -  
556 - case 0xd2:  
557 - case 0xd3: /* shift Ev,cl */  
558 -  
559 - case 0x1a5: /* shld cl */  
560 - case 0x1ad: /* shrd cl */  
561 -  
562 - case 0x190 ... 0x19f: /* setcc Gv */  
563 -  
564 - /* XXX: emulate cmov if not available ? */  
565 - case 0x140 ... 0x14f: /* cmov Gv, Ev */  
566 -  
567 - case 0x1a3: /* bt Gv, Ev */  
568 - case 0x1ab: /* bts */  
569 - case 0x1b3: /* btr */  
570 - case 0x1bb: /* btc */  
571 -  
572 - case 0x1bc: /* bsf */  
573 - case 0x1bd: /* bsr */  
574 -  
575 - modrm = ldub_code(s->pc++);  
576 - parse_modrm(s, modrm);  
577 - break;  
578 -  
579 - case 0x1c7: /* cmpxchg8b */  
580 - modrm = ldub_code(s->pc++);  
581 - mod = (modrm >> 6) & 3;  
582 - if (mod == 3)  
583 - goto illegal_op;  
584 - parse_modrm(s, modrm);  
585 - break;  
586 -  
587 - /**************************/  
588 - /* push/pop */  
589 - case 0x50 ... 0x57: /* push */  
590 - case 0x58 ... 0x5f: /* pop */  
591 - case 0x60: /* pusha */  
592 - case 0x61: /* popa */  
593 - break;  
594 -  
595 - case 0x68: /* push Iv */  
596 - case 0x6a:  
597 - ot = dflag ? OT_LONG : OT_WORD;  
598 - if (b == 0x68)  
599 - insn_get(s, ot);  
600 - else  
601 - insn_get(s, OT_BYTE);  
602 - break;  
603 - case 0xc8: /* enter */  
604 - lduw_code(s->pc);  
605 - s->pc += 2;  
606 - ldub_code(s->pc++);  
607 - break;  
608 - case 0xc9: /* leave */  
609 - break;  
610 -  
611 - case 0x06: /* push es */  
612 - case 0x0e: /* push cs */  
613 - case 0x16: /* push ss */  
614 - case 0x1e: /* push ds */  
615 - /* XXX: optimize:  
616 - push segs[n].selector  
617 - */  
618 - goto unsupported_op;  
619 - case 0x1a0: /* push fs */  
620 - case 0x1a8: /* push gs */  
621 - goto unsupported_op;  
622 - case 0x07: /* pop es */  
623 - case 0x17: /* pop ss */  
624 - case 0x1f: /* pop ds */  
625 - goto unsupported_op;  
626 - case 0x1a1: /* pop fs */  
627 - case 0x1a9: /* pop gs */  
628 - goto unsupported_op;  
629 - case 0x8e: /* mov seg, Gv */  
630 - /* XXX: optimize:  
631 - fs movl r, regs[]  
632 - movl segs[].selector, r  
633 - mov r, Gv  
634 - fs movl regs[], r  
635 - */  
636 - goto unsupported_op;  
637 - case 0x8c: /* mov Gv, seg */  
638 - goto unsupported_op;  
639 - case 0xc4: /* les Gv */  
640 - op = R_ES;  
641 - goto do_lxx;  
642 - case 0xc5: /* lds Gv */  
643 - op = R_DS;  
644 - goto do_lxx;  
645 - case 0x1b2: /* lss Gv */  
646 - op = R_SS;  
647 - goto do_lxx;  
648 - case 0x1b4: /* lfs Gv */  
649 - op = R_FS;  
650 - goto do_lxx;  
651 - case 0x1b5: /* lgs Gv */  
652 - op = R_GS;  
653 - do_lxx:  
654 - goto unsupported_op;  
655 - /************************/  
656 - /* floats */  
657 - case 0xd8 ... 0xdf:  
658 -#if 1  
659 - /* currently not stable enough */  
660 - goto unsupported_op;  
661 -#else  
662 - if (s->flags & (HF_EM_MASK | HF_TS_MASK))  
663 - goto unsupported_op;  
664 -#endif  
665 -#if 0  
666 - /* for testing FPU context switch */  
667 - {  
668 - static int count;  
669 - count = (count + 1) % 3;  
670 - if (count != 0)  
671 - goto unsupported_op;  
672 - }  
673 -#endif  
674 - modrm = ldub_code(s->pc++);  
675 - mod = (modrm >> 6) & 3;  
676 - rm = modrm & 7;  
677 - op = ((b & 7) << 3) | ((modrm >> 3) & 7);  
678 - if (mod != 3) {  
679 - /* memory op */  
680 - parse_modrm(s, modrm);  
681 - switch(op) {  
682 - case 0x00 ... 0x07: /* fxxxs */  
683 - case 0x10 ... 0x17: /* fixxxl */  
684 - case 0x20 ... 0x27: /* fxxxl */  
685 - case 0x30 ... 0x37: /* fixxx */  
686 - break;  
687 - case 0x08: /* flds */  
688 - case 0x0a: /* fsts */  
689 - case 0x0b: /* fstps */  
690 - case 0x18: /* fildl */  
691 - case 0x1a: /* fistl */  
692 - case 0x1b: /* fistpl */  
693 - case 0x28: /* fldl */  
694 - case 0x2a: /* fstl */  
695 - case 0x2b: /* fstpl */  
696 - case 0x38: /* filds */  
697 - case 0x3a: /* fists */  
698 - case 0x3b: /* fistps */  
699 - case 0x0c: /* fldenv mem */  
700 - case 0x0d: /* fldcw mem */  
701 - case 0x0e: /* fnstenv mem */  
702 - case 0x0f: /* fnstcw mem */  
703 - case 0x1d: /* fldt mem */  
704 - case 0x1f: /* fstpt mem */  
705 - case 0x2c: /* frstor mem */  
706 - case 0x2e: /* fnsave mem */  
707 - case 0x2f: /* fnstsw mem */  
708 - case 0x3c: /* fbld */  
709 - case 0x3e: /* fbstp */  
710 - case 0x3d: /* fildll */  
711 - case 0x3f: /* fistpll */  
712 - break;  
713 - default:  
714 - goto illegal_op;  
715 - }  
716 - } else {  
717 - /* register float ops */  
718 - switch(op) {  
719 - case 0x08: /* fld sti */  
720 - case 0x09: /* fxchg sti */  
721 - break;  
722 - case 0x0a: /* grp d9/2 */  
723 - switch(rm) {  
724 - case 0: /* fnop */  
725 - break;  
726 - default:  
727 - goto illegal_op;  
728 - }  
729 - break;  
730 - case 0x0c: /* grp d9/4 */  
731 - switch(rm) {  
732 - case 0: /* fchs */  
733 - case 1: /* fabs */  
734 - case 4: /* ftst */  
735 - case 5: /* fxam */  
736 - break;  
737 - default:  
738 - goto illegal_op;  
739 - }  
740 - break;  
741 - case 0x0d: /* grp d9/5 */  
742 - switch(rm) {  
743 - case 0:  
744 - case 1:  
745 - case 2:  
746 - case 3:  
747 - case 4:  
748 - case 5:  
749 - case 6:  
750 - break;  
751 - default:  
752 - goto illegal_op;  
753 - }  
754 - break;  
755 - case 0x0e: /* grp d9/6 */  
756 - break;  
757 - case 0x0f: /* grp d9/7 */  
758 - break;  
759 - case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */  
760 - case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */  
761 - case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */  
762 - break;  
763 - case 0x02: /* fcom */  
764 - break;  
765 - case 0x03: /* fcomp */  
766 - break;  
767 - case 0x15: /* da/5 */  
768 - switch(rm) {  
769 - case 1: /* fucompp */  
770 - break;  
771 - default:  
772 - goto illegal_op;  
773 - }  
774 - break;  
775 - case 0x1c:  
776 - switch(rm) {  
777 - case 0: /* feni (287 only, just do nop here) */  
778 - case 1: /* fdisi (287 only, just do nop here) */  
779 - goto unsupported_op;  
780 - case 2: /* fclex */  
781 - case 3: /* fninit */  
782 - case 4: /* fsetpm (287 only, just do nop here) */  
783 - break;  
784 - default:  
785 - goto illegal_op;  
786 - }  
787 - break;  
788 - case 0x1d: /* fucomi */  
789 - break;  
790 - case 0x1e: /* fcomi */  
791 - break;  
792 - case 0x28: /* ffree sti */  
793 - break;  
794 - case 0x2a: /* fst sti */  
795 - break;  
796 - case 0x2b: /* fstp sti */  
797 - break;  
798 - case 0x2c: /* fucom st(i) */  
799 - break;  
800 - case 0x2d: /* fucomp st(i) */  
801 - break;  
802 - case 0x33: /* de/3 */  
803 - switch(rm) {  
804 - case 1: /* fcompp */  
805 - break;  
806 - default:  
807 - goto illegal_op;  
808 - }  
809 - break;  
810 - case 0x3c: /* df/4 */  
811 - switch(rm) {  
812 - case 0:  
813 - break;  
814 - default:  
815 - goto illegal_op;  
816 - }  
817 - break;  
818 - case 0x3d: /* fucomip */  
819 - break;  
820 - case 0x3e: /* fcomip */  
821 - break;  
822 - case 0x10 ... 0x13: /* fcmovxx */  
823 - case 0x18 ... 0x1b:  
824 - break;  
825 - default:  
826 - goto illegal_op;  
827 - }  
828 - }  
829 - s->tb->cflags |= CF_TB_FP_USED;  
830 - break;  
831 -  
832 - /**************************/  
833 - /* mov */  
834 - case 0xc6:  
835 - case 0xc7: /* mov Ev, Iv */  
836 - if ((b & 1) == 0)  
837 - ot = OT_BYTE;  
838 - else  
839 - ot = dflag ? OT_LONG : OT_WORD;  
840 - modrm = ldub_code(s->pc++);  
841 - parse_modrm(s, modrm);  
842 - insn_get(s, ot);  
843 - break;  
844 -  
845 - case 0x8d: /* lea */  
846 - ot = dflag ? OT_LONG : OT_WORD;  
847 - modrm = ldub_code(s->pc++);  
848 - mod = (modrm >> 6) & 3;  
849 - if (mod == 3)  
850 - goto illegal_op;  
851 - parse_modrm(s, modrm);  
852 - break;  
853 -  
854 - case 0xa0: /* mov EAX, Ov */  
855 - case 0xa1:  
856 - case 0xa2: /* mov Ov, EAX */  
857 - case 0xa3:  
858 - if ((b & 1) == 0)  
859 - ot = OT_BYTE;  
860 - else  
861 - ot = dflag ? OT_LONG : OT_WORD;  
862 - if (s->aflag)  
863 - insn_get(s, OT_LONG);  
864 - else  
865 - insn_get(s, OT_WORD);  
866 - break;  
867 - case 0xd7: /* xlat */  
868 - break;  
869 - case 0xb0 ... 0xb7: /* mov R, Ib */  
870 - insn_get(s, OT_BYTE);  
871 - break;  
872 - case 0xb8 ... 0xbf: /* mov R, Iv */  
873 - ot = dflag ? OT_LONG : OT_WORD;  
874 - insn_get(s, ot);  
875 - break;  
876 -  
877 - case 0x91 ... 0x97: /* xchg R, EAX */  
878 - break;  
879 -  
880 - /************************/  
881 - /* shifts */  
882 - case 0xc0:  
883 - case 0xc1: /* shift Ev,imm */  
884 -  
885 - case 0x1a4: /* shld imm */  
886 - case 0x1ac: /* shrd imm */  
887 - modrm = ldub_code(s->pc++);  
888 - parse_modrm(s, modrm);  
889 - ldub_code(s->pc++);  
890 - break;  
891 -  
892 - /************************/  
893 - /* string ops */  
894 -  
895 - case 0xa4: /* movsS */  
896 - case 0xa5:  
897 - break;  
898 -  
899 - case 0xaa: /* stosS */  
900 - case 0xab:  
901 - break;  
902 -  
903 - case 0xac: /* lodsS */  
904 - case 0xad:  
905 - break;  
906 -  
907 - case 0xae: /* scasS */  
908 - case 0xaf:  
909 - break;  
910 -  
911 - case 0xa6: /* cmpsS */  
912 - case 0xa7:  
913 - break;  
914 -  
915 - case 0x6c: /* insS */  
916 - case 0x6d:  
917 - goto unsupported_op;  
918 -  
919 - case 0x6e: /* outsS */  
920 - case 0x6f:  
921 - goto unsupported_op;  
922 -  
923 - /************************/  
924 - /* port I/O */  
925 - case 0xe4:  
926 - case 0xe5:  
927 - goto unsupported_op;  
928 -  
929 - case 0xe6:  
930 - case 0xe7:  
931 - goto unsupported_op;  
932 -  
933 - case 0xec:  
934 - case 0xed:  
935 - goto unsupported_op;  
936 -  
937 - case 0xee:  
938 - case 0xef:  
939 - goto unsupported_op;  
940 -  
941 - /************************/  
942 - /* control */  
943 -#if 0  
944 - case 0xc2: /* ret im */  
945 - val = ldsw_code(s->pc);  
946 - s->pc += 2;  
947 - gen_pop_T0(s);  
948 - gen_stack_update(s, val + (2 << s->dflag));  
949 - if (s->dflag == 0)  
950 - gen_op_andl_T0_ffff();  
951 - gen_op_jmp_T0();  
952 - gen_eob(s);  
953 - break;  
954 -#endif  
955 -  
956 - case 0xc3: /* ret */  
957 - gb(s, CPU_SEG);  
958 - if (!s->dflag)  
959 - gb(s, 0x66); /* d16 */  
960 - gb(s, 0x8f); /* pop addr */  
961 - gb(s, 0x05);  
962 - gl(s, CPU_FIELD_OFFSET(eip));  
963 - if (!s->dflag) {  
964 - /* reset high bits of EIP */  
965 - gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);  
966 - }  
967 - gen_eob(s);  
968 - goto no_copy;  
969 - case 0xca: /* lret im */  
970 - case 0xcb: /* lret */  
971 - case 0xcf: /* iret */  
972 - case 0x9a: /* lcall im */  
973 - case 0xea: /* ljmp im */  
974 - goto unsupported_op;  
975 -  
976 - case 0xe8: /* call im */  
977 - ot = dflag ? OT_LONG : OT_WORD;  
978 - val = insn_get(s, ot);  
979 - next_eip = s->pc - s->cs_base;  
980 - val += next_eip;  
981 - if (s->dflag) {  
982 - gb(s, 0x68); /* pushl imm */  
983 - gl(s, next_eip);  
984 - } else {  
985 - gb(s, 0x66); /* pushw imm */  
986 - gb(s, 0x68);  
987 - gw(s, next_eip);  
988 - val &= 0xffff;  
989 - }  
990 - gen_jmp(s, val);  
991 - goto no_copy;  
992 - case 0xe9: /* jmp */  
993 - ot = dflag ? OT_LONG : OT_WORD;  
994 - val = insn_get(s, ot);  
995 - val += s->pc - s->cs_base;  
996 - if (s->dflag == 0)  
997 - val = val & 0xffff;  
998 - gen_jmp(s, val);  
999 - goto no_copy;  
1000 - case 0xeb: /* jmp Jb */  
1001 - val = (int8_t)insn_get(s, OT_BYTE);  
1002 - val += s->pc - s->cs_base;  
1003 - if (s->dflag == 0)  
1004 - val = val & 0xffff;  
1005 - gen_jmp(s, val);  
1006 - goto no_copy;  
1007 - case 0x70 ... 0x7f: /* jcc Jb */  
1008 - val = (int8_t)insn_get(s, OT_BYTE);  
1009 - goto do_jcc;  
1010 - case 0x180 ... 0x18f: /* jcc Jv */  
1011 - if (dflag) {  
1012 - val = insn_get(s, OT_LONG);  
1013 - } else {  
1014 - val = (int16_t)insn_get(s, OT_WORD);  
1015 - }  
1016 - do_jcc:  
1017 - next_eip = s->pc - s->cs_base;  
1018 - val += next_eip;  
1019 - if (s->dflag == 0)  
1020 - val &= 0xffff;  
1021 - gen_jcc(s, b & 0xf, val, next_eip);  
1022 - goto no_copy;  
1023 -  
1024 - /************************/  
1025 - /* flags */  
1026 - case 0x9c: /* pushf */  
1027 - /* XXX: put specific code ? */  
1028 - goto unsupported_op;  
1029 - case 0x9d: /* popf */  
1030 - goto unsupported_op;  
1031 -  
1032 - case 0x9e: /* sahf */  
1033 - case 0x9f: /* lahf */  
1034 - case 0xf5: /* cmc */  
1035 - case 0xf8: /* clc */  
1036 - case 0xf9: /* stc */  
1037 - case 0xfc: /* cld */  
1038 - case 0xfd: /* std */  
1039 - break;  
1040 -  
1041 - /************************/  
1042 - /* bit operations */  
1043 - case 0x1ba: /* bt/bts/btr/btc Gv, im */  
1044 - ot = dflag ? OT_LONG : OT_WORD;  
1045 - modrm = ldub_code(s->pc++);  
1046 - op = (modrm >> 3) & 7;  
1047 - parse_modrm(s, modrm);  
1048 - /* load shift */  
1049 - ldub_code(s->pc++);  
1050 - if (op < 4)  
1051 - goto illegal_op;  
1052 - break;  
1053 - /************************/  
1054 - /* bcd */  
1055 - case 0x27: /* daa */  
1056 - break;  
1057 - case 0x2f: /* das */  
1058 - break;  
1059 - case 0x37: /* aaa */  
1060 - break;  
1061 - case 0x3f: /* aas */  
1062 - break;  
1063 - case 0xd4: /* aam */  
1064 - ldub_code(s->pc++);  
1065 - break;  
1066 - case 0xd5: /* aad */  
1067 - ldub_code(s->pc++);  
1068 - break;  
1069 - /************************/  
1070 - /* misc */  
1071 - case 0x90: /* nop */  
1072 - break;  
1073 - case 0x9b: /* fwait */  
1074 - if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==  
1075 - (HF_MP_MASK | HF_TS_MASK)) {  
1076 - goto unsupported_op;  
1077 - }  
1078 - break;  
1079 - case 0xcc: /* int3 */  
1080 - goto unsupported_op;  
1081 - case 0xcd: /* int N */  
1082 - goto unsupported_op;  
1083 - case 0xce: /* into */  
1084 - goto unsupported_op;  
1085 - case 0xf1: /* icebp (undocumented, exits to external debugger) */  
1086 - goto unsupported_op;  
1087 - case 0xfa: /* cli */  
1088 - goto unsupported_op;  
1089 - case 0xfb: /* sti */  
1090 - goto unsupported_op;  
1091 - case 0x62: /* bound */  
1092 - modrm = ldub_code(s->pc++);  
1093 - mod = (modrm >> 6) & 3;  
1094 - if (mod == 3)  
1095 - goto illegal_op;  
1096 - parse_modrm(s, modrm);  
1097 - break;  
1098 - case 0x1c8 ... 0x1cf: /* bswap reg */  
1099 - break;  
1100 - case 0xd6: /* salc */  
1101 - break;  
1102 - case 0xe0: /* loopnz */  
1103 - case 0xe1: /* loopz */  
1104 - case 0xe2: /* loop */  
1105 - case 0xe3: /* jecxz */  
1106 - goto unsupported_op;  
1107 -  
1108 - case 0x130: /* wrmsr */  
1109 - case 0x132: /* rdmsr */  
1110 - goto unsupported_op;  
1111 - case 0x131: /* rdtsc */  
1112 - goto unsupported_op;  
1113 - case 0x1a2: /* cpuid */  
1114 - goto unsupported_op;  
1115 - case 0xf4: /* hlt */  
1116 - goto unsupported_op;  
1117 - case 0x100:  
1118 - goto unsupported_op;  
1119 - case 0x101:  
1120 - goto unsupported_op;  
1121 - case 0x108: /* invd */  
1122 - case 0x109: /* wbinvd */  
1123 - goto unsupported_op;  
1124 - case 0x63: /* arpl */  
1125 - goto unsupported_op;  
1126 - case 0x102: /* lar */  
1127 - case 0x103: /* lsl */  
1128 - goto unsupported_op;  
1129 - case 0x118:  
1130 - goto unsupported_op;  
1131 - case 0x120: /* mov reg, crN */  
1132 - case 0x122: /* mov crN, reg */  
1133 - goto unsupported_op;  
1134 - case 0x121: /* mov reg, drN */  
1135 - case 0x123: /* mov drN, reg */  
1136 - goto unsupported_op;  
1137 - case 0x106: /* clts */  
1138 - goto unsupported_op;  
1139 - default:  
1140 - goto illegal_op;  
1141 - }  
1142 -  
1143 - /* just copy the code */  
1144 -  
1145 - /* no override yet */  
1146 - if (!s->dflag)  
1147 - gb(s, 0x66);  
1148 - if (!s->aflag)  
1149 - gb(s, 0x67);  
1150 - if (prefixes & PREFIX_REPZ)  
1151 - gb(s, 0xf3);  
1152 - else if (prefixes & PREFIX_REPNZ)  
1153 - gb(s, 0xf2);  
1154 - {  
1155 - int len, i;  
1156 - len = s->pc - pc_start_insn;  
1157 - for(i = 0; i < len; i++) {  
1158 - *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);  
1159 - }  
1160 - }  
1161 - no_copy:  
1162 - return 0;  
1163 - illegal_op:  
1164 - unsupported_op:  
1165 - /* fall back to slower code gen necessary */  
1166 - s->pc = pc_start;  
1167 - return -1;  
1168 -}  
1169 -  
1170 -#define GEN_CODE_MAX_SIZE 8192  
1171 -#define GEN_CODE_MAX_INSN_SIZE 512  
1172 -  
1173 -static inline int gen_intermediate_code_internal(CPUState *env,  
1174 - TranslationBlock *tb,  
1175 - uint8_t *gen_code_ptr,  
1176 - int *gen_code_size_ptr,  
1177 - int search_pc,  
1178 - uint8_t *tc_ptr)  
1179 -{  
1180 - DisasContext dc1, *dc = &dc1;  
1181 - target_ulong pc_insn, pc_start, cs_base;  
1182 - uint8_t *gen_code_end;  
1183 - int flags, ret;  
1184 -  
1185 - if (env->nb_breakpoints > 0 ||  
1186 - env->singlestep_enabled)  
1187 - return -1;  
1188 - flags = tb->flags;  
1189 - if (flags & (HF_TF_MASK | HF_ADDSEG_MASK |  
1190 - HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))  
1191 - return -1;  
1192 - if (!(flags & HF_SS32_MASK))  
1193 - return -1;  
1194 - if (tb->cflags & CF_SINGLE_INSN)  
1195 - return -1;  
1196 - gen_code_end = gen_code_ptr +  
1197 - GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;  
1198 - dc->gen_code_ptr = gen_code_ptr;  
1199 - dc->gen_code_start = gen_code_ptr;  
1200 -  
1201 - /* generate intermediate code */  
1202 - pc_start = tb->pc;  
1203 - cs_base = tb->cs_base;  
1204 - dc->pc = pc_start;  
1205 - dc->cs_base = cs_base;  
1206 - dc->pe = (flags >> HF_PE_SHIFT) & 1;  
1207 - dc->code32 = (flags >> HF_CS32_SHIFT) & 1;  
1208 - dc->f_st = 0;  
1209 - dc->vm86 = (flags >> VM_SHIFT) & 1;  
1210 - dc->cpl = (flags >> HF_CPL_SHIFT) & 3;  
1211 - dc->iopl = (flags >> IOPL_SHIFT) & 3;  
1212 - dc->tb = tb;  
1213 - dc->flags = flags;  
1214 -  
1215 - dc->is_jmp = 0;  
1216 -  
1217 - for(;;) {  
1218 - pc_insn = dc->pc;  
1219 - ret = disas_insn(dc);  
1220 - if (ret < 0) {  
1221 - /* unsupported insn */  
1222 - if (dc->pc == pc_start) {  
1223 - /* if first instruction, signal that no copying was done */  
1224 - return -1;  
1225 - } else {  
1226 - gen_jmp(dc, dc->pc - dc->cs_base);  
1227 - dc->is_jmp = 1;  
1228 - }  
1229 - }  
1230 - if (search_pc) {  
1231 - /* search pc mode */  
1232 - if (tc_ptr < dc->gen_code_ptr) {  
1233 - env->eip = pc_insn - cs_base;  
1234 - return 0;  
1235 - }  
1236 - }  
1237 - /* stop translation if indicated */  
1238 - if (dc->is_jmp)  
1239 - break;  
1240 - /* if too long translation, stop generation */  
1241 - if (dc->gen_code_ptr >= gen_code_end ||  
1242 - (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {  
1243 - gen_jmp(dc, dc->pc - dc->cs_base);  
1244 - break;  
1245 - }  
1246 - }  
1247 -  
1248 -#ifdef DEBUG_DISAS  
1249 - if (loglevel & CPU_LOG_TB_IN_ASM) {  
1250 - fprintf(logfile, "----------------\n");  
1251 - fprintf(logfile, "IN: COPY: %s fpu=%d\n",  
1252 - lookup_symbol(pc_start),  
1253 - tb->cflags & CF_TB_FP_USED ? 1 : 0);  
1254 - target_disas(logfile, pc_start, dc->pc - pc_start, !dc->code32);  
1255 - fprintf(logfile, "\n");  
1256 - }  
1257 -#endif  
1258 -  
1259 - if (!search_pc) {  
1260 - *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;  
1261 - tb->size = dc->pc - pc_start;  
1262 - tb->cflags |= CF_CODE_COPY;  
1263 - return 0;  
1264 - } else {  
1265 - return -1;  
1266 - }  
1267 -}  
1268 -  
1269 -/* generate code by just copying data. Return -1 if cannot generate  
1270 - any code. Return 0 if code was generated */  
1271 -int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,  
1272 - int max_code_size, int *gen_code_size_ptr)  
1273 -{  
1274 - /* generate machine code */  
1275 - tb->tb_next_offset[0] = 0xffff;  
1276 - tb->tb_next_offset[1] = 0xffff;  
1277 -#ifdef USE_DIRECT_JUMP  
1278 - /* the following two entries are optional (only used for string ops) */  
1279 - tb->tb_jmp_offset[2] = 0xffff;  
1280 - tb->tb_jmp_offset[3] = 0xffff;  
1281 -#endif  
1282 - return gen_intermediate_code_internal(env, tb,  
1283 - tb->tc_ptr, gen_code_size_ptr,  
1284 - 0, NULL);  
1285 -}  
1286 -  
1287 -static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];  
1288 -  
1289 -int cpu_restore_state_copy(TranslationBlock *tb,  
1290 - CPUState *env, unsigned long searched_pc,  
1291 - void *puc)  
1292 -{  
1293 - struct ucontext *uc = puc;  
1294 - int ret, eflags;  
1295 -  
1296 - /* find opc index corresponding to search_pc */  
1297 - if (searched_pc < (unsigned long)tb->tc_ptr)  
1298 - return -1;  
1299 - searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;  
1300 - ret = gen_intermediate_code_internal(env, tb,  
1301 - dummy_gen_code_buf, NULL,  
1302 - 1, (uint8_t *)searched_pc);  
1303 - if (ret < 0)  
1304 - return ret;  
1305 - /* restore all the CPU state from the CPU context from the  
1306 - signal. The FPU context stays in the host CPU. */  
1307 -  
1308 - env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];  
1309 - env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];  
1310 - env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];  
1311 - env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];  
1312 - env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];  
1313 - env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];  
1314 - env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];  
1315 - env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];  
1316 - eflags = uc->uc_mcontext.gregs[REG_EFL];  
1317 - env->df = 1 - (2 * ((eflags >> 10) & 1));  
1318 - env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);  
1319 - env->cc_op = CC_OP_EFLAGS;  
1320 - return 0;  
1321 -}  
1322 -  
1323 -#endif /* USE_CODE_COPY */