added minimal segment support
[qemu] / translate-i386.c
1 /*
2  *  i386 translation
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program 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
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <assert.h>
26
27 #define DEBUG_DISAS
28
29 #define IN_OP_I386
30 #include "cpu-i386.h"
31
32 /* dump all code */
33 #ifdef DEBUG_DISAS
34 #include "dis-asm.h"
35 #endif
36
37 #ifndef offsetof
38 #define offsetof(type, field) ((size_t) &((type *)0)->field)
39 #endif
40
41 static uint8_t *gen_code_ptr;
42 int __op_param1, __op_param2, __op_param3;
43
44 extern FILE *logfile;
45 extern int loglevel;
46
47 /* supress that */
48 static void error(const char *fmt, ...)
49 {
50     va_list ap;
51
52     va_start(ap, fmt);
53     fprintf(stderr, "\n");
54     vfprintf(stderr, fmt, ap);
55     fprintf(stderr, "\n");
56     va_end(ap);
57     exit(1);
58 }
59
60 #define PREFIX_REPZ 1
61 #define PREFIX_REPNZ 2
62 #define PREFIX_LOCK 4
63 #define PREFIX_CS 8
64 #define PREFIX_SS 0x10
65 #define PREFIX_DS 0x20
66 #define PREFIX_ES 0x40
67 #define PREFIX_FS 0x80
68 #define PREFIX_GS 0x100
69 #define PREFIX_DATA 0x200
70 #define PREFIX_ADR 0x400
71 #define PREFIX_FWAIT 0x800
72
73 typedef struct DisasContext {
74     /* current insn context */
75     int prefix;
76     int aflag, dflag;
77     uint8_t *pc; /* current pc */
78     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
79                    static state change (stop translation) */
80     /* current block context */
81     int code32; /* 32 bit code segment */
82     int cc_op;  /* current CC operation */
83     int addseg; /* non zero if either DS/ES/SS have a non zero base */
84     int f_st;   /* currently unused */
85 } DisasContext;
86
87 /* i386 arith/logic operations */
88 enum {
89     OP_ADDL, 
90     OP_ORL, 
91     OP_ADCL, 
92     OP_SBBL,
93     OP_ANDL, 
94     OP_SUBL, 
95     OP_XORL, 
96     OP_CMPL,
97 };
98
99 /* i386 shift ops */
100 enum {
101     OP_ROL, 
102     OP_ROR, 
103     OP_RCL, 
104     OP_RCR, 
105     OP_SHL, 
106     OP_SHR, 
107     OP_SHL1, /* undocumented */
108     OP_SAR = 7,
109 };
110
111 #include "op-i386.h"
112
113 /* operand size */
114 enum {
115     OT_BYTE = 0,
116     OT_WORD,
117     OT_LONG, 
118     OT_QUAD,
119 };
120
121 enum {
122     /* I386 int registers */
123     OR_EAX,   /* MUST be even numbered */
124     OR_ECX,
125     OR_EDX,
126     OR_EBX,
127     OR_ESP,
128     OR_EBP,
129     OR_ESI,
130     OR_EDI,
131     OR_TMP0,    /* temporary operand register */
132     OR_TMP1,
133     OR_A0, /* temporary register used when doing address evaluation */
134     OR_ZERO, /* fixed zero register */
135     NB_OREGS,
136 };
137
138 typedef void (GenOpFunc)(void);
139 typedef void (GenOpFunc1)(long);
140 typedef void (GenOpFunc2)(long, long);
141                     
142 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
143     [OT_BYTE] = {
144         gen_op_movb_EAX_T0,
145         gen_op_movb_ECX_T0,
146         gen_op_movb_EDX_T0,
147         gen_op_movb_EBX_T0,
148         gen_op_movh_EAX_T0,
149         gen_op_movh_ECX_T0,
150         gen_op_movh_EDX_T0,
151         gen_op_movh_EBX_T0,
152     },
153     [OT_WORD] = {
154         gen_op_movw_EAX_T0,
155         gen_op_movw_ECX_T0,
156         gen_op_movw_EDX_T0,
157         gen_op_movw_EBX_T0,
158         gen_op_movw_ESP_T0,
159         gen_op_movw_EBP_T0,
160         gen_op_movw_ESI_T0,
161         gen_op_movw_EDI_T0,
162     },
163     [OT_LONG] = {
164         gen_op_movl_EAX_T0,
165         gen_op_movl_ECX_T0,
166         gen_op_movl_EDX_T0,
167         gen_op_movl_EBX_T0,
168         gen_op_movl_ESP_T0,
169         gen_op_movl_EBP_T0,
170         gen_op_movl_ESI_T0,
171         gen_op_movl_EDI_T0,
172     },
173 };
174
175 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
176     [OT_BYTE] = {
177         gen_op_movb_EAX_T1,
178         gen_op_movb_ECX_T1,
179         gen_op_movb_EDX_T1,
180         gen_op_movb_EBX_T1,
181         gen_op_movh_EAX_T1,
182         gen_op_movh_ECX_T1,
183         gen_op_movh_EDX_T1,
184         gen_op_movh_EBX_T1,
185     },
186     [OT_WORD] = {
187         gen_op_movw_EAX_T1,
188         gen_op_movw_ECX_T1,
189         gen_op_movw_EDX_T1,
190         gen_op_movw_EBX_T1,
191         gen_op_movw_ESP_T1,
192         gen_op_movw_EBP_T1,
193         gen_op_movw_ESI_T1,
194         gen_op_movw_EDI_T1,
195     },
196     [OT_LONG] = {
197         gen_op_movl_EAX_T1,
198         gen_op_movl_ECX_T1,
199         gen_op_movl_EDX_T1,
200         gen_op_movl_EBX_T1,
201         gen_op_movl_ESP_T1,
202         gen_op_movl_EBP_T1,
203         gen_op_movl_ESI_T1,
204         gen_op_movl_EDI_T1,
205     },
206 };
207
208 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
209     [0] = {
210         gen_op_movw_EAX_A0,
211         gen_op_movw_ECX_A0,
212         gen_op_movw_EDX_A0,
213         gen_op_movw_EBX_A0,
214         gen_op_movw_ESP_A0,
215         gen_op_movw_EBP_A0,
216         gen_op_movw_ESI_A0,
217         gen_op_movw_EDI_A0,
218     },
219     [1] = {
220         gen_op_movl_EAX_A0,
221         gen_op_movl_ECX_A0,
222         gen_op_movl_EDX_A0,
223         gen_op_movl_EBX_A0,
224         gen_op_movl_ESP_A0,
225         gen_op_movl_EBP_A0,
226         gen_op_movl_ESI_A0,
227         gen_op_movl_EDI_A0,
228     },
229 };
230
231 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = 
232 {
233     [OT_BYTE] = {
234         {
235             gen_op_movl_T0_EAX,
236             gen_op_movl_T0_ECX,
237             gen_op_movl_T0_EDX,
238             gen_op_movl_T0_EBX,
239             gen_op_movh_T0_EAX,
240             gen_op_movh_T0_ECX,
241             gen_op_movh_T0_EDX,
242             gen_op_movh_T0_EBX,
243         },
244         {
245             gen_op_movl_T1_EAX,
246             gen_op_movl_T1_ECX,
247             gen_op_movl_T1_EDX,
248             gen_op_movl_T1_EBX,
249             gen_op_movh_T1_EAX,
250             gen_op_movh_T1_ECX,
251             gen_op_movh_T1_EDX,
252             gen_op_movh_T1_EBX,
253         },
254     },
255     [OT_WORD] = {
256         {
257             gen_op_movl_T0_EAX,
258             gen_op_movl_T0_ECX,
259             gen_op_movl_T0_EDX,
260             gen_op_movl_T0_EBX,
261             gen_op_movl_T0_ESP,
262             gen_op_movl_T0_EBP,
263             gen_op_movl_T0_ESI,
264             gen_op_movl_T0_EDI,
265         },
266         {
267             gen_op_movl_T1_EAX,
268             gen_op_movl_T1_ECX,
269             gen_op_movl_T1_EDX,
270             gen_op_movl_T1_EBX,
271             gen_op_movl_T1_ESP,
272             gen_op_movl_T1_EBP,
273             gen_op_movl_T1_ESI,
274             gen_op_movl_T1_EDI,
275         },
276     },
277     [OT_LONG] = {
278         {
279             gen_op_movl_T0_EAX,
280             gen_op_movl_T0_ECX,
281             gen_op_movl_T0_EDX,
282             gen_op_movl_T0_EBX,
283             gen_op_movl_T0_ESP,
284             gen_op_movl_T0_EBP,
285             gen_op_movl_T0_ESI,
286             gen_op_movl_T0_EDI,
287         },
288         {
289             gen_op_movl_T1_EAX,
290             gen_op_movl_T1_ECX,
291             gen_op_movl_T1_EDX,
292             gen_op_movl_T1_EBX,
293             gen_op_movl_T1_ESP,
294             gen_op_movl_T1_EBP,
295             gen_op_movl_T1_ESI,
296             gen_op_movl_T1_EDI,
297         },
298     },
299 };
300
301 static GenOpFunc *gen_op_movl_A0_reg[8] = {
302     gen_op_movl_A0_EAX,
303     gen_op_movl_A0_ECX,
304     gen_op_movl_A0_EDX,
305     gen_op_movl_A0_EBX,
306     gen_op_movl_A0_ESP,
307     gen_op_movl_A0_EBP,
308     gen_op_movl_A0_ESI,
309     gen_op_movl_A0_EDI,
310 };
311
312 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
313     [0] = {
314         gen_op_addl_A0_EAX,
315         gen_op_addl_A0_ECX,
316         gen_op_addl_A0_EDX,
317         gen_op_addl_A0_EBX,
318         gen_op_addl_A0_ESP,
319         gen_op_addl_A0_EBP,
320         gen_op_addl_A0_ESI,
321         gen_op_addl_A0_EDI,
322     },
323     [1] = {
324         gen_op_addl_A0_EAX_s1,
325         gen_op_addl_A0_ECX_s1,
326         gen_op_addl_A0_EDX_s1,
327         gen_op_addl_A0_EBX_s1,
328         gen_op_addl_A0_ESP_s1,
329         gen_op_addl_A0_EBP_s1,
330         gen_op_addl_A0_ESI_s1,
331         gen_op_addl_A0_EDI_s1,
332     },
333     [2] = {
334         gen_op_addl_A0_EAX_s2,
335         gen_op_addl_A0_ECX_s2,
336         gen_op_addl_A0_EDX_s2,
337         gen_op_addl_A0_EBX_s2,
338         gen_op_addl_A0_ESP_s2,
339         gen_op_addl_A0_EBP_s2,
340         gen_op_addl_A0_ESI_s2,
341         gen_op_addl_A0_EDI_s2,
342     },
343     [3] = {
344         gen_op_addl_A0_EAX_s3,
345         gen_op_addl_A0_ECX_s3,
346         gen_op_addl_A0_EDX_s3,
347         gen_op_addl_A0_EBX_s3,
348         gen_op_addl_A0_ESP_s3,
349         gen_op_addl_A0_EBP_s3,
350         gen_op_addl_A0_ESI_s3,
351         gen_op_addl_A0_EDI_s3,
352     },
353 };
354
355 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
356     gen_op_addl_T0_T1_cc,
357     gen_op_orl_T0_T1_cc,
358     NULL,
359     NULL,
360     gen_op_andl_T0_T1_cc,
361     gen_op_subl_T0_T1_cc,
362     gen_op_xorl_T0_T1_cc,
363     gen_op_cmpl_T0_T1_cc,
364 };
365
366 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
367     [OT_BYTE] = {
368         gen_op_adcb_T0_T1_cc,
369         gen_op_sbbb_T0_T1_cc,
370     },
371     [OT_WORD] = {
372         gen_op_adcw_T0_T1_cc,
373         gen_op_sbbw_T0_T1_cc,
374     },
375     [OT_LONG] = {
376         gen_op_adcl_T0_T1_cc,
377         gen_op_sbbl_T0_T1_cc,
378     },
379 };
380
381 static const int cc_op_arithb[8] = {
382     CC_OP_ADDB,
383     CC_OP_LOGICB,
384     CC_OP_ADDB,
385     CC_OP_SUBB,
386     CC_OP_LOGICB,
387     CC_OP_SUBB,
388     CC_OP_LOGICB,
389     CC_OP_SUBB,
390 };
391
392 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
393     [OT_BYTE] = {
394         gen_op_rolb_T0_T1_cc,
395         gen_op_rorb_T0_T1_cc,
396         gen_op_rclb_T0_T1_cc,
397         gen_op_rcrb_T0_T1_cc,
398         gen_op_shlb_T0_T1_cc,
399         gen_op_shrb_T0_T1_cc,
400         gen_op_shlb_T0_T1_cc,
401         gen_op_sarb_T0_T1_cc,
402     },
403     [OT_WORD] = {
404         gen_op_rolw_T0_T1_cc,
405         gen_op_rorw_T0_T1_cc,
406         gen_op_rclw_T0_T1_cc,
407         gen_op_rcrw_T0_T1_cc,
408         gen_op_shlw_T0_T1_cc,
409         gen_op_shrw_T0_T1_cc,
410         gen_op_shlw_T0_T1_cc,
411         gen_op_sarw_T0_T1_cc,
412     },
413     [OT_LONG] = {
414         gen_op_roll_T0_T1_cc,
415         gen_op_rorl_T0_T1_cc,
416         gen_op_rcll_T0_T1_cc,
417         gen_op_rcrl_T0_T1_cc,
418         gen_op_shll_T0_T1_cc,
419         gen_op_shrl_T0_T1_cc,
420         gen_op_shll_T0_T1_cc,
421         gen_op_sarl_T0_T1_cc,
422     },
423 };
424
425 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
426     [0] = {
427         gen_op_shldw_T0_T1_im_cc,
428         gen_op_shrdw_T0_T1_im_cc,
429     },
430     [1] = {
431         gen_op_shldl_T0_T1_im_cc,
432         gen_op_shrdl_T0_T1_im_cc,
433     },
434 };
435
436 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
437     [0] = {
438         gen_op_shldw_T0_T1_ECX_cc,
439         gen_op_shrdw_T0_T1_ECX_cc,
440     },
441     [1] = {
442         gen_op_shldl_T0_T1_ECX_cc,
443         gen_op_shrdl_T0_T1_ECX_cc,
444     },
445 };
446
447 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
448     [0] = {
449         gen_op_btw_T0_T1_cc,
450         gen_op_btsw_T0_T1_cc,
451         gen_op_btrw_T0_T1_cc,
452         gen_op_btcw_T0_T1_cc,
453     },
454     [1] = {
455         gen_op_btl_T0_T1_cc,
456         gen_op_btsl_T0_T1_cc,
457         gen_op_btrl_T0_T1_cc,
458         gen_op_btcl_T0_T1_cc,
459     },
460 };
461
462 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
463     [0] = {
464         gen_op_bsfw_T0_cc,
465         gen_op_bsrw_T0_cc,
466     },
467     [1] = {
468         gen_op_bsfl_T0_cc,
469         gen_op_bsrl_T0_cc,
470     },
471 };
472
473 static GenOpFunc *gen_op_lds_T0_A0[3] = {
474     gen_op_ldsb_T0_A0,
475     gen_op_ldsw_T0_A0,
476 };
477
478 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
479     gen_op_ldub_T0_A0,
480     gen_op_lduw_T0_A0,
481 };
482
483 /* sign does not matter */
484 static GenOpFunc *gen_op_ld_T0_A0[3] = {
485     gen_op_ldub_T0_A0,
486     gen_op_lduw_T0_A0,
487     gen_op_ldl_T0_A0,
488 };
489
490 static GenOpFunc *gen_op_ld_T1_A0[3] = {
491     gen_op_ldub_T1_A0,
492     gen_op_lduw_T1_A0,
493     gen_op_ldl_T1_A0,
494 };
495
496 static GenOpFunc *gen_op_st_T0_A0[3] = {
497     gen_op_stb_T0_A0,
498     gen_op_stw_T0_A0,
499     gen_op_stl_T0_A0,
500 };
501
502 static GenOpFunc *gen_op_movs[6] = {
503     gen_op_movsb,
504     gen_op_movsw,
505     gen_op_movsl,
506     gen_op_rep_movsb,
507     gen_op_rep_movsw,
508     gen_op_rep_movsl,
509 };
510
511 static GenOpFunc *gen_op_stos[6] = {
512     gen_op_stosb,
513     gen_op_stosw,
514     gen_op_stosl,
515     gen_op_rep_stosb,
516     gen_op_rep_stosw,
517     gen_op_rep_stosl,
518 };
519
520 static GenOpFunc *gen_op_lods[6] = {
521     gen_op_lodsb,
522     gen_op_lodsw,
523     gen_op_lodsl,
524     gen_op_rep_lodsb,
525     gen_op_rep_lodsw,
526     gen_op_rep_lodsl,
527 };
528
529 static GenOpFunc *gen_op_scas[9] = {
530     gen_op_scasb,
531     gen_op_scasw,
532     gen_op_scasl,
533     gen_op_repz_scasb,
534     gen_op_repz_scasw,
535     gen_op_repz_scasl,
536     gen_op_repnz_scasb,
537     gen_op_repnz_scasw,
538     gen_op_repnz_scasl,
539 };
540
541 static GenOpFunc *gen_op_cmps[9] = {
542     gen_op_cmpsb,
543     gen_op_cmpsw,
544     gen_op_cmpsl,
545     gen_op_repz_cmpsb,
546     gen_op_repz_cmpsw,
547     gen_op_repz_cmpsl,
548     gen_op_repnz_cmpsb,
549     gen_op_repnz_cmpsw,
550     gen_op_repnz_cmpsl,
551 };
552
553 static GenOpFunc *gen_op_ins[6] = {
554     gen_op_insb,
555     gen_op_insw,
556     gen_op_insl,
557     gen_op_rep_insb,
558     gen_op_rep_insw,
559     gen_op_rep_insl,
560 };
561
562
563 static GenOpFunc *gen_op_outs[6] = {
564     gen_op_outsb,
565     gen_op_outsw,
566     gen_op_outsl,
567     gen_op_rep_outsb,
568     gen_op_rep_outsw,
569     gen_op_rep_outsl,
570 };
571
572 static GenOpFunc *gen_op_in[3] = {
573     gen_op_inb_T0_T1,
574     gen_op_inw_T0_T1,
575     gen_op_inl_T0_T1,
576 };
577
578 static GenOpFunc *gen_op_out[3] = {
579     gen_op_outb_T0_T1,
580     gen_op_outw_T0_T1,
581     gen_op_outl_T0_T1,
582 };
583
584 enum {
585     JCC_O,
586     JCC_B,
587     JCC_Z,
588     JCC_BE,
589     JCC_S,
590     JCC_P,
591     JCC_L,
592     JCC_LE,
593 };
594
595 static GenOpFunc2 *gen_jcc_slow[8] = {
596     gen_op_jo_cc,
597     gen_op_jb_cc,
598     gen_op_jz_cc,
599     gen_op_jbe_cc,
600     gen_op_js_cc,
601     gen_op_jp_cc,
602     gen_op_jl_cc,
603     gen_op_jle_cc,
604 };
605     
606 static GenOpFunc2 *gen_jcc_sub[3][8] = {
607     [OT_BYTE] = {
608         NULL,
609         gen_op_jb_subb,
610         gen_op_jz_subb,
611         gen_op_jbe_subb,
612         gen_op_js_subb,
613         NULL,
614         gen_op_jl_subb,
615         gen_op_jle_subb,
616     },
617     [OT_WORD] = {
618         NULL,
619         gen_op_jb_subw,
620         gen_op_jz_subw,
621         gen_op_jbe_subw,
622         gen_op_js_subw,
623         NULL,
624         gen_op_jl_subw,
625         gen_op_jle_subw,
626     },
627     [OT_LONG] = {
628         NULL,
629         gen_op_jb_subl,
630         gen_op_jz_subl,
631         gen_op_jbe_subl,
632         gen_op_js_subl,
633         NULL,
634         gen_op_jl_subl,
635         gen_op_jle_subl,
636     },
637 };
638
639 static GenOpFunc *gen_setcc_slow[8] = {
640     gen_op_seto_T0_cc,
641     gen_op_setb_T0_cc,
642     gen_op_setz_T0_cc,
643     gen_op_setbe_T0_cc,
644     gen_op_sets_T0_cc,
645     gen_op_setp_T0_cc,
646     gen_op_setl_T0_cc,
647     gen_op_setle_T0_cc,
648 };
649
650 static GenOpFunc *gen_setcc_sub[3][8] = {
651     [OT_BYTE] = {
652         NULL,
653         gen_op_setb_T0_subb,
654         gen_op_setz_T0_subb,
655         gen_op_setbe_T0_subb,
656         gen_op_sets_T0_subb,
657         NULL,
658         gen_op_setl_T0_subb,
659         gen_op_setle_T0_subb,
660     },
661     [OT_WORD] = {
662         NULL,
663         gen_op_setb_T0_subw,
664         gen_op_setz_T0_subw,
665         gen_op_setbe_T0_subw,
666         gen_op_sets_T0_subw,
667         NULL,
668         gen_op_setl_T0_subw,
669         gen_op_setle_T0_subw,
670     },
671     [OT_LONG] = {
672         NULL,
673         gen_op_setb_T0_subl,
674         gen_op_setz_T0_subl,
675         gen_op_setbe_T0_subl,
676         gen_op_sets_T0_subl,
677         NULL,
678         gen_op_setl_T0_subl,
679         gen_op_setle_T0_subl,
680     },
681 };
682
683 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
684     gen_op_fadd_ST0_FT0,
685     gen_op_fmul_ST0_FT0,
686     gen_op_fcom_ST0_FT0,
687     gen_op_fcom_ST0_FT0,
688     gen_op_fsub_ST0_FT0,
689     gen_op_fsubr_ST0_FT0,
690     gen_op_fdiv_ST0_FT0,
691     gen_op_fdivr_ST0_FT0,
692 };
693
694 /* NOTE the exception in "r" op ordering */
695 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
696     gen_op_fadd_STN_ST0,
697     gen_op_fmul_STN_ST0,
698     NULL,
699     NULL,
700     gen_op_fsubr_STN_ST0,
701     gen_op_fsub_STN_ST0,
702     gen_op_fdivr_STN_ST0,
703     gen_op_fdiv_STN_ST0,
704 };
705
706 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
707 {
708     if (d != OR_TMP0)
709         gen_op_mov_TN_reg[ot][0][d]();
710     if (s != OR_TMP1)
711         gen_op_mov_TN_reg[ot][1][s]();
712     if (op == OP_ADCL || op == OP_SBBL) {
713         if (s1->cc_op != CC_OP_DYNAMIC)
714             gen_op_set_cc_op(s1->cc_op);
715         gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
716         s1->cc_op = CC_OP_DYNAMIC;
717     } else {
718         gen_op_arith_T0_T1_cc[op]();
719         s1->cc_op = cc_op_arithb[op] + ot;
720     }
721     if (d != OR_TMP0 && op != OP_CMPL)
722         gen_op_mov_reg_T0[ot][d]();
723 }
724
725 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
726 {
727     gen_op_movl_T1_im(c);
728     gen_op(s1, op, ot, d, OR_TMP1);
729 }
730
731 static void gen_inc(DisasContext *s1, int ot, int d, int c)
732 {
733     if (d != OR_TMP0)
734         gen_op_mov_TN_reg[ot][0][d]();
735     if (s1->cc_op != CC_OP_DYNAMIC)
736         gen_op_set_cc_op(s1->cc_op);
737     if (c > 0) {
738         gen_op_incl_T0_cc();
739         s1->cc_op = CC_OP_INCB + ot;
740     } else {
741         gen_op_decl_T0_cc();
742         s1->cc_op = CC_OP_DECB + ot;
743     }
744     if (d != OR_TMP0)
745         gen_op_mov_reg_T0[ot][d]();
746 }
747
748 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
749 {
750     if (d != OR_TMP0)
751         gen_op_mov_TN_reg[ot][0][d]();
752     if (s != OR_TMP1)
753         gen_op_mov_TN_reg[ot][1][s]();
754     /* for zero counts, flags are not updated, so must do it dynamically */
755     if (s1->cc_op != CC_OP_DYNAMIC)
756         gen_op_set_cc_op(s1->cc_op);
757
758     gen_op_shift_T0_T1_cc[ot][op]();
759
760     if (d != OR_TMP0)
761         gen_op_mov_reg_T0[ot][d]();
762     s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
763 }
764
765 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
766 {
767     /* currently not optimized */
768     gen_op_movl_T1_im(c);
769     gen_shift(s1, op, ot, d, OR_TMP1);
770 }
771
772 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
773 {
774     int havesib;
775     int base, disp;
776     int index;
777     int scale;
778     int opreg;
779     int mod, rm, code, override, must_add_seg;
780
781     /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
782     /* XXX: fix lea case */
783     override = -1;
784     must_add_seg = s->addseg;
785     if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | 
786                      PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
787         if (s->prefix & PREFIX_ES)
788             override = R_ES;
789         else if (s->prefix & PREFIX_CS)
790             override = R_CS;
791         else if (s->prefix & PREFIX_SS)
792             override = R_SS;
793         else if (s->prefix & PREFIX_DS)
794             override = R_DS;
795         else if (s->prefix & PREFIX_FS)
796             override = R_FS;
797         else
798             override = R_GS;
799         must_add_seg = 1;
800     }
801
802     mod = (modrm >> 6) & 3;
803     rm = modrm & 7;
804
805     if (s->aflag) {
806
807         havesib = 0;
808         base = rm;
809         index = 0;
810         scale = 0;
811         
812         if (base == 4) {
813             havesib = 1;
814             code = ldub(s->pc++);
815             scale = (code >> 6) & 3;
816             index = (code >> 3) & 7;
817             base = code & 7;
818         }
819
820         switch (mod) {
821         case 0:
822             if (base == 5) {
823                 base = -1;
824                 disp = ldl(s->pc);
825                 s->pc += 4;
826             } else {
827                 disp = 0;
828             }
829             break;
830         case 1:
831             disp = (int8_t)ldub(s->pc++);
832             break;
833         default:
834         case 2:
835             disp = ldl(s->pc);
836             s->pc += 4;
837             break;
838         }
839         
840         if (base >= 0) {
841             gen_op_movl_A0_reg[base]();
842             if (disp != 0)
843                 gen_op_addl_A0_im(disp);
844         } else {
845             gen_op_movl_A0_im(disp);
846         }
847         if (havesib && (index != 4 || scale != 0)) {
848             gen_op_addl_A0_reg_sN[scale][index]();
849         }
850         if (must_add_seg) {
851             if (override < 0) {
852                 if (base == R_EBP || base == R_ESP)
853                     override = R_SS;
854                 else
855                     override = R_DS;
856             }
857             gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
858         }
859     } else {
860         switch (mod) {
861         case 0:
862             if (rm == 6) {
863                 disp = lduw(s->pc);
864                 s->pc += 2;
865                 gen_op_movl_A0_im(disp);
866                 rm = 0; /* avoid SS override */
867                 goto no_rm;
868             } else {
869                 disp = 0;
870             }
871             break;
872         case 1:
873             disp = (int8_t)ldub(s->pc++);
874             break;
875         default:
876         case 2:
877             disp = lduw(s->pc);
878             s->pc += 2;
879             break;
880         }
881         switch(rm) {
882         case 0:
883             gen_op_movl_A0_reg[R_EBX]();
884             gen_op_addl_A0_reg_sN[0][R_ESI]();
885             break;
886         case 1:
887             gen_op_movl_A0_reg[R_EBX]();
888             gen_op_addl_A0_reg_sN[0][R_EDI]();
889             break;
890         case 2:
891             gen_op_movl_A0_reg[R_EBP]();
892             gen_op_addl_A0_reg_sN[0][R_ESI]();
893             break;
894         case 3:
895             gen_op_movl_A0_reg[R_EBP]();
896             gen_op_addl_A0_reg_sN[0][R_EDI]();
897             break;
898         case 4:
899             gen_op_movl_A0_reg[R_ESI]();
900             break;
901         case 5:
902             gen_op_movl_A0_reg[R_EDI]();
903             break;
904         case 6:
905             gen_op_movl_A0_reg[R_EBP]();
906             break;
907         default:
908         case 7:
909             gen_op_movl_A0_reg[R_EBX]();
910             break;
911         }
912         if (disp != 0)
913             gen_op_addl_A0_im(disp);
914         gen_op_andl_A0_ffff();
915     no_rm:
916         if (must_add_seg) {
917             if (override < 0) {
918                 if (rm == 2 || rm == 3 || rm == 6)
919                     override = R_SS;
920                 else
921                     override = R_DS;
922             }
923             gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
924         }
925     }
926
927     opreg = OR_A0;
928     disp = 0;
929     *reg_ptr = opreg;
930     *offset_ptr = disp;
931 }
932
933 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
934    OR_TMP0 */
935 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
936 {
937     int mod, rm, opreg, disp;
938
939     mod = (modrm >> 6) & 3;
940     rm = modrm & 7;
941     if (mod == 3) {
942         if (is_store) {
943             if (reg != OR_TMP0)
944                 gen_op_mov_TN_reg[ot][0][reg]();
945             gen_op_mov_reg_T0[ot][rm]();
946         } else {
947             gen_op_mov_TN_reg[ot][0][rm]();
948             if (reg != OR_TMP0)
949                 gen_op_mov_reg_T0[ot][reg]();
950         }
951     } else {
952         gen_lea_modrm(s, modrm, &opreg, &disp);
953         if (is_store) {
954             if (reg != OR_TMP0)
955                 gen_op_mov_TN_reg[ot][0][reg]();
956             gen_op_st_T0_A0[ot]();
957         } else {
958             gen_op_ld_T0_A0[ot]();
959             if (reg != OR_TMP0)
960                 gen_op_mov_reg_T0[ot][reg]();
961         }
962     }
963 }
964
965 static inline uint32_t insn_get(DisasContext *s, int ot)
966 {
967     uint32_t ret;
968
969     switch(ot) {
970     case OT_BYTE:
971         ret = ldub(s->pc);
972         s->pc++;
973         break;
974     case OT_WORD:
975         ret = lduw(s->pc);
976         s->pc += 2;
977         break;
978     default:
979     case OT_LONG:
980         ret = ldl(s->pc);
981         s->pc += 4;
982         break;
983     }
984     return ret;
985 }
986
987 static void gen_jcc(DisasContext *s, int b, int val)
988 {
989     int inv, jcc_op;
990     GenOpFunc2 *func;
991
992     inv = b & 1;
993     jcc_op = (b >> 1) & 7;
994     switch(s->cc_op) {
995         /* we optimize the cmp/jcc case */
996     case CC_OP_SUBB:
997     case CC_OP_SUBW:
998     case CC_OP_SUBL:
999         func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1000         if (!func)
1001             goto slow_jcc;
1002         break;
1003         
1004         /* some jumps are easy to compute */
1005     case CC_OP_ADDB:
1006     case CC_OP_ADDW:
1007     case CC_OP_ADDL:
1008     case CC_OP_ADCB:
1009     case CC_OP_ADCW:
1010     case CC_OP_ADCL:
1011     case CC_OP_SBBB:
1012     case CC_OP_SBBW:
1013     case CC_OP_SBBL:
1014     case CC_OP_LOGICB:
1015     case CC_OP_LOGICW:
1016     case CC_OP_LOGICL:
1017     case CC_OP_INCB:
1018     case CC_OP_INCW:
1019     case CC_OP_INCL:
1020     case CC_OP_DECB:
1021     case CC_OP_DECW:
1022     case CC_OP_DECL:
1023     case CC_OP_SHLB:
1024     case CC_OP_SHLW:
1025     case CC_OP_SHLL:
1026     case CC_OP_SARB:
1027     case CC_OP_SARW:
1028     case CC_OP_SARL:
1029         switch(jcc_op) {
1030         case JCC_Z:
1031             func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1032             break;
1033         case JCC_S:
1034             func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1035             break;
1036         default:
1037             goto slow_jcc;
1038         }
1039         break;
1040     default:
1041     slow_jcc:
1042         if (s->cc_op != CC_OP_DYNAMIC)
1043             gen_op_set_cc_op(s->cc_op);
1044         func = gen_jcc_slow[jcc_op];
1045         break;
1046     }
1047     if (!inv) {
1048         func(val, (long)s->pc);
1049     } else {
1050         func((long)s->pc, val);
1051     }
1052 }
1053
1054 static void gen_setcc(DisasContext *s, int b)
1055 {
1056     int inv, jcc_op;
1057     GenOpFunc *func;
1058
1059     inv = b & 1;
1060     jcc_op = (b >> 1) & 7;
1061     switch(s->cc_op) {
1062         /* we optimize the cmp/jcc case */
1063     case CC_OP_SUBB:
1064     case CC_OP_SUBW:
1065     case CC_OP_SUBL:
1066         func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1067         if (!func)
1068             goto slow_jcc;
1069         break;
1070         
1071         /* some jumps are easy to compute */
1072     case CC_OP_ADDB:
1073     case CC_OP_ADDW:
1074     case CC_OP_ADDL:
1075     case CC_OP_LOGICB:
1076     case CC_OP_LOGICW:
1077     case CC_OP_LOGICL:
1078     case CC_OP_INCB:
1079     case CC_OP_INCW:
1080     case CC_OP_INCL:
1081     case CC_OP_DECB:
1082     case CC_OP_DECW:
1083     case CC_OP_DECL:
1084     case CC_OP_SHLB:
1085     case CC_OP_SHLW:
1086     case CC_OP_SHLL:
1087         switch(jcc_op) {
1088         case JCC_Z:
1089             func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1090             break;
1091         case JCC_S:
1092             func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1093             break;
1094         default:
1095             goto slow_jcc;
1096         }
1097         break;
1098     default:
1099     slow_jcc:
1100         if (s->cc_op != CC_OP_DYNAMIC)
1101             gen_op_set_cc_op(s->cc_op);
1102         func = gen_setcc_slow[jcc_op];
1103         break;
1104     }
1105     func();
1106     if (inv) {
1107         gen_op_xor_T0_1();
1108     }
1109 }
1110
1111 /* move T0 to seg_reg and compute if the CPU state may change */
1112 void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1113 {
1114     gen_op_movl_seg_T0(seg_reg);
1115     if (!s->addseg && seg_reg < R_FS)
1116         s->is_jmp = 2; /* abort translation because the register may
1117                           have a non zero base */
1118 }
1119
1120 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1121    is set to true if the instruction sets the PC (last instruction of
1122    a basic block) */
1123 long disas_insn(DisasContext *s, uint8_t *pc_start)
1124 {
1125     int b, prefixes, aflag, dflag;
1126     int shift, ot;
1127     int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1128
1129     s->pc = pc_start;
1130     prefixes = 0;
1131     aflag = s->code32;
1132     dflag = s->code32;
1133     //    cur_pc = s->pc; /* for insn generation */
1134  next_byte:
1135     b = ldub(s->pc);
1136     s->pc++;
1137     /* check prefixes */
1138     switch (b) {
1139     case 0xf3:
1140         prefixes |= PREFIX_REPZ;
1141         goto next_byte;
1142     case 0xf2:
1143         prefixes |= PREFIX_REPNZ;
1144         goto next_byte;
1145     case 0xf0:
1146         prefixes |= PREFIX_LOCK;
1147         goto next_byte;
1148     case 0x2e:
1149         prefixes |= PREFIX_CS;
1150         goto next_byte;
1151     case 0x36:
1152         prefixes |= PREFIX_SS;
1153         goto next_byte;
1154     case 0x3e:
1155         prefixes |= PREFIX_DS;
1156         goto next_byte;
1157     case 0x26:
1158         prefixes |= PREFIX_ES;
1159         goto next_byte;
1160     case 0x64:
1161         prefixes |= PREFIX_FS;
1162         goto next_byte;
1163     case 0x65:
1164         prefixes |= PREFIX_GS;
1165         goto next_byte;
1166     case 0x66:
1167         prefixes |= PREFIX_DATA;
1168         goto next_byte;
1169     case 0x67:
1170         prefixes |= PREFIX_ADR;
1171         goto next_byte;
1172     case 0x9b:
1173         prefixes |= PREFIX_FWAIT;
1174         goto next_byte;
1175     }
1176
1177     if (prefixes & PREFIX_DATA)
1178         dflag ^= 1;
1179     if (prefixes & PREFIX_ADR)
1180         aflag ^= 1;
1181
1182     s->prefix = prefixes;
1183     s->aflag = aflag;
1184     s->dflag = dflag;
1185
1186     /* now check op code */
1187  reswitch:
1188     switch(b) {
1189     case 0x0f:
1190         /**************************/
1191         /* extended op code */
1192         b = ldub(s->pc++) | 0x100;
1193         goto reswitch;
1194         
1195         /**************************/
1196         /* arith & logic */
1197     case 0x00 ... 0x05:
1198     case 0x08 ... 0x0d:
1199     case 0x10 ... 0x15:
1200     case 0x18 ... 0x1d:
1201     case 0x20 ... 0x25:
1202     case 0x28 ... 0x2d:
1203     case 0x30 ... 0x35:
1204     case 0x38 ... 0x3d:
1205         {
1206             int op, f, val;
1207             op = (b >> 3) & 7;
1208             f = (b >> 1) & 3;
1209
1210             if ((b & 1) == 0)
1211                 ot = OT_BYTE;
1212             else
1213                 ot = dflag ? OT_LONG : OT_WORD;
1214             
1215             switch(f) {
1216             case 0: /* OP Ev, Gv */
1217                 modrm = ldub(s->pc++);
1218                 reg = ((modrm >> 3) & 7) + OR_EAX;
1219                 mod = (modrm >> 6) & 3;
1220                 rm = modrm & 7;
1221                 if (mod != 3) {
1222                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1223                     gen_op_ld_T0_A0[ot]();
1224                     opreg = OR_TMP0;
1225                 } else {
1226                     opreg = OR_EAX + rm;
1227                 }
1228                 gen_op(s, op, ot, opreg, reg);
1229                 if (mod != 3 && op != 7) {
1230                     gen_op_st_T0_A0[ot]();
1231                 }
1232                 break;
1233             case 1: /* OP Gv, Ev */
1234                 modrm = ldub(s->pc++);
1235                 mod = (modrm >> 6) & 3;
1236                 reg = ((modrm >> 3) & 7) + OR_EAX;
1237                 rm = modrm & 7;
1238                 if (mod != 3) {
1239                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1240                     gen_op_ld_T1_A0[ot]();
1241                     opreg = OR_TMP1;
1242                 } else {
1243                     opreg = OR_EAX + rm;
1244                 }
1245                 gen_op(s, op, ot, reg, opreg);
1246                 break;
1247             case 2: /* OP A, Iv */
1248                 val = insn_get(s, ot);
1249                 gen_opi(s, op, ot, OR_EAX, val);
1250                 break;
1251             }
1252         }
1253         break;
1254
1255     case 0x80: /* GRP1 */
1256     case 0x81:
1257     case 0x83:
1258         {
1259             int val;
1260
1261             if ((b & 1) == 0)
1262                 ot = OT_BYTE;
1263             else
1264                 ot = dflag ? OT_LONG : OT_WORD;
1265             
1266             modrm = ldub(s->pc++);
1267             mod = (modrm >> 6) & 3;
1268             rm = modrm & 7;
1269             op = (modrm >> 3) & 7;
1270             
1271             if (mod != 3) {
1272                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1273                 gen_op_ld_T0_A0[ot]();
1274                 opreg = OR_TMP0;
1275             } else {
1276                 opreg = rm + OR_EAX;
1277             }
1278
1279             switch(b) {
1280             default:
1281             case 0x80:
1282             case 0x81:
1283                 val = insn_get(s, ot);
1284                 break;
1285             case 0x83:
1286                 val = (int8_t)insn_get(s, OT_BYTE);
1287                 break;
1288             }
1289
1290             gen_opi(s, op, ot, opreg, val);
1291             if (op != 7 && mod != 3) {
1292                 gen_op_st_T0_A0[ot]();
1293             }
1294         }
1295         break;
1296
1297         /**************************/
1298         /* inc, dec, and other misc arith */
1299     case 0x40 ... 0x47: /* inc Gv */
1300         ot = dflag ? OT_LONG : OT_WORD;
1301         gen_inc(s, ot, OR_EAX + (b & 7), 1);
1302         break;
1303     case 0x48 ... 0x4f: /* dec Gv */
1304         ot = dflag ? OT_LONG : OT_WORD;
1305         gen_inc(s, ot, OR_EAX + (b & 7), -1);
1306         break;
1307     case 0xf6: /* GRP3 */
1308     case 0xf7:
1309         if ((b & 1) == 0)
1310             ot = OT_BYTE;
1311         else
1312             ot = dflag ? OT_LONG : OT_WORD;
1313
1314         modrm = ldub(s->pc++);
1315         mod = (modrm >> 6) & 3;
1316         rm = modrm & 7;
1317         op = (modrm >> 3) & 7;
1318         if (mod != 3) {
1319             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1320             gen_op_ld_T0_A0[ot]();
1321         } else {
1322             gen_op_mov_TN_reg[ot][0][rm]();
1323         }
1324
1325         switch(op) {
1326         case 0: /* test */
1327             val = insn_get(s, ot);
1328             gen_op_movl_T1_im(val);
1329             gen_op_testl_T0_T1_cc();
1330             s->cc_op = CC_OP_LOGICB + ot;
1331             break;
1332         case 2: /* not */
1333             gen_op_notl_T0();
1334             if (mod != 3) {
1335                 gen_op_st_T0_A0[ot]();
1336             } else {
1337                 gen_op_mov_reg_T0[ot][rm]();
1338             }
1339             break;
1340         case 3: /* neg */
1341             gen_op_negl_T0_cc();
1342             if (mod != 3) {
1343                 gen_op_st_T0_A0[ot]();
1344             } else {
1345                 gen_op_mov_reg_T0[ot][rm]();
1346             }
1347             s->cc_op = CC_OP_SUBB + ot;
1348             break;
1349         case 4: /* mul */
1350             switch(ot) {
1351             case OT_BYTE:
1352                 gen_op_mulb_AL_T0();
1353                 break;
1354             case OT_WORD:
1355                 gen_op_mulw_AX_T0();
1356                 break;
1357             default:
1358             case OT_LONG:
1359                 gen_op_mull_EAX_T0();
1360                 break;
1361             }
1362             s->cc_op = CC_OP_MUL;
1363             break;
1364         case 5: /* imul */
1365             switch(ot) {
1366             case OT_BYTE:
1367                 gen_op_imulb_AL_T0();
1368                 break;
1369             case OT_WORD:
1370                 gen_op_imulw_AX_T0();
1371                 break;
1372             default:
1373             case OT_LONG:
1374                 gen_op_imull_EAX_T0();
1375                 break;
1376             }
1377             s->cc_op = CC_OP_MUL;
1378             break;
1379         case 6: /* div */
1380             switch(ot) {
1381             case OT_BYTE:
1382                 gen_op_divb_AL_T0();
1383                 break;
1384             case OT_WORD:
1385                 gen_op_divw_AX_T0();
1386                 break;
1387             default:
1388             case OT_LONG:
1389                 gen_op_divl_EAX_T0();
1390                 break;
1391             }
1392             break;
1393         case 7: /* idiv */
1394             switch(ot) {
1395             case OT_BYTE:
1396                 gen_op_idivb_AL_T0();
1397                 break;
1398             case OT_WORD:
1399                 gen_op_idivw_AX_T0();
1400                 break;
1401             default:
1402             case OT_LONG:
1403                 gen_op_idivl_EAX_T0();
1404                 break;
1405             }
1406             break;
1407         default:
1408             error("GRP3: bad instruction");
1409             return -1;
1410         }
1411         break;
1412
1413     case 0xfe: /* GRP4 */
1414     case 0xff: /* GRP5 */
1415         if ((b & 1) == 0)
1416             ot = OT_BYTE;
1417         else
1418             ot = dflag ? OT_LONG : OT_WORD;
1419
1420         modrm = ldub(s->pc++);
1421         mod = (modrm >> 6) & 3;
1422         rm = modrm & 7;
1423         op = (modrm >> 3) & 7;
1424         if (op >= 2 && b == 0xfe) {
1425             error("GRP4: bad instruction");
1426             return -1;
1427         }
1428         if (mod != 3) {
1429             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1430             gen_op_ld_T0_A0[ot]();
1431         } else {
1432             gen_op_mov_TN_reg[ot][0][rm]();
1433         }
1434
1435         switch(op) {
1436         case 0: /* inc Ev */
1437             gen_inc(s, ot, OR_TMP0, 1);
1438             if (mod != 3)
1439                 gen_op_st_T0_A0[ot]();
1440             else
1441                 gen_op_mov_reg_T0[ot][rm]();
1442             break;
1443         case 1: /* dec Ev */
1444             gen_inc(s, ot, OR_TMP0, -1);
1445             if (mod != 3)
1446                 gen_op_st_T0_A0[ot]();
1447             else
1448                 gen_op_mov_reg_T0[ot][rm]();
1449             break;
1450         case 2: /* call Ev */
1451             gen_op_movl_T1_im((long)s->pc);
1452             gen_op_pushl_T1();
1453             gen_op_jmp_T0();
1454             s->is_jmp = 1;
1455             break;
1456         case 4: /* jmp Ev */
1457             gen_op_jmp_T0();
1458             s->is_jmp = 1;
1459             break;
1460         case 6: /* push Ev */
1461             gen_op_pushl_T0();
1462             break;
1463         default:
1464             error("GRP5: bad instruction");
1465             return -1;
1466         }
1467         break;
1468
1469     case 0x84: /* test Ev, Gv */
1470     case 0x85: 
1471         if ((b & 1) == 0)
1472             ot = OT_BYTE;
1473         else
1474             ot = dflag ? OT_LONG : OT_WORD;
1475
1476         modrm = ldub(s->pc++);
1477         mod = (modrm >> 6) & 3;
1478         rm = modrm & 7;
1479         reg = (modrm >> 3) & 7;
1480         
1481         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1482         gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1483         gen_op_testl_T0_T1_cc();
1484         s->cc_op = CC_OP_LOGICB + ot;
1485         break;
1486         
1487     case 0xa8: /* test eAX, Iv */
1488     case 0xa9:
1489         if ((b & 1) == 0)
1490             ot = OT_BYTE;
1491         else
1492             ot = dflag ? OT_LONG : OT_WORD;
1493         val = insn_get(s, ot);
1494
1495         gen_op_mov_TN_reg[ot][0][OR_EAX]();
1496         gen_op_movl_T1_im(val);
1497         gen_op_testl_T0_T1_cc();
1498         s->cc_op = CC_OP_LOGICB + ot;
1499         break;
1500         
1501     case 0x98: /* CWDE/CBW */
1502         if (dflag)
1503             gen_op_movswl_EAX_AX();
1504         else
1505             gen_op_movsbw_AX_AL();
1506         break;
1507     case 0x99: /* CDQ/CWD */
1508         if (dflag)
1509             gen_op_movslq_EDX_EAX();
1510         else
1511             gen_op_movswl_DX_AX();
1512         break;
1513     case 0x1af: /* imul Gv, Ev */
1514     case 0x69: /* imul Gv, Ev, I */
1515     case 0x6b:
1516         ot = dflag ? OT_LONG : OT_WORD;
1517         modrm = ldub(s->pc++);
1518         reg = ((modrm >> 3) & 7) + OR_EAX;
1519         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1520         if (b == 0x69) {
1521             val = insn_get(s, ot);
1522             gen_op_movl_T1_im(val);
1523         } else if (b == 0x6b) {
1524             val = insn_get(s, OT_BYTE);
1525             gen_op_movl_T1_im(val);
1526         } else {
1527             gen_op_mov_TN_reg[ot][1][reg]();
1528         }
1529
1530         if (ot == OT_LONG) {
1531             gen_op_imull_T0_T1();
1532         } else {
1533             gen_op_imulw_T0_T1();
1534         }
1535         gen_op_mov_reg_T0[ot][reg]();
1536         s->cc_op = CC_OP_MUL;
1537         break;
1538         
1539         /**************************/
1540         /* push/pop */
1541     case 0x50 ... 0x57: /* push */
1542         gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1543         gen_op_pushl_T0();
1544         break;
1545     case 0x58 ... 0x5f: /* pop */
1546         gen_op_popl_T0();
1547         gen_op_mov_reg_T0[OT_LONG][b & 7]();
1548         break;
1549     case 0x60: /* pusha */
1550         if (s->dflag)
1551             gen_op_pushal();
1552         else
1553             gen_op_pushaw();
1554         break;
1555     case 0x61: /* popa */
1556         if (s->dflag)
1557             gen_op_popal();
1558         else
1559             gen_op_popaw();
1560         break;
1561     case 0x68: /* push Iv */
1562     case 0x6a:
1563         ot = dflag ? OT_LONG : OT_WORD;
1564         if (b == 0x68)
1565             val = insn_get(s, ot);
1566         else
1567             val = (int8_t)insn_get(s, OT_BYTE);
1568         gen_op_movl_T0_im(val);
1569         gen_op_pushl_T0();
1570         break;
1571     case 0x8f: /* pop Ev */
1572         ot = dflag ? OT_LONG : OT_WORD;
1573         modrm = ldub(s->pc++);
1574         gen_op_popl_T0();
1575         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1576         break;
1577     case 0xc8: /* enter */
1578         {
1579             int level;
1580             val = lduw(s->pc);
1581             s->pc += 2;
1582             level = ldub(s->pc++);
1583             level &= 0x1f;
1584             gen_op_enterl(val, level);
1585         }
1586         break;
1587     case 0xc9: /* leave */
1588         gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1589         gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1590         gen_op_popl_T0();
1591         gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1592         break;
1593     case 0x06: /* push es */
1594     case 0x0e: /* push cs */
1595     case 0x16: /* push ss */
1596     case 0x1e: /* push ds */
1597         gen_op_movl_T0_seg(b >> 3);
1598         gen_op_pushl_T0();
1599         break;
1600     case 0x1a0: /* push fs */
1601     case 0x1a8: /* push gs */
1602         gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
1603         gen_op_pushl_T0();
1604         break;
1605     case 0x07: /* pop es */
1606     case 0x17: /* pop ss */
1607     case 0x1f: /* pop ds */
1608         gen_op_popl_T0();
1609         gen_movl_seg_T0(s, b >> 3);
1610         break;
1611     case 0x1a1: /* pop fs */
1612     case 0x1a9: /* pop gs */
1613         gen_op_popl_T0();
1614         gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
1615         break;
1616
1617         /**************************/
1618         /* mov */
1619     case 0x88:
1620     case 0x89: /* mov Gv, Ev */
1621         if ((b & 1) == 0)
1622             ot = OT_BYTE;
1623         else
1624             ot = dflag ? OT_LONG : OT_WORD;
1625         modrm = ldub(s->pc++);
1626         reg = (modrm >> 3) & 7;
1627         
1628         /* generate a generic store */
1629         gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1630         break;
1631     case 0xc6:
1632     case 0xc7: /* mov Ev, Iv */
1633         if ((b & 1) == 0)
1634             ot = OT_BYTE;
1635         else
1636             ot = dflag ? OT_LONG : OT_WORD;
1637         modrm = ldub(s->pc++);
1638         mod = (modrm >> 6) & 3;
1639         if (mod != 3)
1640             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1641         val = insn_get(s, ot);
1642         gen_op_movl_T0_im(val);
1643         if (mod != 3)
1644             gen_op_st_T0_A0[ot]();
1645         else
1646             gen_op_mov_reg_T0[ot][modrm & 7]();
1647         break;
1648     case 0x8a:
1649     case 0x8b: /* mov Ev, Gv */
1650         if ((b & 1) == 0)
1651             ot = OT_BYTE;
1652         else
1653             ot = dflag ? OT_LONG : OT_WORD;
1654         modrm = ldub(s->pc++);
1655         reg = (modrm >> 3) & 7;
1656         
1657         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1658         gen_op_mov_reg_T0[ot][reg]();
1659         break;
1660     case 0x8e: /* mov seg, Gv */
1661         ot = dflag ? OT_LONG : OT_WORD;
1662         modrm = ldub(s->pc++);
1663         reg = (modrm >> 3) & 7;
1664         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1665         if (reg >= 6)
1666             goto illegal_op;
1667         gen_movl_seg_T0(s, reg);
1668         break;
1669     case 0x8c: /* mov Gv, seg */
1670         ot = dflag ? OT_LONG : OT_WORD;
1671         modrm = ldub(s->pc++);
1672         reg = (modrm >> 3) & 7;
1673         if (reg >= 6)
1674             goto illegal_op;
1675         gen_op_movl_T0_seg(reg);
1676         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1677         break;
1678
1679     case 0x1b6: /* movzbS Gv, Eb */
1680     case 0x1b7: /* movzwS Gv, Eb */
1681     case 0x1be: /* movsbS Gv, Eb */
1682     case 0x1bf: /* movswS Gv, Eb */
1683         {
1684             int d_ot;
1685             /* d_ot is the size of destination */
1686             d_ot = dflag + OT_WORD;
1687             /* ot is the size of source */
1688             ot = (b & 1) + OT_BYTE;
1689             modrm = ldub(s->pc++);
1690             reg = ((modrm >> 3) & 7) + OR_EAX;
1691             mod = (modrm >> 6) & 3;
1692             rm = modrm & 7;
1693             
1694             if (mod == 3) {
1695                 gen_op_mov_TN_reg[ot][0][rm]();
1696                 switch(ot | (b & 8)) {
1697                 case OT_BYTE:
1698                     gen_op_movzbl_T0_T0();
1699                     break;
1700                 case OT_BYTE | 8:
1701                     gen_op_movsbl_T0_T0();
1702                     break;
1703                 case OT_WORD:
1704                     gen_op_movzwl_T0_T0();
1705                     break;
1706                 default:
1707                 case OT_WORD | 8:
1708                     gen_op_movswl_T0_T0();
1709                     break;
1710                 }
1711                 gen_op_mov_reg_T0[d_ot][reg]();
1712             } else {
1713                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1714                 if (b & 8) {
1715                     gen_op_lds_T0_A0[ot]();
1716                 } else {
1717                     gen_op_ldu_T0_A0[ot]();
1718                 }
1719                 gen_op_mov_reg_T0[d_ot][reg]();
1720             }
1721         }
1722         break;
1723
1724     case 0x8d: /* lea */
1725         ot = dflag ? OT_LONG : OT_WORD;
1726         modrm = ldub(s->pc++);
1727         reg = (modrm >> 3) & 7;
1728         /* we must ensure that no segment is added */
1729         s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS | 
1730                        PREFIX_ES | PREFIX_FS | PREFIX_GS);
1731         val = s->addseg;
1732         s->addseg = 0;
1733         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1734         s->addseg = val;
1735         gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1736         break;
1737         
1738     case 0xa0: /* mov EAX, Ov */
1739     case 0xa1:
1740     case 0xa2: /* mov Ov, EAX */
1741     case 0xa3:
1742         if ((b & 1) == 0)
1743             ot = OT_BYTE;
1744         else
1745             ot = dflag ? OT_LONG : OT_WORD;
1746         if (s->aflag)
1747             offset_addr = insn_get(s, OT_LONG);
1748         else
1749             offset_addr = insn_get(s, OT_WORD);
1750         gen_op_movl_A0_im(offset_addr);
1751         if ((b & 2) == 0) {
1752             gen_op_ld_T0_A0[ot]();
1753             gen_op_mov_reg_T0[ot][R_EAX]();
1754         } else {
1755             gen_op_mov_TN_reg[ot][0][R_EAX]();
1756             gen_op_st_T0_A0[ot]();
1757         }
1758         break;
1759
1760     case 0xb0 ... 0xb7: /* mov R, Ib */
1761         val = insn_get(s, OT_BYTE);
1762         gen_op_movl_T0_im(val);
1763         gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1764         break;
1765     case 0xb8 ... 0xbf: /* mov R, Iv */
1766         ot = dflag ? OT_LONG : OT_WORD;
1767         val = insn_get(s, ot);
1768         reg = OR_EAX + (b & 7);
1769         gen_op_movl_T0_im(val);
1770         gen_op_mov_reg_T0[ot][reg]();
1771         break;
1772
1773     case 0x91 ... 0x97: /* xchg R, EAX */
1774         ot = dflag ? OT_LONG : OT_WORD;
1775         reg = b & 7;
1776         gen_op_mov_TN_reg[ot][0][reg]();
1777         gen_op_mov_TN_reg[ot][1][R_EAX]();
1778         gen_op_mov_reg_T0[ot][R_EAX]();
1779         gen_op_mov_reg_T1[ot][reg]();
1780         break;
1781     case 0x86:
1782     case 0x87: /* xchg Ev, Gv */
1783         if ((b & 1) == 0)
1784             ot = OT_BYTE;
1785         else
1786             ot = dflag ? OT_LONG : OT_WORD;
1787         modrm = ldub(s->pc++);
1788         reg = (modrm >> 3) & 7;
1789
1790         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1791         gen_op_mov_TN_reg[ot][0][reg]();
1792         gen_op_ld_T1_A0[ot]();
1793         gen_op_st_T0_A0[ot]();
1794         gen_op_mov_reg_T1[ot][reg]();
1795         break;
1796     case 0xc4: /* les Gv */
1797         op = R_ES;
1798         goto do_lxx;
1799     case 0xc5: /* lds Gv */
1800         op = R_DS;
1801         goto do_lxx;
1802     case 0x1b2: /* lss Gv */
1803         op = R_SS;
1804         goto do_lxx;
1805     case 0x1b4: /* lfs Gv */
1806         op = R_FS;
1807         goto do_lxx;
1808     case 0x1b5: /* lgs Gv */
1809         op = R_GS;
1810     do_lxx:
1811         ot = dflag ? OT_LONG : OT_WORD;
1812         modrm = ldub(s->pc++);
1813         reg = (modrm >> 3) & 7;
1814         mod = (modrm >> 6) & 3;
1815         if (mod == 3)
1816             goto illegal_op;
1817         gen_op_ld_T1_A0[ot]();
1818         op_addl_A0_im(1 << (ot - OT_WORD + 1));
1819         /* load the segment first to handle exceptions properly */
1820         gen_op_lduw_T0_A0();
1821         gen_movl_seg_T0(s, op);
1822         /* then put the data */
1823         gen_op_mov_reg_T1[ot][reg]();
1824         break;
1825         
1826         /************************/
1827         /* shifts */
1828     case 0xc0:
1829     case 0xc1:
1830         /* shift Ev,Ib */
1831         shift = 2;
1832     grp2:
1833         {
1834             if ((b & 1) == 0)
1835                 ot = OT_BYTE;
1836             else
1837                 ot = dflag ? OT_LONG : OT_WORD;
1838             
1839             modrm = ldub(s->pc++);
1840             mod = (modrm >> 6) & 3;
1841             rm = modrm & 7;
1842             op = (modrm >> 3) & 7;
1843             
1844             if (mod != 3) {
1845                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1846                 gen_op_ld_T0_A0[ot]();
1847                 opreg = OR_TMP0;
1848             } else {
1849                 opreg = rm + OR_EAX;
1850             }
1851
1852             /* simpler op */
1853             if (shift == 0) {
1854                 gen_shift(s, op, ot, opreg, OR_ECX);
1855             } else {
1856                 if (shift == 2) {
1857                     shift = ldub(s->pc++);
1858                 }
1859                 gen_shifti(s, op, ot, opreg, shift);
1860             }
1861
1862             if (mod != 3) {
1863                 gen_op_st_T0_A0[ot]();
1864             }
1865         }
1866         break;
1867     case 0xd0:
1868     case 0xd1:
1869         /* shift Ev,1 */
1870         shift = 1;
1871         goto grp2;
1872     case 0xd2:
1873     case 0xd3:
1874         /* shift Ev,cl */
1875         shift = 0;
1876         goto grp2;
1877
1878     case 0x1a4: /* shld imm */
1879         op = 0;
1880         shift = 1;
1881         goto do_shiftd;
1882     case 0x1a5: /* shld cl */
1883         op = 0;
1884         shift = 0;
1885         goto do_shiftd;
1886     case 0x1ac: /* shrd imm */
1887         op = 1;
1888         shift = 1;
1889         goto do_shiftd;
1890     case 0x1ad: /* shrd cl */
1891         op = 1;
1892         shift = 0;
1893     do_shiftd:
1894         ot = dflag ? OT_LONG : OT_WORD;
1895         modrm = ldub(s->pc++);
1896         mod = (modrm >> 6) & 3;
1897         rm = modrm & 7;
1898         reg = (modrm >> 3) & 7;
1899         
1900         if (mod != 3) {
1901             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1902             gen_op_ld_T0_A0[ot]();
1903         } else {
1904             gen_op_mov_TN_reg[ot][0][rm]();
1905         }
1906         gen_op_mov_TN_reg[ot][1][reg]();
1907         
1908         if (shift) {
1909             val = ldub(s->pc++);
1910             val &= 0x1f;
1911             if (val) {
1912                 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1913                 if (op == 0 && ot != OT_WORD)
1914                     s->cc_op = CC_OP_SHLB + ot;
1915                 else
1916                     s->cc_op = CC_OP_SARB + ot;
1917             }
1918         } else {
1919             if (s->cc_op != CC_OP_DYNAMIC)
1920                 gen_op_set_cc_op(s->cc_op);
1921             gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1922             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1923         }
1924         if (mod != 3) {
1925             gen_op_st_T0_A0[ot]();
1926         } else {
1927             gen_op_mov_reg_T0[ot][rm]();
1928         }
1929         break;
1930
1931         /************************/
1932         /* floats */
1933     case 0xd8 ... 0xdf: 
1934         modrm = ldub(s->pc++);
1935         mod = (modrm >> 6) & 3;
1936         rm = modrm & 7;
1937         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1938         
1939         if (mod != 3) {
1940             /* memory op */
1941             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1942             switch(op) {
1943             case 0x00 ... 0x07: /* fxxxs */
1944             case 0x10 ... 0x17: /* fixxxl */
1945             case 0x20 ... 0x27: /* fxxxl */
1946             case 0x30 ... 0x37: /* fixxx */
1947                 {
1948                     int op1;
1949                     op1 = op & 7;
1950
1951                     switch(op >> 4) {
1952                     case 0:
1953                         gen_op_flds_FT0_A0();
1954                         break;
1955                     case 1:
1956                         gen_op_fildl_FT0_A0();
1957                         break;
1958                     case 2:
1959                         gen_op_fldl_FT0_A0();
1960                         break;
1961                     case 3:
1962                     default:
1963                         gen_op_fild_FT0_A0();
1964                         break;
1965                     }
1966                     
1967                     gen_op_fp_arith_ST0_FT0[op1]();
1968                     if (op1 == 3) {
1969                         /* fcomp needs pop */
1970                         gen_op_fpop();
1971                     }
1972                 }
1973                 break;
1974             case 0x08: /* flds */
1975             case 0x0a: /* fsts */
1976             case 0x0b: /* fstps */
1977             case 0x18: /* fildl */
1978             case 0x1a: /* fistl */
1979             case 0x1b: /* fistpl */
1980             case 0x28: /* fldl */
1981             case 0x2a: /* fstl */
1982             case 0x2b: /* fstpl */
1983             case 0x38: /* filds */
1984             case 0x3a: /* fists */
1985             case 0x3b: /* fistps */
1986                 
1987                 switch(op & 7) {
1988                 case 0:
1989                     gen_op_fpush();
1990                     switch(op >> 4) {
1991                     case 0:
1992                         gen_op_flds_ST0_A0();
1993                         break;
1994                     case 1:
1995                         gen_op_fildl_ST0_A0();
1996                         break;
1997                     case 2:
1998                         gen_op_fldl_ST0_A0();
1999                         break;
2000                     case 3:
2001                     default:
2002                         gen_op_fild_ST0_A0();
2003                         break;
2004                     }
2005                     break;
2006                 default:
2007                     switch(op >> 4) {
2008                     case 0:
2009                         gen_op_fsts_ST0_A0();
2010                         break;
2011                     case 1:
2012                         gen_op_fistl_ST0_A0();
2013                         break;
2014                     case 2:
2015                         gen_op_fstl_ST0_A0();
2016                         break;
2017                     case 3:
2018                     default:
2019                         gen_op_fist_ST0_A0();
2020                         break;
2021                     }
2022                     if ((op & 7) == 3)
2023                         gen_op_fpop();
2024                     break;
2025                 }
2026                 break;
2027             case 0x0d: /* fldcw mem */
2028                 gen_op_fldcw_A0();
2029                 break;
2030             case 0x0f: /* fnstcw mem */
2031                 gen_op_fnstcw_A0();
2032                 break;
2033             case 0x1d: /* fldt mem */
2034                 gen_op_fpush();
2035                 gen_op_fldt_ST0_A0();
2036                 break;
2037             case 0x1f: /* fstpt mem */
2038                 gen_op_fstt_ST0_A0();
2039                 gen_op_fpop();
2040                 break;
2041             case 0x2f: /* fnstsw mem */
2042                 gen_op_fnstsw_A0();
2043                 break;
2044             case 0x3c: /* fbld */
2045                 gen_op_fpush();
2046                 gen_op_fbld_ST0_A0();
2047                 break;
2048             case 0x3e: /* fbstp */
2049                 gen_op_fbst_ST0_A0();
2050                 gen_op_fpop();
2051                 break;
2052             case 0x3d: /* fildll */
2053                 gen_op_fpush();
2054                 gen_op_fildll_ST0_A0();
2055                 break;
2056             case 0x3f: /* fistpll */
2057                 gen_op_fistll_ST0_A0();
2058                 gen_op_fpop();
2059                 break;
2060             default:
2061                 error("unhandled FPm [op=0x%02x]\n", op);
2062                 return -1;
2063             }
2064         } else {
2065             /* register float ops */
2066             opreg = rm;
2067
2068             switch(op) {
2069             case 0x08: /* fld sti */
2070                 gen_op_fpush();
2071                 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2072                 break;
2073             case 0x09: /* fxchg sti */
2074                 gen_op_fxchg_ST0_STN(opreg);
2075                 break;
2076             case 0x0a: /* grp d9/2 */
2077                 switch(rm) {
2078                 case 0: /* fnop */
2079                     break;
2080                 default:
2081                     error("unhandled FP GRP d9/2\n");
2082                     return -1;
2083                 }
2084                 break;
2085             case 0x0c: /* grp d9/4 */
2086                 switch(rm) {
2087                 case 0: /* fchs */
2088                     gen_op_fchs_ST0();
2089                     break;
2090                 case 1: /* fabs */
2091                     gen_op_fabs_ST0();
2092                     break;
2093                 case 4: /* ftst */
2094                     gen_op_fldz_FT0();
2095                     gen_op_fcom_ST0_FT0();
2096                     break;
2097                 case 5: /* fxam */
2098                     gen_op_fxam_ST0();
2099                     break;
2100                 default:
2101                     return -1;
2102                 }
2103                 break;
2104             case 0x0d: /* grp d9/5 */
2105                 {
2106                     switch(rm) {
2107                     case 0:
2108                         gen_op_fpush();
2109                         gen_op_fld1_ST0();
2110                         break;
2111                     case 1:
2112                         gen_op_fpush();
2113                         gen_op_fldl2t_ST0();
2114                         break;
2115                     case 2:
2116                         gen_op_fpush();
2117                         gen_op_fldl2e_ST0();
2118                         break;
2119                     case 3:
2120                         gen_op_fpush();
2121                         gen_op_fldpi_ST0();
2122                         break;
2123                     case 4:
2124                         gen_op_fpush();
2125                         gen_op_fldlg2_ST0();
2126                         break;
2127                     case 5:
2128                         gen_op_fpush();
2129                         gen_op_fldln2_ST0();
2130                         break;
2131                     case 6:
2132                         gen_op_fpush();
2133                         gen_op_fldz_ST0();
2134                         break;
2135                     default:
2136                         return -1;
2137                     }
2138                 }
2139                 break;
2140             case 0x0e: /* grp d9/6 */
2141                 switch(rm) {
2142                 case 0: /* f2xm1 */
2143                     gen_op_f2xm1();
2144                     break;
2145                 case 1: /* fyl2x */
2146                     gen_op_fyl2x();
2147                     break;
2148                 case 2: /* fptan */
2149                     gen_op_fptan();
2150                     break;
2151                 case 3: /* fpatan */
2152                     gen_op_fpatan();
2153                     break;
2154                 case 4: /* fxtract */
2155                     gen_op_fxtract();
2156                     break;
2157                 case 5: /* fprem1 */
2158                     gen_op_fprem1();
2159                     break;
2160                 case 6: /* fdecstp */
2161                     gen_op_fdecstp();
2162                     break;
2163                 default:
2164                 case 7: /* fincstp */
2165                     gen_op_fincstp();
2166                     break;
2167                 }
2168                 break;
2169             case 0x0f: /* grp d9/7 */
2170                 switch(rm) {
2171                 case 0: /* fprem */
2172                     gen_op_fprem();
2173                     break;
2174                 case 1: /* fyl2xp1 */
2175                     gen_op_fyl2xp1();
2176                     break;
2177                 case 2: /* fsqrt */
2178                     gen_op_fsqrt();
2179                     break;
2180                 case 3: /* fsincos */
2181                     gen_op_fsincos();
2182                     break;
2183                 case 5: /* fscale */
2184                     gen_op_fscale();
2185                     break;
2186                 case 4: /* frndint */
2187                     gen_op_frndint();
2188                     break;
2189                 case 6: /* fsin */
2190                     gen_op_fsin();
2191                     break;
2192                 default:
2193                 case 7: /* fcos */
2194                     gen_op_fcos();
2195                     break;
2196                 }
2197                 break;
2198             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2199             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2200             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2201                 {
2202                     int op1;
2203                     
2204                     op1 = op & 7;
2205                     if (op >= 0x20) {
2206                         gen_op_fp_arith_STN_ST0[op1](opreg);
2207                         if (op >= 0x30)
2208                             gen_op_fpop();
2209                     } else {
2210                         gen_op_fmov_FT0_STN(opreg);
2211                         gen_op_fp_arith_ST0_FT0[op1]();
2212                     }
2213                 }
2214                 break;
2215             case 0x02: /* fcom */
2216                 gen_op_fmov_FT0_STN(opreg);
2217                 gen_op_fcom_ST0_FT0();
2218                 break;
2219             case 0x03: /* fcomp */
2220                 gen_op_fmov_FT0_STN(opreg);
2221                 gen_op_fcom_ST0_FT0();
2222                 gen_op_fpop();
2223                 break;
2224             case 0x15: /* da/5 */
2225                 switch(rm) {
2226                 case 1: /* fucompp */
2227                     gen_op_fmov_FT0_STN(1);
2228                     gen_op_fucom_ST0_FT0();
2229                     gen_op_fpop();
2230                     gen_op_fpop();
2231                     break;
2232                 default:
2233                     return -1;
2234                 }
2235                 break;
2236             case 0x2a: /* fst sti */
2237                 gen_op_fmov_STN_ST0(opreg);
2238                 break;
2239             case 0x2b: /* fstp sti */
2240                 gen_op_fmov_STN_ST0(opreg);
2241                 gen_op_fpop();
2242                 break;
2243             case 0x2c: /* fucom st(i) */
2244                 gen_op_fmov_FT0_STN(opreg);
2245                 gen_op_fucom_ST0_FT0();
2246                 break;
2247             case 0x2d: /* fucomp st(i) */
2248                 gen_op_fmov_FT0_STN(opreg);
2249                 gen_op_fucom_ST0_FT0();
2250                 gen_op_fpop();
2251                 break;
2252             case 0x33: /* de/3 */
2253                 switch(rm) {
2254                 case 1: /* fcompp */
2255                     gen_op_fmov_FT0_STN(1);
2256                     gen_op_fcom_ST0_FT0();
2257                     gen_op_fpop();
2258                     gen_op_fpop();
2259                     break;
2260                 default:
2261                     return -1;
2262                 }
2263                 break;
2264             case 0x3c: /* df/4 */
2265                 switch(rm) {
2266                 case 0:
2267                     gen_op_fnstsw_EAX();
2268                     break;
2269                 default:
2270                     error("unhandled FP %x df/4\n", rm);
2271                     return -1;
2272                 }
2273                 break;
2274             default:
2275                 error("unhandled FPr [op=0x%x]\n", op);
2276                 return -1;
2277             }
2278         }
2279         break;
2280         /************************/
2281         /* string ops */
2282     case 0xa4: /* movsS */
2283     case 0xa5:
2284         if ((b & 1) == 0)
2285             ot = OT_BYTE;
2286         else
2287             ot = dflag ? OT_LONG : OT_WORD;
2288         if (prefixes & PREFIX_REPZ) {
2289             gen_op_movs[3 + ot]();
2290         } else {
2291             gen_op_movs[ot]();
2292         }
2293         break;
2294         
2295     case 0xaa: /* stosS */
2296     case 0xab:
2297         if ((b & 1) == 0)
2298             ot = OT_BYTE;
2299         else
2300             ot = dflag ? OT_LONG : OT_WORD;
2301         if (prefixes & PREFIX_REPZ) {
2302             gen_op_stos[3 + ot]();
2303         } else {
2304             gen_op_stos[ot]();
2305         }
2306         break;
2307     case 0xac: /* lodsS */
2308     case 0xad:
2309         if ((b & 1) == 0)
2310             ot = OT_BYTE;
2311         else
2312             ot = dflag ? OT_LONG : OT_WORD;
2313         if (prefixes & PREFIX_REPZ) {
2314             gen_op_lods[3 + ot]();
2315         } else {
2316             gen_op_lods[ot]();
2317         }
2318         break;
2319     case 0xae: /* scasS */
2320     case 0xaf:
2321         if ((b & 1) == 0)
2322             ot = OT_BYTE;
2323         else
2324             ot = dflag ? OT_LONG : OT_WORD;
2325         if (prefixes & PREFIX_REPNZ) {
2326             if (s->cc_op != CC_OP_DYNAMIC)
2327                 gen_op_set_cc_op(s->cc_op);
2328             gen_op_scas[6 + ot]();
2329             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2330         } else if (prefixes & PREFIX_REPZ) {
2331             if (s->cc_op != CC_OP_DYNAMIC)
2332                 gen_op_set_cc_op(s->cc_op);
2333             gen_op_scas[3 + ot]();
2334             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2335         } else {
2336             gen_op_scas[ot]();
2337             s->cc_op = CC_OP_SUBB + ot;
2338         }
2339         break;
2340
2341     case 0xa6: /* cmpsS */
2342     case 0xa7:
2343         if ((b & 1) == 0)
2344             ot = OT_BYTE;
2345         else
2346             ot = dflag ? OT_LONG : OT_WORD;
2347         if (prefixes & PREFIX_REPNZ) {
2348             if (s->cc_op != CC_OP_DYNAMIC)
2349                 gen_op_set_cc_op(s->cc_op);
2350             gen_op_cmps[6 + ot]();
2351             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2352         } else if (prefixes & PREFIX_REPZ) {
2353             if (s->cc_op != CC_OP_DYNAMIC)
2354                 gen_op_set_cc_op(s->cc_op);
2355             gen_op_cmps[3 + ot]();
2356             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2357         } else {
2358             gen_op_cmps[ot]();
2359             s->cc_op = CC_OP_SUBB + ot;
2360         }
2361         break;
2362         
2363         /************************/
2364         /* port I/O */
2365     case 0x6c: /* insS */
2366     case 0x6d:
2367         if ((b & 1) == 0)
2368             ot = OT_BYTE;
2369         else
2370             ot = dflag ? OT_LONG : OT_WORD;
2371         if (prefixes & PREFIX_REPZ) {
2372             gen_op_ins[3 + ot]();
2373         } else {
2374             gen_op_ins[ot]();
2375         }
2376         break;
2377     case 0x6e: /* outsS */
2378     case 0x6f:
2379         if ((b & 1) == 0)
2380             ot = OT_BYTE;
2381         else
2382             ot = dflag ? OT_LONG : OT_WORD;
2383         if (prefixes & PREFIX_REPZ) {
2384             gen_op_outs[3 + ot]();
2385         } else {
2386             gen_op_outs[ot]();
2387         }
2388         break;
2389     case 0xe4:
2390     case 0xe5:
2391         if ((b & 1) == 0)
2392             ot = OT_BYTE;
2393         else
2394             ot = dflag ? OT_LONG : OT_WORD;
2395         val = ldub(s->pc++);
2396         gen_op_movl_T0_im(val);
2397         gen_op_in[ot]();
2398         gen_op_mov_reg_T1[ot][R_EAX]();
2399         break;
2400     case 0xe6:
2401     case 0xe7:
2402         if ((b & 1) == 0)
2403             ot = OT_BYTE;
2404         else
2405             ot = dflag ? OT_LONG : OT_WORD;
2406         val = ldub(s->pc++);
2407         gen_op_movl_T0_im(val);
2408         gen_op_mov_TN_reg[ot][1][R_EAX]();
2409         gen_op_out[ot]();
2410         break;
2411     case 0xec:
2412     case 0xed:
2413         if ((b & 1) == 0)
2414             ot = OT_BYTE;
2415         else
2416             ot = dflag ? OT_LONG : OT_WORD;
2417         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2418         gen_op_in[ot]();
2419         gen_op_mov_reg_T1[ot][R_EAX]();
2420         break;
2421     case 0xee:
2422     case 0xef:
2423         if ((b & 1) == 0)
2424             ot = OT_BYTE;
2425         else
2426             ot = dflag ? OT_LONG : OT_WORD;
2427         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2428         gen_op_mov_TN_reg[ot][1][R_EAX]();
2429         gen_op_out[ot]();
2430         break;
2431
2432         /************************/
2433         /* control */
2434     case 0xc2: /* ret im */
2435         /* XXX: handle stack pop ? */
2436         val = ldsw(s->pc);
2437         s->pc += 2;
2438         gen_op_popl_T0();
2439         gen_op_addl_ESP_im(val);
2440         gen_op_jmp_T0();
2441         s->is_jmp = 1;
2442         break;
2443     case 0xc3: /* ret */
2444         gen_op_popl_T0();
2445         gen_op_jmp_T0();
2446         s->is_jmp = 1;
2447         break;
2448     case 0xe8: /* call */
2449         val = insn_get(s, OT_LONG);
2450         val += (long)s->pc;
2451         gen_op_movl_T1_im((long)s->pc);
2452         gen_op_pushl_T1();
2453         gen_op_jmp_im(val);
2454         s->is_jmp = 1;
2455         break;
2456     case 0xe9: /* jmp */
2457         val = insn_get(s, OT_LONG);
2458         val += (long)s->pc;
2459         gen_op_jmp_im(val);
2460         s->is_jmp = 1;
2461         break;
2462     case 0xeb: /* jmp Jb */
2463         val = (int8_t)insn_get(s, OT_BYTE);
2464         val += (long)s->pc;
2465         gen_op_jmp_im(val);
2466         s->is_jmp = 1;
2467         break;
2468     case 0x70 ... 0x7f: /* jcc Jb */
2469         val = (int8_t)insn_get(s, OT_BYTE);
2470         val += (long)s->pc;
2471         goto do_jcc;
2472     case 0x180 ... 0x18f: /* jcc Jv */
2473         if (dflag) {
2474             val = insn_get(s, OT_LONG);
2475         } else {
2476             val = (int16_t)insn_get(s, OT_WORD); 
2477         }
2478         val += (long)s->pc; /* XXX: fix 16 bit wrap */
2479     do_jcc:
2480         gen_jcc(s, b, val);
2481         s->is_jmp = 1;
2482         break;
2483
2484     case 0x190 ... 0x19f:
2485         modrm = ldub(s->pc++);
2486         gen_setcc(s, b);
2487         gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2488         break;
2489
2490         /************************/
2491         /* flags */
2492     case 0x9c: /* pushf */
2493         if (s->cc_op != CC_OP_DYNAMIC)
2494             gen_op_set_cc_op(s->cc_op);
2495         gen_op_movl_T0_eflags();
2496         gen_op_pushl_T0();
2497         break;
2498     case 0x9d: /* popf */
2499         gen_op_popl_T0();
2500         gen_op_movl_eflags_T0();
2501         s->cc_op = CC_OP_EFLAGS;
2502         break;
2503     case 0x9e: /* sahf */
2504         gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2505         if (s->cc_op != CC_OP_DYNAMIC)
2506             gen_op_set_cc_op(s->cc_op);
2507         gen_op_movb_eflags_T0();
2508         s->cc_op = CC_OP_EFLAGS;
2509         break;
2510     case 0x9f: /* lahf */
2511         if (s->cc_op != CC_OP_DYNAMIC)
2512             gen_op_set_cc_op(s->cc_op);
2513         gen_op_movl_T0_eflags();
2514         gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2515         break;
2516     case 0xf5: /* cmc */
2517         if (s->cc_op != CC_OP_DYNAMIC)
2518             gen_op_set_cc_op(s->cc_op);
2519         gen_op_cmc();
2520         s->cc_op = CC_OP_EFLAGS;
2521         break;
2522     case 0xf8: /* clc */
2523         if (s->cc_op != CC_OP_DYNAMIC)
2524             gen_op_set_cc_op(s->cc_op);
2525         gen_op_clc();
2526         s->cc_op = CC_OP_EFLAGS;
2527         break;
2528     case 0xf9: /* stc */
2529         if (s->cc_op != CC_OP_DYNAMIC)
2530             gen_op_set_cc_op(s->cc_op);
2531         gen_op_stc();
2532         s->cc_op = CC_OP_EFLAGS;
2533         break;
2534     case 0xfc: /* cld */
2535         gen_op_cld();
2536         break;
2537     case 0xfd: /* std */
2538         gen_op_std();
2539         break;
2540
2541         /************************/
2542         /* bit operations */
2543     case 0x1ba: /* bt/bts/btr/btc Gv, im */
2544         ot = dflag ? OT_LONG : OT_WORD;
2545         modrm = ldub(s->pc++);
2546         op = (modrm >> 3) & 7;
2547         mod = (modrm >> 6) & 3;
2548         rm = modrm & 7;
2549         if (mod != 3) {
2550             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2551             gen_op_ld_T0_A0[ot]();
2552         } else {
2553             gen_op_mov_TN_reg[ot][0][rm]();
2554         }
2555         /* load shift */
2556         val = ldub(s->pc++);
2557         gen_op_movl_T1_im(val);
2558         if (op < 4)
2559             return -1;
2560         op -= 4;
2561         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2562         s->cc_op = CC_OP_SARB + ot;
2563         if (op != 0) {
2564             if (mod != 3)
2565                 gen_op_st_T0_A0[ot]();
2566             else
2567                 gen_op_mov_reg_T0[ot][rm]();
2568         }
2569         break;
2570     case 0x1a3: /* bt Gv, Ev */
2571         op = 0;
2572         goto do_btx;
2573     case 0x1ab: /* bts */
2574         op = 1;
2575         goto do_btx;
2576     case 0x1b3: /* btr */
2577         op = 2;
2578         goto do_btx;
2579     case 0x1bb: /* btc */
2580         op = 3;
2581     do_btx:
2582         ot = dflag ? OT_LONG : OT_WORD;
2583         modrm = ldub(s->pc++);
2584         reg = (modrm >> 3) & 7;
2585         mod = (modrm >> 6) & 3;
2586         rm = modrm & 7;
2587         gen_op_mov_TN_reg[OT_LONG][1][reg]();
2588         if (mod != 3) {
2589             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2590             /* specific case: we need to add a displacement */
2591             if (ot == OT_WORD)
2592                 gen_op_add_bitw_A0_T1();
2593             else
2594                 gen_op_add_bitl_A0_T1();
2595             gen_op_ld_T0_A0[ot]();
2596         } else {
2597             gen_op_mov_TN_reg[ot][0][rm]();
2598         }
2599         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2600         s->cc_op = CC_OP_SARB + ot;
2601         if (op != 0) {
2602             if (mod != 3)
2603                 gen_op_st_T0_A0[ot]();
2604             else
2605                 gen_op_mov_reg_T0[ot][rm]();
2606         }
2607         break;
2608     case 0x1bc: /* bsf */
2609     case 0x1bd: /* bsr */
2610         ot = dflag ? OT_LONG : OT_WORD;
2611         modrm = ldub(s->pc++);
2612         reg = (modrm >> 3) & 7;
2613         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2614         gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2615         /* NOTE: we always write back the result. Intel doc says it is
2616            undefined if T0 == 0 */
2617         gen_op_mov_reg_T0[ot][reg]();
2618         s->cc_op = CC_OP_LOGICB + ot;
2619         break;
2620         /************************/
2621         /* bcd */
2622     case 0x27: /* daa */
2623         if (s->cc_op != CC_OP_DYNAMIC)
2624             gen_op_set_cc_op(s->cc_op);
2625         gen_op_daa();
2626         s->cc_op = CC_OP_EFLAGS;
2627         break;
2628     case 0x2f: /* das */
2629         if (s->cc_op != CC_OP_DYNAMIC)
2630             gen_op_set_cc_op(s->cc_op);
2631         gen_op_das();
2632         s->cc_op = CC_OP_EFLAGS;
2633         break;
2634     case 0x37: /* aaa */
2635         if (s->cc_op != CC_OP_DYNAMIC)
2636             gen_op_set_cc_op(s->cc_op);
2637         gen_op_aaa();
2638         s->cc_op = CC_OP_EFLAGS;
2639         break;
2640     case 0x3f: /* aas */
2641         if (s->cc_op != CC_OP_DYNAMIC)
2642             gen_op_set_cc_op(s->cc_op);
2643         gen_op_aas();
2644         s->cc_op = CC_OP_EFLAGS;
2645         break;
2646     case 0xd4: /* aam */
2647         val = ldub(s->pc++);
2648         gen_op_aam(val);
2649         s->cc_op = CC_OP_LOGICB;
2650         break;
2651     case 0xd5: /* aad */
2652         val = ldub(s->pc++);
2653         gen_op_aad(val);
2654         s->cc_op = CC_OP_LOGICB;
2655         break;
2656         /************************/
2657         /* misc */
2658     case 0x90: /* nop */
2659         break;
2660     case 0xcc: /* int3 */
2661         gen_op_int3((long)pc_start);
2662         s->is_jmp = 1;
2663         break;
2664     case 0xcd: /* int N */
2665         val = ldub(s->pc++);
2666         /* XXX: currently we ignore the interrupt number */
2667         gen_op_int_im((long)pc_start);
2668         s->is_jmp = 1;
2669         break;
2670     case 0xce: /* into */
2671         if (s->cc_op != CC_OP_DYNAMIC)
2672             gen_op_set_cc_op(s->cc_op);
2673         gen_op_into((long)pc_start, (long)s->pc);
2674         s->is_jmp = 1;
2675         break;
2676     case 0x1c8 ... 0x1cf: /* bswap reg */
2677         reg = b & 7;
2678         gen_op_mov_TN_reg[OT_LONG][0][reg]();
2679         gen_op_bswapl_T0();
2680         gen_op_mov_reg_T0[OT_LONG][reg]();
2681         break;
2682     case 0xd6: /* salc */
2683         if (s->cc_op != CC_OP_DYNAMIC)
2684             gen_op_set_cc_op(s->cc_op);
2685         gen_op_salc();
2686         break;
2687     case 0x1a2: /* rdtsc */
2688         gen_op_rdtsc();
2689         break;
2690 #if 0
2691     case 0x1a2: /* cpuid */
2692         gen_insn0(OP_ASM);
2693         break;
2694 #endif
2695     default:
2696         error("unknown opcode 0x%x", b);
2697         return -1;
2698     }
2699     return (long)s->pc;
2700  illegal_op:
2701     error("illegal opcode pc=0x%08Lx", (long)pc_start);
2702     return -1;
2703 }
2704
2705 /* return the next pc */
2706 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
2707                      int *gen_code_size_ptr, uint8_t *pc_start, 
2708                      int flags)
2709 {
2710     DisasContext dc1, *dc = &dc1;
2711     uint8_t *gen_code_end, *pc_ptr;
2712     long ret;
2713 #ifdef DEBUG_DISAS
2714     struct disassemble_info disasm_info;
2715 #endif
2716     dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
2717     dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
2718     dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
2719     dc->cc_op = CC_OP_DYNAMIC;
2720     gen_code_ptr = gen_code_buf;
2721     gen_code_end = gen_code_buf + max_code_size - 4096;
2722     gen_start();
2723
2724     dc->is_jmp = 0;
2725     pc_ptr = pc_start;
2726     do {
2727         ret = disas_insn(dc, pc_ptr);
2728         if (ret == -1) 
2729             error("unknown instruction at PC=0x%x B=%02x %02x", 
2730                   pc_ptr, pc_ptr[0], pc_ptr[1]);
2731         pc_ptr = (void *)ret;
2732     } while (!dc->is_jmp && gen_code_ptr < gen_code_end);
2733     /* we must store the eflags state if it is not already done */
2734     if (dc->cc_op != CC_OP_DYNAMIC)
2735         gen_op_set_cc_op(dc->cc_op);
2736     if (dc->is_jmp != 1) {
2737         /* we add an additionnal jmp to update the simulated PC */
2738         gen_op_jmp_im(ret);
2739     }
2740     gen_end();
2741     *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2742
2743 #ifdef DEBUG_DISAS
2744     if (loglevel) {
2745         uint8_t *pc;
2746         int count;
2747
2748         INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2749 #if 0        
2750         disasm_info.flavour = bfd_get_flavour (abfd);
2751         disasm_info.arch = bfd_get_arch (abfd);
2752         disasm_info.mach = bfd_get_mach (abfd);
2753 #endif
2754 #ifdef WORDS_BIGENDIAN
2755         disasm_info.endian = BFD_ENDIAN_BIG;
2756 #else
2757         disasm_info.endian = BFD_ENDIAN_LITTLE;
2758 #endif        
2759         fprintf(logfile, "IN:\n");
2760         disasm_info.buffer = pc_start;
2761         disasm_info.buffer_vma = (unsigned long)pc_start;
2762         disasm_info.buffer_length = pc_ptr - pc_start;
2763         pc = pc_start;
2764         while (pc < pc_ptr) {
2765             fprintf(logfile, "0x%08lx:  ", (long)pc);
2766             count = print_insn_i386((unsigned long)pc, &disasm_info);
2767             fprintf(logfile, "\n");
2768             pc += count;
2769         }
2770         fprintf(logfile, "\n");
2771         
2772         pc = gen_code_buf;
2773         disasm_info.buffer = pc;
2774         disasm_info.buffer_vma = (unsigned long)pc;
2775         disasm_info.buffer_length = *gen_code_size_ptr;
2776         fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2777         while (pc < gen_code_ptr) {
2778             fprintf(logfile, "0x%08lx:  ", (long)pc);
2779             count = print_insn_i386((unsigned long)pc, &disasm_info);
2780             fprintf(logfile, "\n");
2781             pc += count;
2782         }
2783         fprintf(logfile, "\n");
2784     }
2785 #endif
2786     return 0;
2787 }
2788
2789 CPUX86State *cpu_x86_init(void)
2790 {
2791     CPUX86State *env;
2792     int i;
2793
2794     cpu_x86_tblocks_init();
2795
2796     env = malloc(sizeof(CPUX86State));
2797     if (!env)
2798         return NULL;
2799     memset(env, 0, sizeof(CPUX86State));
2800     /* basic FPU init */
2801     for(i = 0;i < 8; i++)
2802         env->fptags[i] = 1;
2803     env->fpuc = 0x37f;
2804     /* flags setup */
2805     env->cc_op = CC_OP_EFLAGS;
2806     env->df = 1;
2807     return env;
2808 }
2809
2810 void cpu_x86_close(CPUX86State *env)
2811 {
2812     free(env);
2813 }