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