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