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