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