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 */