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