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