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