use direct jump only for jumps in the same page
[qemu] / target-i386 / translate.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 "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
31
32 /* XXX: move that elsewhere */
33 static uint16_t *gen_opc_ptr;
34 static uint32_t *gen_opparam_ptr;
35
36 #define PREFIX_REPZ   0x01
37 #define PREFIX_REPNZ  0x02
38 #define PREFIX_LOCK   0x04
39 #define PREFIX_DATA   0x08
40 #define PREFIX_ADR    0x10
41
42 #ifdef TARGET_X86_64
43 #define X86_64_ONLY(x) x
44 #define X86_64_DEF(x...) x
45 #define CODE64(s) ((s)->code64)
46 #define REX_X(s) ((s)->rex_x)
47 #define REX_B(s) ((s)->rex_b)
48 /* XXX: gcc generates push/pop in some opcodes, so we cannot use them */
49 #if 1
50 #define BUGGY_64(x) NULL
51 #endif
52 #else
53 #define X86_64_ONLY(x) NULL
54 #define X86_64_DEF(x...)
55 #define CODE64(s) 0
56 #define REX_X(s) 0
57 #define REX_B(s) 0
58 #endif
59
60 #ifdef TARGET_X86_64
61 static int x86_64_hregs;
62 #endif
63
64 #ifdef USE_DIRECT_JUMP
65 #define TBPARAM(x)
66 #else
67 #define TBPARAM(x) (long)(x)
68 #endif
69
70 typedef struct DisasContext {
71     /* current insn context */
72     int override; /* -1 if no override */
73     int prefix;
74     int aflag, dflag;
75     target_ulong pc; /* pc = eip + cs_base */
76     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
77                    static state change (stop translation) */
78     /* current block context */
79     target_ulong cs_base; /* base of CS segment */
80     int pe;     /* protected mode */
81     int code32; /* 32 bit code segment */
82 #ifdef TARGET_X86_64
83     int lma;    /* long mode active */
84     int code64; /* 64 bit code segment */
85     int rex_x, rex_b;
86 #endif
87     int ss32;   /* 32 bit stack segment */
88     int cc_op;  /* current CC operation */
89     int addseg; /* non zero if either DS/ES/SS have a non zero base */
90     int f_st;   /* currently unused */
91     int vm86;   /* vm86 mode */
92     int cpl;
93     int iopl;
94     int tf;     /* TF cpu flag */
95     int singlestep_enabled; /* "hardware" single step enabled */
96     int jmp_opt; /* use direct block chaining for direct jumps */
97     int mem_index; /* select memory access functions */
98     int flags; /* all execution flags */
99     struct TranslationBlock *tb;
100     int popl_esp_hack; /* for correct popl with esp base handling */
101     int rip_offset; /* only used in x86_64, but left for simplicity */
102     int cpuid_features;
103 } DisasContext;
104
105 static void gen_eob(DisasContext *s);
106 static void gen_jmp(DisasContext *s, target_ulong eip);
107 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
108
109 /* i386 arith/logic operations */
110 enum {
111     OP_ADDL, 
112     OP_ORL, 
113     OP_ADCL, 
114     OP_SBBL,
115     OP_ANDL, 
116     OP_SUBL, 
117     OP_XORL, 
118     OP_CMPL,
119 };
120
121 /* i386 shift ops */
122 enum {
123     OP_ROL, 
124     OP_ROR, 
125     OP_RCL, 
126     OP_RCR, 
127     OP_SHL, 
128     OP_SHR, 
129     OP_SHL1, /* undocumented */
130     OP_SAR = 7,
131 };
132
133 enum {
134 #define DEF(s, n, copy_size) INDEX_op_ ## s,
135 #include "opc.h"
136 #undef DEF
137     NB_OPS,
138 };
139
140 #include "gen-op.h"
141
142 /* operand size */
143 enum {
144     OT_BYTE = 0,
145     OT_WORD,
146     OT_LONG, 
147     OT_QUAD,
148 };
149
150 enum {
151     /* I386 int registers */
152     OR_EAX,   /* MUST be even numbered */
153     OR_ECX,
154     OR_EDX,
155     OR_EBX,
156     OR_ESP,
157     OR_EBP,
158     OR_ESI,
159     OR_EDI,
160
161     OR_TMP0 = 16,    /* temporary operand register */
162     OR_TMP1,
163     OR_A0, /* temporary register used when doing address evaluation */
164 };
165
166 #ifdef TARGET_X86_64
167
168 #define NB_OP_SIZES 4
169
170 #define DEF_REGS(prefix, suffix) \
171   prefix ## EAX ## suffix,\
172   prefix ## ECX ## suffix,\
173   prefix ## EDX ## suffix,\
174   prefix ## EBX ## suffix,\
175   prefix ## ESP ## suffix,\
176   prefix ## EBP ## suffix,\
177   prefix ## ESI ## suffix,\
178   prefix ## EDI ## suffix,\
179   prefix ## R8 ## suffix,\
180   prefix ## R9 ## suffix,\
181   prefix ## R10 ## suffix,\
182   prefix ## R11 ## suffix,\
183   prefix ## R12 ## suffix,\
184   prefix ## R13 ## suffix,\
185   prefix ## R14 ## suffix,\
186   prefix ## R15 ## suffix,
187
188 #define DEF_BREGS(prefixb, prefixh, suffix)             \
189                                                         \
190 static void prefixb ## ESP ## suffix ## _wrapper(void)  \
191 {                                                       \
192     if (x86_64_hregs)                                 \
193         prefixb ## ESP ## suffix ();                    \
194     else                                                \
195         prefixh ## EAX ## suffix ();                    \
196 }                                                       \
197                                                         \
198 static void prefixb ## EBP ## suffix ## _wrapper(void)  \
199 {                                                       \
200     if (x86_64_hregs)                                 \
201         prefixb ## EBP ## suffix ();                    \
202     else                                                \
203         prefixh ## ECX ## suffix ();                    \
204 }                                                       \
205                                                         \
206 static void prefixb ## ESI ## suffix ## _wrapper(void)  \
207 {                                                       \
208     if (x86_64_hregs)                                 \
209         prefixb ## ESI ## suffix ();                    \
210     else                                                \
211         prefixh ## EDX ## suffix ();                    \
212 }                                                       \
213                                                         \
214 static void prefixb ## EDI ## suffix ## _wrapper(void)  \
215 {                                                       \
216     if (x86_64_hregs)                                 \
217         prefixb ## EDI ## suffix ();                    \
218     else                                                \
219         prefixh ## EBX ## suffix ();                    \
220 }
221
222 DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0)
223 DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1)
224 DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, )
225 DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, )
226
227 #else /* !TARGET_X86_64 */
228
229 #define NB_OP_SIZES 3
230
231 #define DEF_REGS(prefix, suffix) \
232   prefix ## EAX ## suffix,\
233   prefix ## ECX ## suffix,\
234   prefix ## EDX ## suffix,\
235   prefix ## EBX ## suffix,\
236   prefix ## ESP ## suffix,\
237   prefix ## EBP ## suffix,\
238   prefix ## ESI ## suffix,\
239   prefix ## EDI ## suffix,
240
241 #endif /* !TARGET_X86_64 */
242
243 static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = {
244     [OT_BYTE] = {
245         gen_op_movb_EAX_T0,
246         gen_op_movb_ECX_T0,
247         gen_op_movb_EDX_T0,
248         gen_op_movb_EBX_T0,
249 #ifdef TARGET_X86_64
250         gen_op_movb_ESP_T0_wrapper,
251         gen_op_movb_EBP_T0_wrapper,
252         gen_op_movb_ESI_T0_wrapper,
253         gen_op_movb_EDI_T0_wrapper,
254         gen_op_movb_R8_T0,
255         gen_op_movb_R9_T0,
256         gen_op_movb_R10_T0,
257         gen_op_movb_R11_T0,
258         gen_op_movb_R12_T0,
259         gen_op_movb_R13_T0,
260         gen_op_movb_R14_T0,
261         gen_op_movb_R15_T0,
262 #else
263         gen_op_movh_EAX_T0,
264         gen_op_movh_ECX_T0,
265         gen_op_movh_EDX_T0,
266         gen_op_movh_EBX_T0,
267 #endif
268     },
269     [OT_WORD] = {
270         DEF_REGS(gen_op_movw_, _T0)
271     },
272     [OT_LONG] = {
273         DEF_REGS(gen_op_movl_, _T0)
274     },
275 #ifdef TARGET_X86_64
276     [OT_QUAD] = {
277         DEF_REGS(gen_op_movq_, _T0)
278     },
279 #endif
280 };
281
282 static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = {
283     [OT_BYTE] = {
284         gen_op_movb_EAX_T1,
285         gen_op_movb_ECX_T1,
286         gen_op_movb_EDX_T1,
287         gen_op_movb_EBX_T1,
288 #ifdef TARGET_X86_64
289         gen_op_movb_ESP_T1_wrapper,
290         gen_op_movb_EBP_T1_wrapper,
291         gen_op_movb_ESI_T1_wrapper,
292         gen_op_movb_EDI_T1_wrapper,
293         gen_op_movb_R8_T1,
294         gen_op_movb_R9_T1,
295         gen_op_movb_R10_T1,
296         gen_op_movb_R11_T1,
297         gen_op_movb_R12_T1,
298         gen_op_movb_R13_T1,
299         gen_op_movb_R14_T1,
300         gen_op_movb_R15_T1,
301 #else
302         gen_op_movh_EAX_T1,
303         gen_op_movh_ECX_T1,
304         gen_op_movh_EDX_T1,
305         gen_op_movh_EBX_T1,
306 #endif
307     },
308     [OT_WORD] = {
309         DEF_REGS(gen_op_movw_, _T1)
310     },
311     [OT_LONG] = {
312         DEF_REGS(gen_op_movl_, _T1)
313     },
314 #ifdef TARGET_X86_64
315     [OT_QUAD] = {
316         DEF_REGS(gen_op_movq_, _T1)
317     },
318 #endif
319 };
320
321 static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
322     [0] = {
323         DEF_REGS(gen_op_movw_, _A0)
324     },
325     [1] = {
326         DEF_REGS(gen_op_movl_, _A0)
327     },
328 #ifdef TARGET_X86_64
329     [2] = {
330         DEF_REGS(gen_op_movq_, _A0)
331     },
332 #endif
333 };
334
335 static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] = 
336 {
337     [OT_BYTE] = {
338         {
339             gen_op_movl_T0_EAX,
340             gen_op_movl_T0_ECX,
341             gen_op_movl_T0_EDX,
342             gen_op_movl_T0_EBX,
343 #ifdef TARGET_X86_64
344             gen_op_movl_T0_ESP_wrapper,
345             gen_op_movl_T0_EBP_wrapper,
346             gen_op_movl_T0_ESI_wrapper,
347             gen_op_movl_T0_EDI_wrapper,
348             gen_op_movl_T0_R8,
349             gen_op_movl_T0_R9,
350             gen_op_movl_T0_R10,
351             gen_op_movl_T0_R11,
352             gen_op_movl_T0_R12,
353             gen_op_movl_T0_R13,
354             gen_op_movl_T0_R14,
355             gen_op_movl_T0_R15,
356 #else
357             gen_op_movh_T0_EAX,
358             gen_op_movh_T0_ECX,
359             gen_op_movh_T0_EDX,
360             gen_op_movh_T0_EBX,
361 #endif
362         },
363         {
364             gen_op_movl_T1_EAX,
365             gen_op_movl_T1_ECX,
366             gen_op_movl_T1_EDX,
367             gen_op_movl_T1_EBX,
368 #ifdef TARGET_X86_64
369             gen_op_movl_T1_ESP_wrapper,
370             gen_op_movl_T1_EBP_wrapper,
371             gen_op_movl_T1_ESI_wrapper,
372             gen_op_movl_T1_EDI_wrapper,
373             gen_op_movl_T1_R8,
374             gen_op_movl_T1_R9,
375             gen_op_movl_T1_R10,
376             gen_op_movl_T1_R11,
377             gen_op_movl_T1_R12,
378             gen_op_movl_T1_R13,
379             gen_op_movl_T1_R14,
380             gen_op_movl_T1_R15,
381 #else
382             gen_op_movh_T1_EAX,
383             gen_op_movh_T1_ECX,
384             gen_op_movh_T1_EDX,
385             gen_op_movh_T1_EBX,
386 #endif
387         },
388     },
389     [OT_WORD] = {
390         {
391             DEF_REGS(gen_op_movl_T0_, )
392         },
393         {
394             DEF_REGS(gen_op_movl_T1_, )
395         },
396     },
397     [OT_LONG] = {
398         {
399             DEF_REGS(gen_op_movl_T0_, )
400         },
401         {
402             DEF_REGS(gen_op_movl_T1_, )
403         },
404     },
405 #ifdef TARGET_X86_64
406     [OT_QUAD] = {
407         {
408             DEF_REGS(gen_op_movl_T0_, )
409         },
410         {
411             DEF_REGS(gen_op_movl_T1_, )
412         },
413     },
414 #endif
415 };
416
417 static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = {
418     DEF_REGS(gen_op_movl_A0_, )
419 };
420
421 static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = {
422     [0] = {
423         DEF_REGS(gen_op_addl_A0_, )
424     },
425     [1] = {
426         DEF_REGS(gen_op_addl_A0_, _s1)
427     },
428     [2] = {
429         DEF_REGS(gen_op_addl_A0_, _s2)
430     },
431     [3] = {
432         DEF_REGS(gen_op_addl_A0_, _s3)
433     },
434 };
435
436 #ifdef TARGET_X86_64
437 static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = {
438     DEF_REGS(gen_op_movq_A0_, )
439 };
440
441 static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = {
442     [0] = {
443         DEF_REGS(gen_op_addq_A0_, )
444     },
445     [1] = {
446         DEF_REGS(gen_op_addq_A0_, _s1)
447     },
448     [2] = {
449         DEF_REGS(gen_op_addq_A0_, _s2)
450     },
451     [3] = {
452         DEF_REGS(gen_op_addq_A0_, _s3)
453     },
454 };
455 #endif
456
457 static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = {
458     [0] = {
459         DEF_REGS(gen_op_cmovw_, _T1_T0)
460     },
461     [1] = {
462         DEF_REGS(gen_op_cmovl_, _T1_T0)
463     },
464 #ifdef TARGET_X86_64
465     [2] = {
466         DEF_REGS(gen_op_cmovq_, _T1_T0)
467     },
468 #endif
469 };
470
471 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
472     NULL,
473     gen_op_orl_T0_T1,
474     NULL,
475     NULL,
476     gen_op_andl_T0_T1,
477     NULL,
478     gen_op_xorl_T0_T1,
479     NULL,
480 };
481
482 #define DEF_ARITHC(SUFFIX)\
483     {\
484         gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
485         gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
486     },\
487     {\
488         gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
489         gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
490     },\
491     {\
492         gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
493         gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
494     },\
495     {\
496         X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\
497         X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\
498     },
499
500 static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = {
501     DEF_ARITHC( )
502 };
503
504 static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = {
505     DEF_ARITHC(_raw)
506 #ifndef CONFIG_USER_ONLY
507     DEF_ARITHC(_kernel)
508     DEF_ARITHC(_user)
509 #endif
510 };
511
512 static const int cc_op_arithb[8] = {
513     CC_OP_ADDB,
514     CC_OP_LOGICB,
515     CC_OP_ADDB,
516     CC_OP_SUBB,
517     CC_OP_LOGICB,
518     CC_OP_SUBB,
519     CC_OP_LOGICB,
520     CC_OP_SUBB,
521 };
522
523 #define DEF_CMPXCHG(SUFFIX)\
524     gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
525     gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
526     gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\
527     X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc),
528
529 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = {
530     DEF_CMPXCHG( )
531 };
532
533 static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = {
534     DEF_CMPXCHG(_raw)
535 #ifndef CONFIG_USER_ONLY
536     DEF_CMPXCHG(_kernel)
537     DEF_CMPXCHG(_user)
538 #endif
539 };
540
541 #define DEF_SHIFT(SUFFIX)\
542     {\
543         gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
544         gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
545         gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
546         gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
547         gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
548         gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
549         gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
550         gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
551     },\
552     {\
553         gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
554         gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
555         gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
556         gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
557         gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
558         gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
559         gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
560         gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
561     },\
562     {\
563         gen_op_roll ## SUFFIX ## _T0_T1_cc,\
564         gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
565         gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
566         gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
567         gen_op_shll ## SUFFIX ## _T0_T1_cc,\
568         gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
569         gen_op_shll ## SUFFIX ## _T0_T1_cc,\
570         gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
571     },\
572     {\
573         X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\
574         X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\
575         X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\
576         X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\
577         X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
578         X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\
579         X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\
580         X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\
581     },
582
583 static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = {
584     DEF_SHIFT( )
585 };
586
587 static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = {
588     DEF_SHIFT(_raw)
589 #ifndef CONFIG_USER_ONLY
590     DEF_SHIFT(_kernel)
591     DEF_SHIFT(_user)
592 #endif
593 };
594
595 #define DEF_SHIFTD(SUFFIX, op)\
596     {\
597         NULL,\
598         NULL,\
599     },\
600     {\
601         gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
602         gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
603      },\
604     {\
605         gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
606         gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
607     },\
608     {\
609 X86_64_DEF(gen_op_shldq ## SUFFIX ## _T0_T1_ ## op ## _cc,\
610            gen_op_shrdq ## SUFFIX ## _T0_T1_ ## op ## _cc,)\
611     },
612
613 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = {
614     DEF_SHIFTD(, im)
615 };
616
617 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = {
618     DEF_SHIFTD(, ECX)
619 };
620
621 static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = {
622     DEF_SHIFTD(_raw, im)
623 #ifndef CONFIG_USER_ONLY
624     DEF_SHIFTD(_kernel, im)
625     DEF_SHIFTD(_user, im)
626 #endif
627 };
628
629 static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = {
630     DEF_SHIFTD(_raw, ECX)
631 #ifndef CONFIG_USER_ONLY
632     DEF_SHIFTD(_kernel, ECX)
633     DEF_SHIFTD(_user, ECX)
634 #endif
635 };
636
637 static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = {
638     [0] = {
639         gen_op_btw_T0_T1_cc,
640         gen_op_btsw_T0_T1_cc,
641         gen_op_btrw_T0_T1_cc,
642         gen_op_btcw_T0_T1_cc,
643     },
644     [1] = {
645         gen_op_btl_T0_T1_cc,
646         gen_op_btsl_T0_T1_cc,
647         gen_op_btrl_T0_T1_cc,
648         gen_op_btcl_T0_T1_cc,
649     },
650 #ifdef TARGET_X86_64
651     [2] = {
652         gen_op_btq_T0_T1_cc,
653         gen_op_btsq_T0_T1_cc,
654         gen_op_btrq_T0_T1_cc,
655         gen_op_btcq_T0_T1_cc,
656     },
657 #endif
658 };
659
660 static GenOpFunc *gen_op_add_bit_A0_T1[3] = {
661     gen_op_add_bitw_A0_T1,
662     gen_op_add_bitl_A0_T1,
663     X86_64_ONLY(gen_op_add_bitq_A0_T1),
664 };
665
666 static GenOpFunc *gen_op_bsx_T0_cc[3][2] = {
667     [0] = {
668         gen_op_bsfw_T0_cc,
669         gen_op_bsrw_T0_cc,
670     },
671     [1] = {
672         gen_op_bsfl_T0_cc,
673         gen_op_bsrl_T0_cc,
674     },
675 #ifdef TARGET_X86_64
676     [2] = {
677         gen_op_bsfq_T0_cc,
678         gen_op_bsrq_T0_cc,
679     },
680 #endif
681 };
682
683 static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = {
684     gen_op_ldsb_raw_T0_A0,
685     gen_op_ldsw_raw_T0_A0,
686     X86_64_ONLY(gen_op_ldsl_raw_T0_A0),
687     NULL,
688 #ifndef CONFIG_USER_ONLY
689     gen_op_ldsb_kernel_T0_A0,
690     gen_op_ldsw_kernel_T0_A0,
691     X86_64_ONLY(gen_op_ldsl_kernel_T0_A0),
692     NULL,
693
694     gen_op_ldsb_user_T0_A0,
695     gen_op_ldsw_user_T0_A0,
696     X86_64_ONLY(gen_op_ldsl_user_T0_A0),
697     NULL,
698 #endif
699 };
700
701 static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = {
702     gen_op_ldub_raw_T0_A0,
703     gen_op_lduw_raw_T0_A0,
704     NULL,
705     NULL,
706
707 #ifndef CONFIG_USER_ONLY
708     gen_op_ldub_kernel_T0_A0,
709     gen_op_lduw_kernel_T0_A0,
710     NULL,
711     NULL,
712
713     gen_op_ldub_user_T0_A0,
714     gen_op_lduw_user_T0_A0,
715     NULL,
716     NULL,
717 #endif
718 };
719
720 /* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
721 static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = {
722     gen_op_ldub_raw_T0_A0,
723     gen_op_lduw_raw_T0_A0,
724     gen_op_ldl_raw_T0_A0,
725     X86_64_ONLY(gen_op_ldq_raw_T0_A0),
726
727 #ifndef CONFIG_USER_ONLY
728     gen_op_ldub_kernel_T0_A0,
729     gen_op_lduw_kernel_T0_A0,
730     gen_op_ldl_kernel_T0_A0,
731     X86_64_ONLY(gen_op_ldq_kernel_T0_A0),
732
733     gen_op_ldub_user_T0_A0,
734     gen_op_lduw_user_T0_A0,
735     gen_op_ldl_user_T0_A0,
736     X86_64_ONLY(gen_op_ldq_user_T0_A0),
737 #endif
738 };
739
740 static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = {
741     gen_op_ldub_raw_T1_A0,
742     gen_op_lduw_raw_T1_A0,
743     gen_op_ldl_raw_T1_A0,
744     X86_64_ONLY(gen_op_ldq_raw_T1_A0),
745
746 #ifndef CONFIG_USER_ONLY
747     gen_op_ldub_kernel_T1_A0,
748     gen_op_lduw_kernel_T1_A0,
749     gen_op_ldl_kernel_T1_A0,
750     X86_64_ONLY(gen_op_ldq_kernel_T1_A0),
751
752     gen_op_ldub_user_T1_A0,
753     gen_op_lduw_user_T1_A0,
754     gen_op_ldl_user_T1_A0,
755     X86_64_ONLY(gen_op_ldq_user_T1_A0),
756 #endif
757 };
758
759 static GenOpFunc *gen_op_st_T0_A0[3 * 4] = {
760     gen_op_stb_raw_T0_A0,
761     gen_op_stw_raw_T0_A0,
762     gen_op_stl_raw_T0_A0,
763     X86_64_ONLY(gen_op_stq_raw_T0_A0),
764
765 #ifndef CONFIG_USER_ONLY
766     gen_op_stb_kernel_T0_A0,
767     gen_op_stw_kernel_T0_A0,
768     gen_op_stl_kernel_T0_A0,
769     X86_64_ONLY(gen_op_stq_kernel_T0_A0),
770
771     gen_op_stb_user_T0_A0,
772     gen_op_stw_user_T0_A0,
773     gen_op_stl_user_T0_A0,
774     X86_64_ONLY(gen_op_stq_user_T0_A0),
775 #endif
776 };
777
778 static GenOpFunc *gen_op_st_T1_A0[3 * 4] = {
779     NULL,
780     gen_op_stw_raw_T1_A0,
781     gen_op_stl_raw_T1_A0,
782     X86_64_ONLY(gen_op_stq_raw_T1_A0),
783
784 #ifndef CONFIG_USER_ONLY
785     NULL,
786     gen_op_stw_kernel_T1_A0,
787     gen_op_stl_kernel_T1_A0,
788     X86_64_ONLY(gen_op_stq_kernel_T1_A0),
789
790     NULL,
791     gen_op_stw_user_T1_A0,
792     gen_op_stl_user_T1_A0,
793     X86_64_ONLY(gen_op_stq_user_T1_A0),
794 #endif
795 };
796
797 static inline void gen_jmp_im(target_ulong pc)
798 {
799 #ifdef TARGET_X86_64
800     if (pc == (uint32_t)pc) {
801         gen_op_movl_eip_im(pc);
802     } else if (pc == (int32_t)pc) {
803         gen_op_movq_eip_im(pc);
804     } else {
805         gen_op_movq_eip_im64(pc >> 32, pc);
806     }
807 #else
808     gen_op_movl_eip_im(pc);
809 #endif
810 }
811
812 static inline void gen_string_movl_A0_ESI(DisasContext *s)
813 {
814     int override;
815
816     override = s->override;
817 #ifdef TARGET_X86_64
818     if (s->aflag == 2) {
819         if (override >= 0) {
820             gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base));
821             gen_op_addq_A0_reg_sN[0][R_ESI]();
822         } else {
823             gen_op_movq_A0_reg[R_ESI]();
824         }
825     } else
826 #endif
827     if (s->aflag) {
828         /* 32 bit address */
829         if (s->addseg && override < 0)
830             override = R_DS;
831         if (override >= 0) {
832             gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
833             gen_op_addl_A0_reg_sN[0][R_ESI]();
834         } else {
835             gen_op_movl_A0_reg[R_ESI]();
836         }
837     } else {
838         /* 16 address, always override */
839         if (override < 0)
840             override = R_DS;
841         gen_op_movl_A0_reg[R_ESI]();
842         gen_op_andl_A0_ffff();
843         gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
844     }
845 }
846
847 static inline void gen_string_movl_A0_EDI(DisasContext *s)
848 {
849 #ifdef TARGET_X86_64
850     if (s->aflag == 2) {
851         gen_op_movq_A0_reg[R_EDI]();
852     } else
853 #endif
854     if (s->aflag) {
855         if (s->addseg) {
856             gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
857             gen_op_addl_A0_reg_sN[0][R_EDI]();
858         } else {
859             gen_op_movl_A0_reg[R_EDI]();
860         }
861     } else {
862         gen_op_movl_A0_reg[R_EDI]();
863         gen_op_andl_A0_ffff();
864         gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base));
865     }
866 }
867
868 static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
869     gen_op_movl_T0_Dshiftb,
870     gen_op_movl_T0_Dshiftw,
871     gen_op_movl_T0_Dshiftl,
872     X86_64_ONLY(gen_op_movl_T0_Dshiftq),
873 };
874
875 static GenOpFunc1 *gen_op_jnz_ecx[3] = {
876     gen_op_jnz_ecxw,
877     gen_op_jnz_ecxl,
878     X86_64_ONLY(gen_op_jnz_ecxq),
879 };
880     
881 static GenOpFunc1 *gen_op_jz_ecx[3] = {
882     gen_op_jz_ecxw,
883     gen_op_jz_ecxl,
884     X86_64_ONLY(gen_op_jz_ecxq),
885 };
886
887 static GenOpFunc *gen_op_dec_ECX[3] = {
888     gen_op_decw_ECX,
889     gen_op_decl_ECX,
890     X86_64_ONLY(gen_op_decq_ECX),
891 };
892
893 static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
894     {
895         gen_op_jnz_subb,
896         gen_op_jnz_subw,
897         gen_op_jnz_subl,
898         X86_64_ONLY(gen_op_jnz_subq),
899     },
900     {
901         gen_op_jz_subb,
902         gen_op_jz_subw,
903         gen_op_jz_subl,
904         X86_64_ONLY(gen_op_jz_subq),
905     },
906 };
907
908 static GenOpFunc *gen_op_in_DX_T0[3] = {
909     gen_op_inb_DX_T0,
910     gen_op_inw_DX_T0,
911     gen_op_inl_DX_T0,
912 };
913
914 static GenOpFunc *gen_op_out_DX_T0[3] = {
915     gen_op_outb_DX_T0,
916     gen_op_outw_DX_T0,
917     gen_op_outl_DX_T0,
918 };
919
920 static GenOpFunc *gen_op_in[3] = {
921     gen_op_inb_T0_T1,
922     gen_op_inw_T0_T1,
923     gen_op_inl_T0_T1,
924 };
925
926 static GenOpFunc *gen_op_out[3] = {
927     gen_op_outb_T0_T1,
928     gen_op_outw_T0_T1,
929     gen_op_outl_T0_T1,
930 };
931
932 static GenOpFunc *gen_check_io_T0[3] = {
933     gen_op_check_iob_T0,
934     gen_op_check_iow_T0,
935     gen_op_check_iol_T0,
936 };
937
938 static GenOpFunc *gen_check_io_DX[3] = {
939     gen_op_check_iob_DX,
940     gen_op_check_iow_DX,
941     gen_op_check_iol_DX,
942 };
943
944 static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip)
945 {
946     if (s->pe && (s->cpl > s->iopl || s->vm86)) {
947         if (s->cc_op != CC_OP_DYNAMIC)
948             gen_op_set_cc_op(s->cc_op);
949         gen_jmp_im(cur_eip);
950         if (use_dx)
951             gen_check_io_DX[ot]();
952         else
953             gen_check_io_T0[ot]();
954     }
955 }
956
957 static inline void gen_movs(DisasContext *s, int ot)
958 {
959     gen_string_movl_A0_ESI(s);
960     gen_op_ld_T0_A0[ot + s->mem_index]();
961     gen_string_movl_A0_EDI(s);
962     gen_op_st_T0_A0[ot + s->mem_index]();
963     gen_op_movl_T0_Dshift[ot]();
964 #ifdef TARGET_X86_64
965     if (s->aflag == 2) {
966         gen_op_addq_ESI_T0();
967         gen_op_addq_EDI_T0();
968     } else 
969 #endif
970     if (s->aflag) {
971         gen_op_addl_ESI_T0();
972         gen_op_addl_EDI_T0();
973     } else {
974         gen_op_addw_ESI_T0();
975         gen_op_addw_EDI_T0();
976     }
977 }
978
979 static inline void gen_update_cc_op(DisasContext *s)
980 {
981     if (s->cc_op != CC_OP_DYNAMIC) {
982         gen_op_set_cc_op(s->cc_op);
983         s->cc_op = CC_OP_DYNAMIC;
984     }
985 }
986
987 /* XXX: does not work with gdbstub "ice" single step - not a
988    serious problem */
989 static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
990 {
991     int l1, l2;
992
993     l1 = gen_new_label();
994     l2 = gen_new_label();
995     gen_op_jnz_ecx[s->aflag](l1);
996     gen_set_label(l2);
997     gen_jmp_tb(s, next_eip, 1);
998     gen_set_label(l1);
999     return l2;
1000 }
1001
1002 static inline void gen_stos(DisasContext *s, int ot)
1003 {
1004     gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1005     gen_string_movl_A0_EDI(s);
1006     gen_op_st_T0_A0[ot + s->mem_index]();
1007     gen_op_movl_T0_Dshift[ot]();
1008 #ifdef TARGET_X86_64
1009     if (s->aflag == 2) {
1010         gen_op_addq_EDI_T0();
1011     } else 
1012 #endif
1013     if (s->aflag) {
1014         gen_op_addl_EDI_T0();
1015     } else {
1016         gen_op_addw_EDI_T0();
1017     }
1018 }
1019
1020 static inline void gen_lods(DisasContext *s, int ot)
1021 {
1022     gen_string_movl_A0_ESI(s);
1023     gen_op_ld_T0_A0[ot + s->mem_index]();
1024     gen_op_mov_reg_T0[ot][R_EAX]();
1025     gen_op_movl_T0_Dshift[ot]();
1026 #ifdef TARGET_X86_64
1027     if (s->aflag == 2) {
1028         gen_op_addq_ESI_T0();
1029     } else 
1030 #endif
1031     if (s->aflag) {
1032         gen_op_addl_ESI_T0();
1033     } else {
1034         gen_op_addw_ESI_T0();
1035     }
1036 }
1037
1038 static inline void gen_scas(DisasContext *s, int ot)
1039 {
1040     gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
1041     gen_string_movl_A0_EDI(s);
1042     gen_op_ld_T1_A0[ot + s->mem_index]();
1043     gen_op_cmpl_T0_T1_cc();
1044     gen_op_movl_T0_Dshift[ot]();
1045 #ifdef TARGET_X86_64
1046     if (s->aflag == 2) {
1047         gen_op_addq_EDI_T0();
1048     } else 
1049 #endif
1050     if (s->aflag) {
1051         gen_op_addl_EDI_T0();
1052     } else {
1053         gen_op_addw_EDI_T0();
1054     }
1055 }
1056
1057 static inline void gen_cmps(DisasContext *s, int ot)
1058 {
1059     gen_string_movl_A0_ESI(s);
1060     gen_op_ld_T0_A0[ot + s->mem_index]();
1061     gen_string_movl_A0_EDI(s);
1062     gen_op_ld_T1_A0[ot + s->mem_index]();
1063     gen_op_cmpl_T0_T1_cc();
1064     gen_op_movl_T0_Dshift[ot]();
1065 #ifdef TARGET_X86_64
1066     if (s->aflag == 2) {
1067         gen_op_addq_ESI_T0();
1068         gen_op_addq_EDI_T0();
1069     } else 
1070 #endif
1071     if (s->aflag) {
1072         gen_op_addl_ESI_T0();
1073         gen_op_addl_EDI_T0();
1074     } else {
1075         gen_op_addw_ESI_T0();
1076         gen_op_addw_EDI_T0();
1077     }
1078 }
1079
1080 static inline void gen_ins(DisasContext *s, int ot)
1081 {
1082     gen_string_movl_A0_EDI(s);
1083     gen_op_movl_T0_0();
1084     gen_op_st_T0_A0[ot + s->mem_index]();
1085     gen_op_in_DX_T0[ot]();
1086     gen_op_st_T0_A0[ot + s->mem_index]();
1087     gen_op_movl_T0_Dshift[ot]();
1088 #ifdef TARGET_X86_64
1089     if (s->aflag == 2) {
1090         gen_op_addq_EDI_T0();
1091     } else 
1092 #endif
1093     if (s->aflag) {
1094         gen_op_addl_EDI_T0();
1095     } else {
1096         gen_op_addw_EDI_T0();
1097     }
1098 }
1099
1100 static inline void gen_outs(DisasContext *s, int ot)
1101 {
1102     gen_string_movl_A0_ESI(s);
1103     gen_op_ld_T0_A0[ot + s->mem_index]();
1104     gen_op_out_DX_T0[ot]();
1105     gen_op_movl_T0_Dshift[ot]();
1106 #ifdef TARGET_X86_64
1107     if (s->aflag == 2) {
1108         gen_op_addq_ESI_T0();
1109     } else 
1110 #endif
1111     if (s->aflag) {
1112         gen_op_addl_ESI_T0();
1113     } else {
1114         gen_op_addw_ESI_T0();
1115     }
1116 }
1117
1118 /* same method as Valgrind : we generate jumps to current or next
1119    instruction */
1120 #define GEN_REPZ(op)                                                          \
1121 static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
1122                                  target_ulong cur_eip, target_ulong next_eip) \
1123 {                                                                             \
1124     int l2;\
1125     gen_update_cc_op(s);                                                      \
1126     l2 = gen_jz_ecx_string(s, next_eip);                                      \
1127     gen_ ## op(s, ot);                                                        \
1128     gen_op_dec_ECX[s->aflag]();                                               \
1129     /* a loop would cause two single step exceptions if ECX = 1               \
1130        before rep string_insn */                                              \
1131     if (!s->jmp_opt)                                                          \
1132         gen_op_jz_ecx[s->aflag](l2);                                          \
1133     gen_jmp(s, cur_eip);                                                      \
1134 }
1135
1136 #define GEN_REPZ2(op)                                                         \
1137 static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
1138                                    target_ulong cur_eip,                      \
1139                                    target_ulong next_eip,                     \
1140                                    int nz)                                    \
1141 {                                                                             \
1142     int l2;\
1143     gen_update_cc_op(s);                                                      \
1144     l2 = gen_jz_ecx_string(s, next_eip);                                      \
1145     gen_ ## op(s, ot);                                                        \
1146     gen_op_dec_ECX[s->aflag]();                                               \
1147     gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
1148     gen_op_string_jnz_sub[nz][ot](l2);\
1149     if (!s->jmp_opt)                                                          \
1150         gen_op_jz_ecx[s->aflag](l2);                                          \
1151     gen_jmp(s, cur_eip);                                                      \
1152 }
1153
1154 GEN_REPZ(movs)
1155 GEN_REPZ(stos)
1156 GEN_REPZ(lods)
1157 GEN_REPZ(ins)
1158 GEN_REPZ(outs)
1159 GEN_REPZ2(scas)
1160 GEN_REPZ2(cmps)
1161
1162 enum {
1163     JCC_O,
1164     JCC_B,
1165     JCC_Z,
1166     JCC_BE,
1167     JCC_S,
1168     JCC_P,
1169     JCC_L,
1170     JCC_LE,
1171 };
1172
1173 static GenOpFunc1 *gen_jcc_sub[4][8] = {
1174     [OT_BYTE] = {
1175         NULL,
1176         gen_op_jb_subb,
1177         gen_op_jz_subb,
1178         gen_op_jbe_subb,
1179         gen_op_js_subb,
1180         NULL,
1181         gen_op_jl_subb,
1182         gen_op_jle_subb,
1183     },
1184     [OT_WORD] = {
1185         NULL,
1186         gen_op_jb_subw,
1187         gen_op_jz_subw,
1188         gen_op_jbe_subw,
1189         gen_op_js_subw,
1190         NULL,
1191         gen_op_jl_subw,
1192         gen_op_jle_subw,
1193     },
1194     [OT_LONG] = {
1195         NULL,
1196         gen_op_jb_subl,
1197         gen_op_jz_subl,
1198         gen_op_jbe_subl,
1199         gen_op_js_subl,
1200         NULL,
1201         gen_op_jl_subl,
1202         gen_op_jle_subl,
1203     },
1204 #ifdef TARGET_X86_64
1205     [OT_QUAD] = {
1206         NULL,
1207         BUGGY_64(gen_op_jb_subq),
1208         gen_op_jz_subq,
1209         BUGGY_64(gen_op_jbe_subq),
1210         gen_op_js_subq,
1211         NULL,
1212         BUGGY_64(gen_op_jl_subq),
1213         BUGGY_64(gen_op_jle_subq),
1214     },
1215 #endif
1216 };
1217 static GenOpFunc1 *gen_op_loop[3][4] = {
1218     [0] = {
1219         gen_op_loopnzw,
1220         gen_op_loopzw,
1221         gen_op_jnz_ecxw,
1222     },
1223     [1] = {
1224         gen_op_loopnzl,
1225         gen_op_loopzl,
1226         gen_op_jnz_ecxl,
1227     },
1228 #ifdef TARGET_X86_64
1229     [2] = {
1230         gen_op_loopnzq,
1231         gen_op_loopzq,
1232         gen_op_jnz_ecxq,
1233     },
1234 #endif
1235 };
1236
1237 static GenOpFunc *gen_setcc_slow[8] = {
1238     gen_op_seto_T0_cc,
1239     gen_op_setb_T0_cc,
1240     gen_op_setz_T0_cc,
1241     gen_op_setbe_T0_cc,
1242     gen_op_sets_T0_cc,
1243     gen_op_setp_T0_cc,
1244     gen_op_setl_T0_cc,
1245     gen_op_setle_T0_cc,
1246 };
1247
1248 static GenOpFunc *gen_setcc_sub[4][8] = {
1249     [OT_BYTE] = {
1250         NULL,
1251         gen_op_setb_T0_subb,
1252         gen_op_setz_T0_subb,
1253         gen_op_setbe_T0_subb,
1254         gen_op_sets_T0_subb,
1255         NULL,
1256         gen_op_setl_T0_subb,
1257         gen_op_setle_T0_subb,
1258     },
1259     [OT_WORD] = {
1260         NULL,
1261         gen_op_setb_T0_subw,
1262         gen_op_setz_T0_subw,
1263         gen_op_setbe_T0_subw,
1264         gen_op_sets_T0_subw,
1265         NULL,
1266         gen_op_setl_T0_subw,
1267         gen_op_setle_T0_subw,
1268     },
1269     [OT_LONG] = {
1270         NULL,
1271         gen_op_setb_T0_subl,
1272         gen_op_setz_T0_subl,
1273         gen_op_setbe_T0_subl,
1274         gen_op_sets_T0_subl,
1275         NULL,
1276         gen_op_setl_T0_subl,
1277         gen_op_setle_T0_subl,
1278     },
1279 #ifdef TARGET_X86_64
1280     [OT_QUAD] = {
1281         NULL,
1282         gen_op_setb_T0_subq,
1283         gen_op_setz_T0_subq,
1284         gen_op_setbe_T0_subq,
1285         gen_op_sets_T0_subq,
1286         NULL,
1287         gen_op_setl_T0_subq,
1288         gen_op_setle_T0_subq,
1289     },
1290 #endif
1291 };
1292
1293 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
1294     gen_op_fadd_ST0_FT0,
1295     gen_op_fmul_ST0_FT0,
1296     gen_op_fcom_ST0_FT0,
1297     gen_op_fcom_ST0_FT0,
1298     gen_op_fsub_ST0_FT0,
1299     gen_op_fsubr_ST0_FT0,
1300     gen_op_fdiv_ST0_FT0,
1301     gen_op_fdivr_ST0_FT0,
1302 };
1303
1304 /* NOTE the exception in "r" op ordering */
1305 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
1306     gen_op_fadd_STN_ST0,
1307     gen_op_fmul_STN_ST0,
1308     NULL,
1309     NULL,
1310     gen_op_fsubr_STN_ST0,
1311     gen_op_fsub_STN_ST0,
1312     gen_op_fdivr_STN_ST0,
1313     gen_op_fdiv_STN_ST0,
1314 };
1315
1316 /* if d == OR_TMP0, it means memory operand (address in A0) */
1317 static void gen_op(DisasContext *s1, int op, int ot, int d)
1318 {
1319     GenOpFunc *gen_update_cc;
1320     
1321     if (d != OR_TMP0) {
1322         gen_op_mov_TN_reg[ot][0][d]();
1323     } else {
1324         gen_op_ld_T0_A0[ot + s1->mem_index]();
1325     }
1326     switch(op) {
1327     case OP_ADCL:
1328     case OP_SBBL:
1329         if (s1->cc_op != CC_OP_DYNAMIC)
1330             gen_op_set_cc_op(s1->cc_op);
1331         if (d != OR_TMP0) {
1332             gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
1333             gen_op_mov_reg_T0[ot][d]();
1334         } else {
1335             gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
1336         }
1337         s1->cc_op = CC_OP_DYNAMIC;
1338         goto the_end;
1339     case OP_ADDL:
1340         gen_op_addl_T0_T1();
1341         s1->cc_op = CC_OP_ADDB + ot;
1342         gen_update_cc = gen_op_update2_cc;
1343         break;
1344     case OP_SUBL:
1345         gen_op_subl_T0_T1();
1346         s1->cc_op = CC_OP_SUBB + ot;
1347         gen_update_cc = gen_op_update2_cc;
1348         break;
1349     default:
1350     case OP_ANDL:
1351     case OP_ORL:
1352     case OP_XORL:
1353         gen_op_arith_T0_T1_cc[op]();
1354         s1->cc_op = CC_OP_LOGICB + ot;
1355         gen_update_cc = gen_op_update1_cc;
1356         break;
1357     case OP_CMPL:
1358         gen_op_cmpl_T0_T1_cc();
1359         s1->cc_op = CC_OP_SUBB + ot;
1360         gen_update_cc = NULL;
1361         break;
1362     }
1363     if (op != OP_CMPL) {
1364         if (d != OR_TMP0)
1365             gen_op_mov_reg_T0[ot][d]();
1366         else
1367             gen_op_st_T0_A0[ot + s1->mem_index]();
1368     }
1369     /* the flags update must happen after the memory write (precise
1370        exception support) */
1371     if (gen_update_cc)
1372         gen_update_cc();
1373  the_end: ;
1374 }
1375
1376 /* if d == OR_TMP0, it means memory operand (address in A0) */
1377 static void gen_inc(DisasContext *s1, int ot, int d, int c)
1378 {
1379     if (d != OR_TMP0)
1380         gen_op_mov_TN_reg[ot][0][d]();
1381     else
1382         gen_op_ld_T0_A0[ot + s1->mem_index]();
1383     if (s1->cc_op != CC_OP_DYNAMIC)
1384         gen_op_set_cc_op(s1->cc_op);
1385     if (c > 0) {
1386         gen_op_incl_T0();
1387         s1->cc_op = CC_OP_INCB + ot;
1388     } else {
1389         gen_op_decl_T0();
1390         s1->cc_op = CC_OP_DECB + ot;
1391     }
1392     if (d != OR_TMP0)
1393         gen_op_mov_reg_T0[ot][d]();
1394     else
1395         gen_op_st_T0_A0[ot + s1->mem_index]();
1396     gen_op_update_inc_cc();
1397 }
1398
1399 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
1400 {
1401     if (d != OR_TMP0)
1402         gen_op_mov_TN_reg[ot][0][d]();
1403     else
1404         gen_op_ld_T0_A0[ot + s1->mem_index]();
1405     if (s != OR_TMP1)
1406         gen_op_mov_TN_reg[ot][1][s]();
1407     /* for zero counts, flags are not updated, so must do it dynamically */
1408     if (s1->cc_op != CC_OP_DYNAMIC)
1409         gen_op_set_cc_op(s1->cc_op);
1410     
1411     if (d != OR_TMP0)
1412         gen_op_shift_T0_T1_cc[ot][op]();
1413     else
1414         gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
1415     if (d != OR_TMP0)
1416         gen_op_mov_reg_T0[ot][d]();
1417     s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1418 }
1419
1420 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
1421 {
1422     /* currently not optimized */
1423     gen_op_movl_T1_im(c);
1424     gen_shift(s1, op, ot, d, OR_TMP1);
1425 }
1426
1427 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
1428 {
1429     target_long disp;
1430     int havesib;
1431     int base;
1432     int index;
1433     int scale;
1434     int opreg;
1435     int mod, rm, code, override, must_add_seg;
1436
1437     override = s->override;
1438     must_add_seg = s->addseg;
1439     if (override >= 0)
1440         must_add_seg = 1;
1441     mod = (modrm >> 6) & 3;
1442     rm = modrm & 7;
1443
1444     if (s->aflag) {
1445
1446         havesib = 0;
1447         base = rm;
1448         index = 0;
1449         scale = 0;
1450         
1451         if (base == 4) {
1452             havesib = 1;
1453             code = ldub_code(s->pc++);
1454             scale = (code >> 6) & 3;
1455             index = ((code >> 3) & 7) | REX_X(s);
1456             base = (code & 7);
1457         }
1458         base |= REX_B(s);
1459
1460         switch (mod) {
1461         case 0:
1462             if ((base & 7) == 5) {
1463                 base = -1;
1464                 disp = (int32_t)ldl_code(s->pc);
1465                 s->pc += 4;
1466                 if (CODE64(s) && !havesib) {
1467                     disp += s->pc + s->rip_offset;
1468                 }
1469             } else {
1470                 disp = 0;
1471             }
1472             break;
1473         case 1:
1474             disp = (int8_t)ldub_code(s->pc++);
1475             break;
1476         default:
1477         case 2:
1478             disp = ldl_code(s->pc);
1479             s->pc += 4;
1480             break;
1481         }
1482         
1483         if (base >= 0) {
1484             /* for correct popl handling with esp */
1485             if (base == 4 && s->popl_esp_hack)
1486                 disp += s->popl_esp_hack;
1487 #ifdef TARGET_X86_64
1488             if (s->aflag == 2) {
1489                 gen_op_movq_A0_reg[base]();
1490                 if (disp != 0) {
1491                     if ((int32_t)disp == disp)
1492                         gen_op_addq_A0_im(disp);
1493                     else
1494                         gen_op_addq_A0_im64(disp >> 32, disp);
1495                 }
1496             } else 
1497 #endif
1498             {
1499                 gen_op_movl_A0_reg[base]();
1500                 if (disp != 0)
1501                     gen_op_addl_A0_im(disp);
1502             }
1503         } else {
1504 #ifdef TARGET_X86_64
1505             if (s->aflag == 2) {
1506                 if ((int32_t)disp == disp)
1507                     gen_op_movq_A0_im(disp);
1508                 else
1509                     gen_op_movq_A0_im64(disp >> 32, disp);
1510             } else 
1511 #endif
1512             {
1513                 gen_op_movl_A0_im(disp);
1514             }
1515         }
1516         /* XXX: index == 4 is always invalid */
1517         if (havesib && (index != 4 || scale != 0)) {
1518 #ifdef TARGET_X86_64
1519             if (s->aflag == 2) {
1520                 gen_op_addq_A0_reg_sN[scale][index]();
1521             } else 
1522 #endif
1523             {
1524                 gen_op_addl_A0_reg_sN[scale][index]();
1525             }
1526         }
1527         if (must_add_seg) {
1528             if (override < 0) {
1529                 if (base == R_EBP || base == R_ESP)
1530                     override = R_SS;
1531                 else
1532                     override = R_DS;
1533             }
1534 #ifdef TARGET_X86_64
1535             if (s->aflag == 2) {
1536                 gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1537             } else 
1538 #endif
1539             {
1540                 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1541             }
1542         }
1543     } else {
1544         switch (mod) {
1545         case 0:
1546             if (rm == 6) {
1547                 disp = lduw_code(s->pc);
1548                 s->pc += 2;
1549                 gen_op_movl_A0_im(disp);
1550                 rm = 0; /* avoid SS override */
1551                 goto no_rm;
1552             } else {
1553                 disp = 0;
1554             }
1555             break;
1556         case 1:
1557             disp = (int8_t)ldub_code(s->pc++);
1558             break;
1559         default:
1560         case 2:
1561             disp = lduw_code(s->pc);
1562             s->pc += 2;
1563             break;
1564         }
1565         switch(rm) {
1566         case 0:
1567             gen_op_movl_A0_reg[R_EBX]();
1568             gen_op_addl_A0_reg_sN[0][R_ESI]();
1569             break;
1570         case 1:
1571             gen_op_movl_A0_reg[R_EBX]();
1572             gen_op_addl_A0_reg_sN[0][R_EDI]();
1573             break;
1574         case 2:
1575             gen_op_movl_A0_reg[R_EBP]();
1576             gen_op_addl_A0_reg_sN[0][R_ESI]();
1577             break;
1578         case 3:
1579             gen_op_movl_A0_reg[R_EBP]();
1580             gen_op_addl_A0_reg_sN[0][R_EDI]();
1581             break;
1582         case 4:
1583             gen_op_movl_A0_reg[R_ESI]();
1584             break;
1585         case 5:
1586             gen_op_movl_A0_reg[R_EDI]();
1587             break;
1588         case 6:
1589             gen_op_movl_A0_reg[R_EBP]();
1590             break;
1591         default:
1592         case 7:
1593             gen_op_movl_A0_reg[R_EBX]();
1594             break;
1595         }
1596         if (disp != 0)
1597             gen_op_addl_A0_im(disp);
1598         gen_op_andl_A0_ffff();
1599     no_rm:
1600         if (must_add_seg) {
1601             if (override < 0) {
1602                 if (rm == 2 || rm == 3 || rm == 6)
1603                     override = R_SS;
1604                 else
1605                     override = R_DS;
1606             }
1607             gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1608         }
1609     }
1610
1611     opreg = OR_A0;
1612     disp = 0;
1613     *reg_ptr = opreg;
1614     *offset_ptr = disp;
1615 }
1616
1617 /* used for LEA and MOV AX, mem */
1618 static void gen_add_A0_ds_seg(DisasContext *s)
1619 {
1620     int override, must_add_seg;
1621     must_add_seg = s->addseg;
1622     override = R_DS;
1623     if (s->override >= 0) {
1624         override = s->override;
1625         must_add_seg = 1;
1626     } else {
1627         override = R_DS;
1628     }
1629     if (must_add_seg) {
1630 #ifdef TARGET_X86_64
1631         if (CODE64(s)) {
1632             gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base));
1633         } else 
1634 #endif
1635         {
1636             gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1637         }
1638     }
1639 }
1640
1641 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1642    OR_TMP0 */
1643 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1644 {
1645     int mod, rm, opreg, disp;
1646
1647     mod = (modrm >> 6) & 3;
1648     rm = (modrm & 7) | REX_B(s);
1649     if (mod == 3) {
1650         if (is_store) {
1651             if (reg != OR_TMP0)
1652                 gen_op_mov_TN_reg[ot][0][reg]();
1653             gen_op_mov_reg_T0[ot][rm]();
1654         } else {
1655             gen_op_mov_TN_reg[ot][0][rm]();
1656             if (reg != OR_TMP0)
1657                 gen_op_mov_reg_T0[ot][reg]();
1658         }
1659     } else {
1660         gen_lea_modrm(s, modrm, &opreg, &disp);
1661         if (is_store) {
1662             if (reg != OR_TMP0)
1663                 gen_op_mov_TN_reg[ot][0][reg]();
1664             gen_op_st_T0_A0[ot + s->mem_index]();
1665         } else {
1666             gen_op_ld_T0_A0[ot + s->mem_index]();
1667             if (reg != OR_TMP0)
1668                 gen_op_mov_reg_T0[ot][reg]();
1669         }
1670     }
1671 }
1672
1673 static inline uint32_t insn_get(DisasContext *s, int ot)
1674 {
1675     uint32_t ret;
1676
1677     switch(ot) {
1678     case OT_BYTE:
1679         ret = ldub_code(s->pc);
1680         s->pc++;
1681         break;
1682     case OT_WORD:
1683         ret = lduw_code(s->pc);
1684         s->pc += 2;
1685         break;
1686     default:
1687     case OT_LONG:
1688         ret = ldl_code(s->pc);
1689         s->pc += 4;
1690         break;
1691     }
1692     return ret;
1693 }
1694
1695 static inline int insn_const_size(unsigned int ot)
1696 {
1697     if (ot <= OT_LONG)
1698         return 1 << ot;
1699     else
1700         return 4;
1701 }
1702
1703 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
1704 {
1705     TranslationBlock *tb;
1706     target_ulong pc;
1707
1708     pc = s->cs_base + eip;
1709     tb = s->tb;
1710     /* NOTE: we handle the case where the TB spans two pages here */
1711     if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
1712         (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))  {
1713         /* jump to same page: we can use a direct jump */
1714         if (tb_num == 0)
1715             gen_op_goto_tb0(TBPARAM(tb));
1716         else
1717             gen_op_goto_tb1(TBPARAM(tb));
1718         gen_jmp_im(eip);
1719         gen_op_movl_T0_im((long)tb + tb_num);
1720         gen_op_exit_tb();
1721     } else {
1722         /* jump to another page: currently not optimized */
1723         gen_jmp_im(eip);
1724         gen_eob(s);
1725     }
1726 }
1727
1728 static inline void gen_jcc(DisasContext *s, int b, 
1729                            target_ulong val, target_ulong next_eip)
1730 {
1731     TranslationBlock *tb;
1732     int inv, jcc_op;
1733     GenOpFunc1 *func;
1734     target_ulong tmp;
1735     int l1, l2;
1736
1737     inv = b & 1;
1738     jcc_op = (b >> 1) & 7;
1739     
1740     if (s->jmp_opt) {
1741         switch(s->cc_op) {
1742             /* we optimize the cmp/jcc case */
1743         case CC_OP_SUBB:
1744         case CC_OP_SUBW:
1745         case CC_OP_SUBL:
1746         case CC_OP_SUBQ:
1747             func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1748             break;
1749             
1750             /* some jumps are easy to compute */
1751         case CC_OP_ADDB:
1752         case CC_OP_ADDW:
1753         case CC_OP_ADDL:
1754         case CC_OP_ADDQ:
1755
1756         case CC_OP_ADCB:
1757         case CC_OP_ADCW:
1758         case CC_OP_ADCL:
1759         case CC_OP_ADCQ:
1760
1761         case CC_OP_SBBB:
1762         case CC_OP_SBBW:
1763         case CC_OP_SBBL:
1764         case CC_OP_SBBQ:
1765
1766         case CC_OP_LOGICB:
1767         case CC_OP_LOGICW:
1768         case CC_OP_LOGICL:
1769         case CC_OP_LOGICQ:
1770
1771         case CC_OP_INCB:
1772         case CC_OP_INCW:
1773         case CC_OP_INCL:
1774         case CC_OP_INCQ:
1775
1776         case CC_OP_DECB:
1777         case CC_OP_DECW:
1778         case CC_OP_DECL:
1779         case CC_OP_DECQ:
1780
1781         case CC_OP_SHLB:
1782         case CC_OP_SHLW:
1783         case CC_OP_SHLL:
1784         case CC_OP_SHLQ:
1785
1786         case CC_OP_SARB:
1787         case CC_OP_SARW:
1788         case CC_OP_SARL:
1789         case CC_OP_SARQ:
1790             switch(jcc_op) {
1791             case JCC_Z:
1792                 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1793                 break;
1794             case JCC_S:
1795                 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1796                 break;
1797             default:
1798                 func = NULL;
1799                 break;
1800             }
1801             break;
1802         default:
1803             func = NULL;
1804             break;
1805         }
1806
1807         if (s->cc_op != CC_OP_DYNAMIC) {
1808             gen_op_set_cc_op(s->cc_op);
1809             s->cc_op = CC_OP_DYNAMIC;
1810         }
1811
1812         if (!func) {
1813             gen_setcc_slow[jcc_op]();
1814             func = gen_op_jnz_T0_label;
1815         }
1816     
1817         if (inv) {
1818             tmp = val;
1819             val = next_eip;
1820             next_eip = tmp;
1821         }
1822         tb = s->tb;
1823
1824         l1 = gen_new_label();
1825         func(l1);
1826
1827         gen_goto_tb(s, 0, next_eip);
1828
1829         gen_set_label(l1);
1830         gen_goto_tb(s, 1, val);
1831
1832         s->is_jmp = 3;
1833     } else {
1834
1835         if (s->cc_op != CC_OP_DYNAMIC) {
1836             gen_op_set_cc_op(s->cc_op);
1837             s->cc_op = CC_OP_DYNAMIC;
1838         }
1839         gen_setcc_slow[jcc_op]();
1840         if (inv) {
1841             tmp = val;
1842             val = next_eip;
1843             next_eip = tmp;
1844         }
1845         l1 = gen_new_label();
1846         l2 = gen_new_label();
1847         gen_op_jnz_T0_label(l1);
1848         gen_jmp_im(next_eip);
1849         gen_op_jmp_label(l2);
1850         gen_set_label(l1);
1851         gen_jmp_im(val);
1852         gen_set_label(l2);
1853         gen_eob(s);
1854     }
1855 }
1856
1857 static void gen_setcc(DisasContext *s, int b)
1858 {
1859     int inv, jcc_op;
1860     GenOpFunc *func;
1861
1862     inv = b & 1;
1863     jcc_op = (b >> 1) & 7;
1864     switch(s->cc_op) {
1865         /* we optimize the cmp/jcc case */
1866     case CC_OP_SUBB:
1867     case CC_OP_SUBW:
1868     case CC_OP_SUBL:
1869     case CC_OP_SUBQ:
1870         func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1871         if (!func)
1872             goto slow_jcc;
1873         break;
1874         
1875         /* some jumps are easy to compute */
1876     case CC_OP_ADDB:
1877     case CC_OP_ADDW:
1878     case CC_OP_ADDL:
1879     case CC_OP_ADDQ:
1880
1881     case CC_OP_LOGICB:
1882     case CC_OP_LOGICW:
1883     case CC_OP_LOGICL:
1884     case CC_OP_LOGICQ:
1885
1886     case CC_OP_INCB:
1887     case CC_OP_INCW:
1888     case CC_OP_INCL:
1889     case CC_OP_INCQ:
1890
1891     case CC_OP_DECB:
1892     case CC_OP_DECW:
1893     case CC_OP_DECL:
1894     case CC_OP_DECQ:
1895
1896     case CC_OP_SHLB:
1897     case CC_OP_SHLW:
1898     case CC_OP_SHLL:
1899     case CC_OP_SHLQ:
1900         switch(jcc_op) {
1901         case JCC_Z:
1902             func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1903             break;
1904         case JCC_S:
1905             func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op];
1906             break;
1907         default:
1908             goto slow_jcc;
1909         }
1910         break;
1911     default:
1912     slow_jcc:
1913         if (s->cc_op != CC_OP_DYNAMIC)
1914             gen_op_set_cc_op(s->cc_op);
1915         func = gen_setcc_slow[jcc_op];
1916         break;
1917     }
1918     func();
1919     if (inv) {
1920         gen_op_xor_T0_1();
1921     }
1922 }
1923
1924 /* move T0 to seg_reg and compute if the CPU state may change. Never
1925    call this function with seg_reg == R_CS */
1926 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
1927 {
1928     if (s->pe && !s->vm86) {
1929         /* XXX: optimize by finding processor state dynamically */
1930         if (s->cc_op != CC_OP_DYNAMIC)
1931             gen_op_set_cc_op(s->cc_op);
1932         gen_jmp_im(cur_eip);
1933         gen_op_movl_seg_T0(seg_reg);
1934         /* abort translation because the addseg value may change or
1935            because ss32 may change. For R_SS, translation must always
1936            stop as a special handling must be done to disable hardware
1937            interrupts for the next instruction */
1938         if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
1939             s->is_jmp = 3;
1940     } else {
1941         gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1942         if (seg_reg == R_SS)
1943             s->is_jmp = 3;
1944     }
1945 }
1946
1947 static inline void gen_stack_update(DisasContext *s, int addend)
1948 {
1949 #ifdef TARGET_X86_64
1950     if (CODE64(s)) {
1951         if (addend == 8)
1952             gen_op_addq_ESP_8();
1953         else 
1954             gen_op_addq_ESP_im(addend);
1955     } else
1956 #endif
1957     if (s->ss32) {
1958         if (addend == 2)
1959             gen_op_addl_ESP_2();
1960         else if (addend == 4)
1961             gen_op_addl_ESP_4();
1962         else 
1963             gen_op_addl_ESP_im(addend);
1964     } else {
1965         if (addend == 2)
1966             gen_op_addw_ESP_2();
1967         else if (addend == 4)
1968             gen_op_addw_ESP_4();
1969         else
1970             gen_op_addw_ESP_im(addend);
1971     }
1972 }
1973
1974 /* generate a push. It depends on ss32, addseg and dflag */
1975 static void gen_push_T0(DisasContext *s)
1976 {
1977 #ifdef TARGET_X86_64
1978     if (CODE64(s)) {
1979         gen_op_movq_A0_reg[R_ESP]();
1980         if (s->dflag) {
1981             gen_op_subq_A0_8();
1982             gen_op_st_T0_A0[OT_QUAD + s->mem_index]();
1983         } else {
1984             gen_op_subq_A0_2();
1985             gen_op_st_T0_A0[OT_WORD + s->mem_index]();
1986         }
1987         gen_op_movq_ESP_A0();
1988     } else 
1989 #endif
1990     {
1991         gen_op_movl_A0_reg[R_ESP]();
1992         if (!s->dflag)
1993             gen_op_subl_A0_2();
1994         else
1995             gen_op_subl_A0_4();
1996         if (s->ss32) {
1997             if (s->addseg) {
1998                 gen_op_movl_T1_A0();
1999                 gen_op_addl_A0_SS();
2000             }
2001         } else {
2002             gen_op_andl_A0_ffff();
2003             gen_op_movl_T1_A0();
2004             gen_op_addl_A0_SS();
2005         }
2006         gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
2007         if (s->ss32 && !s->addseg)
2008             gen_op_movl_ESP_A0();
2009         else
2010             gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
2011     }
2012 }
2013
2014 /* generate a push. It depends on ss32, addseg and dflag */
2015 /* slower version for T1, only used for call Ev */
2016 static void gen_push_T1(DisasContext *s)
2017 {
2018 #ifdef TARGET_X86_64
2019     if (CODE64(s)) {
2020         gen_op_movq_A0_reg[R_ESP]();
2021         if (s->dflag) {
2022             gen_op_subq_A0_8();
2023             gen_op_st_T1_A0[OT_QUAD + s->mem_index]();
2024         } else {
2025             gen_op_subq_A0_2();
2026             gen_op_st_T0_A0[OT_WORD + s->mem_index]();
2027         }
2028         gen_op_movq_ESP_A0();
2029     } else 
2030 #endif
2031     {
2032         gen_op_movl_A0_reg[R_ESP]();
2033         if (!s->dflag)
2034             gen_op_subl_A0_2();
2035         else
2036             gen_op_subl_A0_4();
2037         if (s->ss32) {
2038             if (s->addseg) {
2039                 gen_op_addl_A0_SS();
2040             }
2041         } else {
2042             gen_op_andl_A0_ffff();
2043             gen_op_addl_A0_SS();
2044         }
2045         gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
2046         
2047         if (s->ss32 && !s->addseg)
2048             gen_op_movl_ESP_A0();
2049         else
2050             gen_stack_update(s, (-2) << s->dflag);
2051     }
2052 }
2053
2054 /* two step pop is necessary for precise exceptions */
2055 static void gen_pop_T0(DisasContext *s)
2056 {
2057 #ifdef TARGET_X86_64
2058     if (CODE64(s)) {
2059         gen_op_movq_A0_reg[R_ESP]();
2060         gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index]();
2061     } else 
2062 #endif
2063     {
2064         gen_op_movl_A0_reg[R_ESP]();
2065         if (s->ss32) {
2066             if (s->addseg)
2067                 gen_op_addl_A0_SS();
2068         } else {
2069             gen_op_andl_A0_ffff();
2070             gen_op_addl_A0_SS();
2071         }
2072         gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
2073     }
2074 }
2075
2076 static void gen_pop_update(DisasContext *s)
2077 {
2078 #ifdef TARGET_X86_64
2079     if (CODE64(s) && s->dflag) {
2080         gen_stack_update(s, 8);
2081     } else
2082 #endif
2083     {
2084         gen_stack_update(s, 2 << s->dflag);
2085     }
2086 }
2087
2088 static void gen_stack_A0(DisasContext *s)
2089 {
2090     gen_op_movl_A0_ESP();
2091     if (!s->ss32)
2092         gen_op_andl_A0_ffff();
2093     gen_op_movl_T1_A0();
2094     if (s->addseg)
2095         gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2096 }
2097
2098 /* NOTE: wrap around in 16 bit not fully handled */
2099 static void gen_pusha(DisasContext *s)
2100 {
2101     int i;
2102     gen_op_movl_A0_ESP();
2103     gen_op_addl_A0_im(-16 <<  s->dflag);
2104     if (!s->ss32)
2105         gen_op_andl_A0_ffff();
2106     gen_op_movl_T1_A0();
2107     if (s->addseg)
2108         gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2109     for(i = 0;i < 8; i++) {
2110         gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
2111         gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2112         gen_op_addl_A0_im(2 <<  s->dflag);
2113     }
2114     gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2115 }
2116
2117 /* NOTE: wrap around in 16 bit not fully handled */
2118 static void gen_popa(DisasContext *s)
2119 {
2120     int i;
2121     gen_op_movl_A0_ESP();
2122     if (!s->ss32)
2123         gen_op_andl_A0_ffff();
2124     gen_op_movl_T1_A0();
2125     gen_op_addl_T1_im(16 <<  s->dflag);
2126     if (s->addseg)
2127         gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2128     for(i = 0;i < 8; i++) {
2129         /* ESP is not reloaded */
2130         if (i != 3) {
2131             gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index]();
2132             gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
2133         }
2134         gen_op_addl_A0_im(2 <<  s->dflag);
2135     }
2136     gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2137 }
2138
2139 static void gen_enter(DisasContext *s, int esp_addend, int level)
2140 {
2141     int ot, opsize;
2142
2143     level &= 0x1f;
2144 #ifdef TARGET_X86_64
2145     if (CODE64(s)) {
2146         ot = s->dflag ? OT_QUAD : OT_WORD;
2147         opsize = 1 << ot;
2148         
2149         gen_op_movl_A0_ESP();
2150         gen_op_addq_A0_im(-opsize);
2151         gen_op_movl_T1_A0();
2152
2153         /* push bp */
2154         gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2155         gen_op_st_T0_A0[ot + s->mem_index]();
2156         if (level) {
2157             gen_op_enter64_level(level, (ot == OT_QUAD));
2158         }
2159         gen_op_mov_reg_T1[ot][R_EBP]();
2160         gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2161         gen_op_mov_reg_T1[OT_QUAD][R_ESP]();
2162     } else 
2163 #endif
2164     {
2165         ot = s->dflag + OT_WORD;
2166         opsize = 2 << s->dflag;
2167         
2168         gen_op_movl_A0_ESP();
2169         gen_op_addl_A0_im(-opsize);
2170         if (!s->ss32)
2171             gen_op_andl_A0_ffff();
2172         gen_op_movl_T1_A0();
2173         if (s->addseg)
2174             gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
2175         /* push bp */
2176         gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2177         gen_op_st_T0_A0[ot + s->mem_index]();
2178         if (level) {
2179             gen_op_enter_level(level, s->dflag);
2180         }
2181         gen_op_mov_reg_T1[ot][R_EBP]();
2182         gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
2183         gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP]();
2184     }
2185 }
2186
2187 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2188 {
2189     if (s->cc_op != CC_OP_DYNAMIC)
2190         gen_op_set_cc_op(s->cc_op);
2191     gen_jmp_im(cur_eip);
2192     gen_op_raise_exception(trapno);
2193     s->is_jmp = 3;
2194 }
2195
2196 /* an interrupt is different from an exception because of the
2197    priviledge checks */
2198 static void gen_interrupt(DisasContext *s, int intno, 
2199                           target_ulong cur_eip, target_ulong next_eip)
2200 {
2201     if (s->cc_op != CC_OP_DYNAMIC)
2202         gen_op_set_cc_op(s->cc_op);
2203     gen_jmp_im(cur_eip);
2204     gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
2205     s->is_jmp = 3;
2206 }
2207
2208 static void gen_debug(DisasContext *s, target_ulong cur_eip)
2209 {
2210     if (s->cc_op != CC_OP_DYNAMIC)
2211         gen_op_set_cc_op(s->cc_op);
2212     gen_jmp_im(cur_eip);
2213     gen_op_debug();
2214     s->is_jmp = 3;
2215 }
2216
2217 /* generate a generic end of block. Trace exception is also generated
2218    if needed */
2219 static void gen_eob(DisasContext *s)
2220 {
2221     if (s->cc_op != CC_OP_DYNAMIC)
2222         gen_op_set_cc_op(s->cc_op);
2223     if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
2224         gen_op_reset_inhibit_irq();
2225     }
2226     if (s->singlestep_enabled) {
2227         gen_op_debug();
2228     } else if (s->tf) {
2229         gen_op_raise_exception(EXCP01_SSTP);
2230     } else {
2231         gen_op_movl_T0_0();
2232         gen_op_exit_tb();
2233     }
2234     s->is_jmp = 3;
2235 }
2236
2237 /* generate a jump to eip. No segment change must happen before as a
2238    direct call to the next block may occur */
2239 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2240 {
2241     if (s->jmp_opt) {
2242         if (s->cc_op != CC_OP_DYNAMIC) {
2243             gen_op_set_cc_op(s->cc_op);
2244             s->cc_op = CC_OP_DYNAMIC;
2245         }
2246         gen_goto_tb(s, tb_num, eip);
2247         s->is_jmp = 3;
2248     } else {
2249         gen_jmp_im(eip);
2250         gen_eob(s);
2251     }
2252 }
2253
2254 static void gen_jmp(DisasContext *s, target_ulong eip)
2255 {
2256     gen_jmp_tb(s, eip, 0);
2257 }
2258
2259 static void gen_movtl_T0_im(target_ulong val)
2260 {
2261 #ifdef TARGET_X86_64    
2262     if ((int32_t)val == val) {
2263         gen_op_movl_T0_im(val);
2264     } else {
2265         gen_op_movq_T0_im64(val >> 32, val);
2266     }
2267 #else
2268     gen_op_movl_T0_im(val);
2269 #endif
2270 }
2271
2272 static void gen_movtl_T1_im(target_ulong val)
2273 {
2274 #ifdef TARGET_X86_64    
2275     if ((int32_t)val == val) {
2276         gen_op_movl_T1_im(val);
2277     } else {
2278         gen_op_movq_T1_im64(val >> 32, val);
2279     }
2280 #else
2281     gen_op_movl_T1_im(val);
2282 #endif
2283 }
2284
2285 static void gen_add_A0_im(DisasContext *s, int val)
2286 {
2287 #ifdef TARGET_X86_64
2288     if (CODE64(s))
2289         gen_op_addq_A0_im(val);
2290     else
2291 #endif
2292         gen_op_addl_A0_im(val);
2293 }
2294
2295 static GenOpFunc1 *gen_ldq_env_A0[3] = {
2296     gen_op_ldq_raw_env_A0,
2297 #ifndef CONFIG_USER_ONLY
2298     gen_op_ldq_kernel_env_A0,
2299     gen_op_ldq_user_env_A0,
2300 #endif
2301 };
2302
2303 static GenOpFunc1 *gen_stq_env_A0[3] = {
2304     gen_op_stq_raw_env_A0,
2305 #ifndef CONFIG_USER_ONLY
2306     gen_op_stq_kernel_env_A0,
2307     gen_op_stq_user_env_A0,
2308 #endif
2309 };
2310
2311 static GenOpFunc1 *gen_ldo_env_A0[3] = {
2312     gen_op_ldo_raw_env_A0,
2313 #ifndef CONFIG_USER_ONLY
2314     gen_op_ldo_kernel_env_A0,
2315     gen_op_ldo_user_env_A0,
2316 #endif
2317 };
2318
2319 static GenOpFunc1 *gen_sto_env_A0[3] = {
2320     gen_op_sto_raw_env_A0,
2321 #ifndef CONFIG_USER_ONLY
2322     gen_op_sto_kernel_env_A0,
2323     gen_op_sto_user_env_A0,
2324 #endif
2325 };
2326
2327 #define SSE_SPECIAL ((GenOpFunc2 *)1)
2328
2329 #define MMX_OP2(x) { gen_op_ ## x ## _mmx, gen_op_ ## x ## _xmm }
2330 #define SSE_FOP(x) { gen_op_ ## x ## ps, gen_op_ ## x ## pd, \
2331                      gen_op_ ## x ## ss, gen_op_ ## x ## sd, }
2332
2333 static GenOpFunc2 *sse_op_table1[256][4] = {
2334     /* pure SSE operations */
2335     [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2336     [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2337     [0x12] = { SSE_SPECIAL, SSE_SPECIAL },  /* movlps, movlpd */
2338     [0x13] = { SSE_SPECIAL, SSE_SPECIAL },  /* movlps, movlpd */
2339     [0x14] = { gen_op_punpckldq_xmm, gen_op_punpcklqdq_xmm },
2340     [0x15] = { gen_op_punpckhdq_xmm, gen_op_punpckhqdq_xmm },
2341     [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd, movshdup */
2342     [0x17] = { SSE_SPECIAL, SSE_SPECIAL },  /* movhps, movhpd */
2343
2344     [0x28] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
2345     [0x29] = { SSE_SPECIAL, SSE_SPECIAL },  /* movaps, movapd */
2346     [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
2347     [0x2b] = { SSE_SPECIAL, SSE_SPECIAL },  /* movntps, movntpd */
2348     [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2349     [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
2350     [0x2e] = { gen_op_ucomiss, gen_op_ucomisd },
2351     [0x2f] = { gen_op_comiss, gen_op_comisd },
2352     [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2353     [0x51] = SSE_FOP(sqrt),
2354     [0x52] = { gen_op_rsqrtps, NULL, gen_op_rsqrtss, NULL },
2355     [0x53] = { gen_op_rcpps, NULL, gen_op_rcpss, NULL },
2356     [0x54] = { gen_op_pand_xmm, gen_op_pand_xmm }, /* andps, andpd */
2357     [0x55] = { gen_op_pandn_xmm, gen_op_pandn_xmm }, /* andnps, andnpd */
2358     [0x56] = { gen_op_por_xmm, gen_op_por_xmm }, /* orps, orpd */
2359     [0x57] = { gen_op_pxor_xmm, gen_op_pxor_xmm }, /* xorps, xorpd */
2360     [0x58] = SSE_FOP(add),
2361     [0x59] = SSE_FOP(mul),
2362     [0x5a] = { gen_op_cvtps2pd, gen_op_cvtpd2ps, 
2363                gen_op_cvtss2sd, gen_op_cvtsd2ss },
2364     [0x5b] = { gen_op_cvtdq2ps, gen_op_cvtps2dq, gen_op_cvttps2dq },
2365     [0x5c] = SSE_FOP(sub),
2366     [0x5d] = SSE_FOP(min),
2367     [0x5e] = SSE_FOP(div),
2368     [0x5f] = SSE_FOP(max),
2369
2370     [0xc2] = SSE_FOP(cmpeq),
2371     [0xc6] = { (GenOpFunc2 *)gen_op_shufps, (GenOpFunc2 *)gen_op_shufpd },
2372
2373     /* MMX ops and their SSE extensions */
2374     [0x60] = MMX_OP2(punpcklbw),
2375     [0x61] = MMX_OP2(punpcklwd),
2376     [0x62] = MMX_OP2(punpckldq),
2377     [0x63] = MMX_OP2(packsswb),
2378     [0x64] = MMX_OP2(pcmpgtb),
2379     [0x65] = MMX_OP2(pcmpgtw),
2380     [0x66] = MMX_OP2(pcmpgtl),
2381     [0x67] = MMX_OP2(packuswb),
2382     [0x68] = MMX_OP2(punpckhbw),
2383     [0x69] = MMX_OP2(punpckhwd),
2384     [0x6a] = MMX_OP2(punpckhdq),
2385     [0x6b] = MMX_OP2(packssdw),
2386     [0x6c] = { NULL, gen_op_punpcklqdq_xmm },
2387     [0x6d] = { NULL, gen_op_punpckhqdq_xmm },
2388     [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2389     [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
2390     [0x70] = { (GenOpFunc2 *)gen_op_pshufw_mmx, 
2391                (GenOpFunc2 *)gen_op_pshufd_xmm, 
2392                (GenOpFunc2 *)gen_op_pshufhw_xmm, 
2393                (GenOpFunc2 *)gen_op_pshuflw_xmm },
2394     [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2395     [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2396     [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2397     [0x74] = MMX_OP2(pcmpeqb),
2398     [0x75] = MMX_OP2(pcmpeqw),
2399     [0x76] = MMX_OP2(pcmpeql),
2400     [0x77] = { SSE_SPECIAL }, /* emms */
2401     [0x7c] = { NULL, gen_op_haddpd, NULL, gen_op_haddps },
2402     [0x7d] = { NULL, gen_op_hsubpd, NULL, gen_op_hsubps },
2403     [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2404     [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2405     [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2406     [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
2407     [0xd0] = { NULL, gen_op_addsubpd, NULL, gen_op_addsubps },
2408     [0xd1] = MMX_OP2(psrlw),
2409     [0xd2] = MMX_OP2(psrld),
2410     [0xd3] = MMX_OP2(psrlq),
2411     [0xd4] = MMX_OP2(paddq),
2412     [0xd5] = MMX_OP2(pmullw),
2413     [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2414     [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2415     [0xd8] = MMX_OP2(psubusb),
2416     [0xd9] = MMX_OP2(psubusw),
2417     [0xda] = MMX_OP2(pminub),
2418     [0xdb] = MMX_OP2(pand),
2419     [0xdc] = MMX_OP2(paddusb),
2420     [0xdd] = MMX_OP2(paddusw),
2421     [0xde] = MMX_OP2(pmaxub),
2422     [0xdf] = MMX_OP2(pandn),
2423     [0xe0] = MMX_OP2(pavgb),
2424     [0xe1] = MMX_OP2(psraw),
2425     [0xe2] = MMX_OP2(psrad),
2426     [0xe3] = MMX_OP2(pavgw),
2427     [0xe4] = MMX_OP2(pmulhuw),
2428     [0xe5] = MMX_OP2(pmulhw),
2429     [0xe6] = { NULL, gen_op_cvttpd2dq, gen_op_cvtdq2pd, gen_op_cvtpd2dq },
2430     [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
2431     [0xe8] = MMX_OP2(psubsb),
2432     [0xe9] = MMX_OP2(psubsw),
2433     [0xea] = MMX_OP2(pminsw),
2434     [0xeb] = MMX_OP2(por),
2435     [0xec] = MMX_OP2(paddsb),
2436     [0xed] = MMX_OP2(paddsw),
2437     [0xee] = MMX_OP2(pmaxsw),
2438     [0xef] = MMX_OP2(pxor),
2439     [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu (PNI) */
2440     [0xf1] = MMX_OP2(psllw),
2441     [0xf2] = MMX_OP2(pslld),
2442     [0xf3] = MMX_OP2(psllq),
2443     [0xf4] = MMX_OP2(pmuludq),
2444     [0xf5] = MMX_OP2(pmaddwd),
2445     [0xf6] = MMX_OP2(psadbw),
2446     [0xf7] = MMX_OP2(maskmov),
2447     [0xf8] = MMX_OP2(psubb),
2448     [0xf9] = MMX_OP2(psubw),
2449     [0xfa] = MMX_OP2(psubl),
2450     [0xfb] = MMX_OP2(psubq),
2451     [0xfc] = MMX_OP2(paddb),
2452     [0xfd] = MMX_OP2(paddw),
2453     [0xfe] = MMX_OP2(paddl),
2454 };
2455
2456 static GenOpFunc2 *sse_op_table2[3 * 8][2] = {
2457     [0 + 2] = MMX_OP2(psrlw),
2458     [0 + 4] = MMX_OP2(psraw),
2459     [0 + 6] = MMX_OP2(psllw),
2460     [8 + 2] = MMX_OP2(psrld),
2461     [8 + 4] = MMX_OP2(psrad),
2462     [8 + 6] = MMX_OP2(pslld),
2463     [16 + 2] = MMX_OP2(psrlq),
2464     [16 + 3] = { NULL, gen_op_psrldq_xmm },
2465     [16 + 6] = MMX_OP2(psllq),
2466     [16 + 7] = { NULL, gen_op_pslldq_xmm },
2467 };
2468
2469 static GenOpFunc1 *sse_op_table3[4 * 3] = {
2470     gen_op_cvtsi2ss,
2471     gen_op_cvtsi2sd,
2472     X86_64_ONLY(gen_op_cvtsq2ss),
2473     X86_64_ONLY(gen_op_cvtsq2sd),
2474     
2475     gen_op_cvttss2si,
2476     gen_op_cvttsd2si,
2477     X86_64_ONLY(gen_op_cvttss2sq),
2478     X86_64_ONLY(gen_op_cvttsd2sq),
2479
2480     gen_op_cvtss2si,
2481     gen_op_cvtsd2si,
2482     X86_64_ONLY(gen_op_cvtss2sq),
2483     X86_64_ONLY(gen_op_cvtsd2sq),
2484 };
2485     
2486 static GenOpFunc2 *sse_op_table4[8][4] = {
2487     SSE_FOP(cmpeq),
2488     SSE_FOP(cmplt),
2489     SSE_FOP(cmple),
2490     SSE_FOP(cmpunord),
2491     SSE_FOP(cmpneq),
2492     SSE_FOP(cmpnlt),
2493     SSE_FOP(cmpnle),
2494     SSE_FOP(cmpord),
2495 };
2496     
2497 static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
2498 {
2499     int b1, op1_offset, op2_offset, is_xmm, val, ot;
2500     int modrm, mod, rm, reg, reg_addr, offset_addr;
2501     GenOpFunc2 *sse_op2;
2502     GenOpFunc3 *sse_op3;
2503
2504     b &= 0xff;
2505     if (s->prefix & PREFIX_DATA) 
2506         b1 = 1;
2507     else if (s->prefix & PREFIX_REPZ) 
2508         b1 = 2;
2509     else if (s->prefix & PREFIX_REPNZ) 
2510         b1 = 3;
2511     else
2512         b1 = 0;
2513     sse_op2 = sse_op_table1[b][b1];
2514     if (!sse_op2) 
2515         goto illegal_op;
2516     if (b <= 0x5f || b == 0xc6 || b == 0xc2) {
2517         is_xmm = 1;
2518     } else {
2519         if (b1 == 0) {
2520             /* MMX case */
2521             is_xmm = 0;
2522         } else {
2523             is_xmm = 1;
2524         }
2525     }
2526     /* simple MMX/SSE operation */
2527     if (s->flags & HF_TS_MASK) {
2528         gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2529         return;
2530     }
2531     if (s->flags & HF_EM_MASK) {
2532     illegal_op:
2533         gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
2534         return;
2535     }
2536     if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
2537         goto illegal_op;
2538     if (b == 0x77) {
2539         /* emms */
2540         gen_op_emms();
2541         return;
2542     }
2543     /* prepare MMX state (XXX: optimize by storing fptt and fptags in
2544        the static cpu state) */
2545     if (!is_xmm) {
2546         gen_op_enter_mmx();
2547     }
2548
2549     modrm = ldub_code(s->pc++);
2550     reg = ((modrm >> 3) & 7);
2551     if (is_xmm)
2552         reg |= rex_r;
2553     mod = (modrm >> 6) & 3;
2554     if (sse_op2 == SSE_SPECIAL) {
2555         b |= (b1 << 8);
2556         switch(b) {
2557         case 0x0e7: /* movntq */
2558             if (mod == 3) 
2559                 goto illegal_op;
2560             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2561             gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2562             break;
2563         case 0x1e7: /* movntdq */
2564         case 0x02b: /* movntps */
2565         case 0x12b: /* movntps */
2566         case 0x2f0: /* lddqu */
2567             if (mod == 3) 
2568                 goto illegal_op;
2569             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2570             gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2571             break;
2572         case 0x6e: /* movd mm, ea */
2573             gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2574             gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2575             break;
2576         case 0x16e: /* movd xmm, ea */
2577             gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
2578             gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2579             break;
2580         case 0x6f: /* movq mm, ea */
2581             if (mod != 3) {
2582                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2583                 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2584             } else {
2585                 rm = (modrm & 7);
2586                 gen_op_movq(offsetof(CPUX86State,fpregs[reg].mmx),
2587                             offsetof(CPUX86State,fpregs[rm].mmx));
2588             }
2589             break;
2590         case 0x010: /* movups */
2591         case 0x110: /* movupd */
2592         case 0x028: /* movaps */
2593         case 0x128: /* movapd */
2594         case 0x16f: /* movdqa xmm, ea */
2595         case 0x26f: /* movdqu xmm, ea */
2596             if (mod != 3) {
2597                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2598                 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2599             } else {
2600                 rm = (modrm & 7) | REX_B(s);
2601                 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
2602                             offsetof(CPUX86State,xmm_regs[rm]));
2603             }
2604             break;
2605         case 0x210: /* movss xmm, ea */
2606             if (mod != 3) {
2607                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2608                 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2609                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2610                 gen_op_movl_T0_0();
2611                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2612                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2613                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2614             } else {
2615                 rm = (modrm & 7) | REX_B(s);
2616                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2617                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
2618             }
2619             break;
2620         case 0x310: /* movsd xmm, ea */
2621             if (mod != 3) {
2622                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2623                 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2624                 gen_op_movl_T0_0();
2625                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
2626                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2627             } else {
2628                 rm = (modrm & 7) | REX_B(s);
2629                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2630                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2631             }
2632             break;
2633         case 0x012: /* movlps */
2634         case 0x112: /* movlpd */
2635             if (mod != 3) {
2636                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2637                 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2638             } else {
2639                 /* movhlps */
2640                 rm = (modrm & 7) | REX_B(s);
2641                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2642                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2643             }
2644             break;
2645         case 0x016: /* movhps */
2646         case 0x116: /* movhpd */
2647             if (mod != 3) {
2648                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2649                 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2650             } else {
2651                 /* movlhps */
2652                 rm = (modrm & 7) | REX_B(s);
2653                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
2654                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2655             }
2656             break;
2657         case 0x216: /* movshdup */
2658             if (mod != 3) {
2659                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2660                 gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2661             } else {
2662                 rm = (modrm & 7) | REX_B(s);
2663                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
2664                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
2665                 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
2666                             offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
2667             }
2668             gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
2669                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
2670             gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
2671                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
2672             break;
2673         case 0x7e: /* movd ea, mm */
2674             gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
2675             gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2676             break;
2677         case 0x17e: /* movd ea, xmm */
2678             gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
2679             gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
2680             break;
2681         case 0x27e: /* movq xmm, ea */
2682             if (mod != 3) {
2683                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2684                 gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2685             } else {
2686                 rm = (modrm & 7) | REX_B(s);
2687                 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
2688                             offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
2689             }
2690             gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2691             break;
2692         case 0x7f: /* movq ea, mm */
2693             if (mod != 3) {
2694                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2695                 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,fpregs[reg].mmx));
2696             } else {
2697                 rm = (modrm & 7);
2698                 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2699                             offsetof(CPUX86State,fpregs[reg].mmx));
2700             }
2701             break;
2702         case 0x011: /* movups */
2703         case 0x111: /* movupd */
2704         case 0x029: /* movaps */
2705         case 0x129: /* movapd */
2706         case 0x17f: /* movdqa ea, xmm */
2707         case 0x27f: /* movdqu ea, xmm */
2708             if (mod != 3) {
2709                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2710                 gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
2711             } else {
2712                 rm = (modrm & 7) | REX_B(s);
2713                 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
2714                             offsetof(CPUX86State,xmm_regs[reg]));
2715             }
2716             break;
2717         case 0x211: /* movss ea, xmm */
2718             if (mod != 3) {
2719                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2720                 gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2721                 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
2722             } else {
2723                 rm = (modrm & 7) | REX_B(s);
2724                 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
2725                             offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
2726             }
2727             break;
2728         case 0x311: /* movsd ea, xmm */
2729             if (mod != 3) {
2730                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2731                 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2732             } else {
2733                 rm = (modrm & 7) | REX_B(s);
2734                 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2735                             offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2736             }
2737             break;
2738         case 0x013: /* movlps */
2739         case 0x113: /* movlpd */
2740             if (mod != 3) {
2741                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2742                 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2743             } else {
2744                 goto illegal_op;
2745             }
2746             break;
2747         case 0x017: /* movhps */
2748         case 0x117: /* movhpd */
2749             if (mod != 3) {
2750                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2751                 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
2752             } else {
2753                 goto illegal_op;
2754             }
2755             break;
2756         case 0x71: /* shift mm, im */
2757         case 0x72:
2758         case 0x73:
2759         case 0x171: /* shift xmm, im */
2760         case 0x172:
2761         case 0x173:
2762             val = ldub_code(s->pc++);
2763             if (is_xmm) {
2764                 gen_op_movl_T0_im(val);
2765                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2766                 gen_op_movl_T0_0();
2767                 gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(1)));
2768                 op1_offset = offsetof(CPUX86State,xmm_t0);
2769             } else {
2770                 gen_op_movl_T0_im(val);
2771                 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(0)));
2772                 gen_op_movl_T0_0();
2773                 gen_op_movl_env_T0(offsetof(CPUX86State,mmx_t0.MMX_L(1)));
2774                 op1_offset = offsetof(CPUX86State,mmx_t0);
2775             }
2776             sse_op2 = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1];
2777             if (!sse_op2)
2778                 goto illegal_op;
2779             if (is_xmm) {
2780                 rm = (modrm & 7) | REX_B(s);
2781                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2782             } else {
2783                 rm = (modrm & 7);
2784                 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2785             }
2786             sse_op2(op2_offset, op1_offset);
2787             break;
2788         case 0x050: /* movmskps */
2789             rm = (modrm & 7) | REX_B(s);
2790             gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm]));
2791             gen_op_mov_reg_T0[OT_LONG][reg]();
2792             break;
2793         case 0x150: /* movmskpd */
2794             rm = (modrm & 7) | REX_B(s);
2795             gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm]));
2796             gen_op_mov_reg_T0[OT_LONG][reg]();
2797             break;
2798         case 0x02a: /* cvtpi2ps */
2799         case 0x12a: /* cvtpi2pd */
2800             gen_op_enter_mmx();
2801             if (mod != 3) {
2802                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2803                 op2_offset = offsetof(CPUX86State,mmx_t0);
2804                 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
2805             } else {
2806                 rm = (modrm & 7);
2807                 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2808             }
2809             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2810             switch(b >> 8) {
2811             case 0x0:
2812                 gen_op_cvtpi2ps(op1_offset, op2_offset);
2813                 break;
2814             default:
2815             case 0x1:
2816                 gen_op_cvtpi2pd(op1_offset, op2_offset);
2817                 break;
2818             }
2819             break;
2820         case 0x22a: /* cvtsi2ss */
2821         case 0x32a: /* cvtsi2sd */
2822             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
2823             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2824             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2825             sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2)](op1_offset);
2826             break;
2827         case 0x02c: /* cvttps2pi */
2828         case 0x12c: /* cvttpd2pi */
2829         case 0x02d: /* cvtps2pi */
2830         case 0x12d: /* cvtpd2pi */
2831             gen_op_enter_mmx();
2832             if (mod != 3) {
2833                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2834                 op2_offset = offsetof(CPUX86State,xmm_t0);
2835                 gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
2836             } else {
2837                 rm = (modrm & 7) | REX_B(s);
2838                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2839             }
2840             op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
2841             switch(b) {
2842             case 0x02c:
2843                 gen_op_cvttps2pi(op1_offset, op2_offset);
2844                 break;
2845             case 0x12c:
2846                 gen_op_cvttpd2pi(op1_offset, op2_offset);
2847                 break;
2848             case 0x02d:
2849                 gen_op_cvtps2pi(op1_offset, op2_offset);
2850                 break;
2851             case 0x12d:
2852                 gen_op_cvtpd2pi(op1_offset, op2_offset);
2853                 break;
2854             }
2855             break;
2856         case 0x22c: /* cvttss2si */
2857         case 0x32c: /* cvttsd2si */
2858         case 0x22d: /* cvtss2si */
2859         case 0x32d: /* cvtsd2si */
2860             ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
2861             if (mod != 3) {
2862                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2863                 if ((b >> 8) & 1) {
2864                     gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0)));
2865                 } else {
2866                     gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2867                     gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2868                 }
2869                 op2_offset = offsetof(CPUX86State,xmm_t0);
2870             } else {
2871                 rm = (modrm & 7) | REX_B(s);
2872                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2873             }
2874             sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 + 
2875                           (b & 1) * 4](op2_offset);
2876             gen_op_mov_reg_T0[ot][reg]();
2877             break;
2878         case 0xc4: /* pinsrw */
2879         case 0x1c4: 
2880             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2881             val = ldub_code(s->pc++);
2882             if (b1) {
2883                 val &= 7;
2884                 gen_op_pinsrw_xmm(offsetof(CPUX86State,xmm_regs[reg]), val);
2885             } else {
2886                 val &= 3;
2887                 gen_op_pinsrw_mmx(offsetof(CPUX86State,fpregs[reg].mmx), val);
2888             }
2889             break;
2890         case 0xc5: /* pextrw */
2891         case 0x1c5: 
2892             if (mod != 3)
2893                 goto illegal_op;
2894             val = ldub_code(s->pc++);
2895             if (b1) {
2896                 val &= 7;
2897                 rm = (modrm & 7) | REX_B(s);
2898                 gen_op_pextrw_xmm(offsetof(CPUX86State,xmm_regs[rm]), val);
2899             } else {
2900                 val &= 3;
2901                 rm = (modrm & 7);
2902                 gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val);
2903             }
2904             reg = ((modrm >> 3) & 7) | rex_r;
2905             gen_op_mov_reg_T0[OT_LONG][reg]();
2906             break;
2907         case 0x1d6: /* movq ea, xmm */
2908             if (mod != 3) {
2909                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2910                 gen_stq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2911             } else {
2912                 rm = (modrm & 7) | REX_B(s);
2913                 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2914                             offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2915                 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2916             }
2917             break;
2918         case 0x2d6: /* movq2dq */
2919             gen_op_enter_mmx();
2920             rm = (modrm & 7) | REX_B(s);
2921             gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
2922                         offsetof(CPUX86State,fpregs[reg & 7].mmx));
2923             gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
2924             break;
2925         case 0x3d6: /* movdq2q */
2926             gen_op_enter_mmx();
2927             rm = (modrm & 7);
2928             gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
2929                         offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
2930             break;
2931         case 0xd7: /* pmovmskb */
2932         case 0x1d7:
2933             if (mod != 3)
2934                 goto illegal_op;
2935             if (b1) {
2936                 rm = (modrm & 7) | REX_B(s);
2937                 gen_op_pmovmskb_xmm(offsetof(CPUX86State,xmm_regs[rm]));
2938             } else {
2939                 rm = (modrm & 7);
2940                 gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx));
2941             }
2942             reg = ((modrm >> 3) & 7) | rex_r;
2943             gen_op_mov_reg_T0[OT_LONG][reg]();
2944             break;
2945         default:
2946             goto illegal_op;
2947         }
2948     } else {
2949         /* generic MMX or SSE operation */
2950         if (b == 0xf7) {
2951             /* maskmov : we must prepare A0 */
2952             if (mod != 3) 
2953                 goto illegal_op;
2954 #ifdef TARGET_X86_64
2955             if (s->aflag == 2) {
2956                 gen_op_movq_A0_reg[R_EDI]();
2957             } else 
2958 #endif
2959             {
2960                 gen_op_movl_A0_reg[R_EDI]();
2961                 if (s->aflag == 0)
2962                     gen_op_andl_A0_ffff();
2963             }
2964             gen_add_A0_ds_seg(s);
2965         }
2966         if (is_xmm) {
2967             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
2968             if (mod != 3) {
2969                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2970                 op2_offset = offsetof(CPUX86State,xmm_t0);
2971                 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f) ||
2972                                 b == 0xc2)) {
2973                     /* specific case for SSE single instructions */
2974                     if (b1 == 2) {
2975                         /* 32 bit access */
2976                         gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
2977                         gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0)));
2978                     } else {
2979                         /* 64 bit access */
2980                         gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_D(0)));
2981                     }
2982                 } else {
2983                     gen_ldo_env_A0[s->mem_index >> 2](op2_offset);
2984                 }
2985             } else {
2986                 rm = (modrm & 7) | REX_B(s);
2987                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
2988             }
2989         } else {
2990             op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
2991             if (mod != 3) {
2992                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2993                 op2_offset = offsetof(CPUX86State,mmx_t0);
2994                 gen_ldq_env_A0[s->mem_index >> 2](op2_offset);
2995             } else {
2996                 rm = (modrm & 7);
2997                 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
2998             }
2999         }
3000         switch(b) {
3001         case 0x70: /* pshufx insn */
3002         case 0xc6: /* pshufx insn */
3003             val = ldub_code(s->pc++);
3004             sse_op3 = (GenOpFunc3 *)sse_op2;
3005             sse_op3(op1_offset, op2_offset, val);
3006             break;
3007         case 0xc2:
3008             /* compare insns */
3009             val = ldub_code(s->pc++);
3010             if (val >= 8)
3011                 goto illegal_op;
3012             sse_op2 = sse_op_table4[val][b1];
3013             sse_op2(op1_offset, op2_offset);
3014             break;
3015         default:
3016             sse_op2(op1_offset, op2_offset);
3017             break;
3018         }
3019         if (b == 0x2e || b == 0x2f) {
3020             s->cc_op = CC_OP_EFLAGS;
3021         }
3022     }
3023 }
3024
3025
3026 /* convert one instruction. s->is_jmp is set if the translation must
3027    be stopped. Return the next pc value */
3028 static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
3029 {
3030     int b, prefixes, aflag, dflag;
3031     int shift, ot;
3032     int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
3033     target_ulong next_eip, tval;
3034     int rex_w, rex_r;
3035
3036     s->pc = pc_start;
3037     prefixes = 0;
3038     aflag = s->code32;
3039     dflag = s->code32;
3040     s->override = -1;
3041     rex_w = -1;
3042     rex_r = 0;
3043 #ifdef TARGET_X86_64
3044     s->rex_x = 0;
3045     s->rex_b = 0;
3046     x86_64_hregs = 0; 
3047 #endif
3048     s->rip_offset = 0; /* for relative ip address */
3049  next_byte:
3050     b = ldub_code(s->pc);
3051     s->pc++;
3052     /* check prefixes */
3053 #ifdef TARGET_X86_64
3054     if (CODE64(s)) {
3055         switch (b) {
3056         case 0xf3:
3057             prefixes |= PREFIX_REPZ;
3058             goto next_byte;
3059         case 0xf2:
3060             prefixes |= PREFIX_REPNZ;
3061             goto next_byte;
3062         case 0xf0:
3063             prefixes |= PREFIX_LOCK;
3064             goto next_byte;
3065         case 0x2e:
3066             s->override = R_CS;
3067             goto next_byte;
3068         case 0x36:
3069             s->override = R_SS;
3070             goto next_byte;
3071         case 0x3e:
3072             s->override = R_DS;
3073             goto next_byte;
3074         case 0x26:
3075             s->override = R_ES;
3076             goto next_byte;
3077         case 0x64:
3078             s->override = R_FS;
3079             goto next_byte;
3080         case 0x65:
3081             s->override = R_GS;
3082             goto next_byte;
3083         case 0x66:
3084             prefixes |= PREFIX_DATA;
3085             goto next_byte;
3086         case 0x67:
3087             prefixes |= PREFIX_ADR;
3088             goto next_byte;
3089         case 0x40 ... 0x4f:
3090             /* REX prefix */
3091             rex_w = (b >> 3) & 1;
3092             rex_r = (b & 0x4) << 1;
3093             s->rex_x = (b & 0x2) << 2;
3094             REX_B(s) = (b & 0x1) << 3;
3095             x86_64_hregs = 1; /* select uniform byte register addressing */
3096             goto next_byte;
3097         }
3098         if (rex_w == 1) {
3099             /* 0x66 is ignored if rex.w is set */
3100             dflag = 2;
3101         } else {
3102             if (prefixes & PREFIX_DATA)
3103                 dflag ^= 1;
3104         }
3105         if (!(prefixes & PREFIX_ADR))
3106             aflag = 2;
3107     } else 
3108 #endif
3109     {
3110         switch (b) {
3111         case 0xf3:
3112             prefixes |= PREFIX_REPZ;
3113             goto next_byte;
3114         case 0xf2:
3115             prefixes |= PREFIX_REPNZ;
3116             goto next_byte;
3117         case 0xf0:
3118             prefixes |= PREFIX_LOCK;
3119             goto next_byte;
3120         case 0x2e:
3121             s->override = R_CS;
3122             goto next_byte;
3123         case 0x36:
3124             s->override = R_SS;
3125             goto next_byte;
3126         case 0x3e:
3127             s->override = R_DS;
3128             goto next_byte;
3129         case 0x26:
3130             s->override = R_ES;
3131             goto next_byte;
3132         case 0x64:
3133             s->override = R_FS;
3134             goto next_byte;
3135         case 0x65:
3136             s->override = R_GS;
3137             goto next_byte;
3138         case 0x66:
3139             prefixes |= PREFIX_DATA;
3140             goto next_byte;
3141         case 0x67:
3142             prefixes |= PREFIX_ADR;
3143             goto next_byte;
3144         }
3145         if (prefixes & PREFIX_DATA)
3146             dflag ^= 1;
3147         if (prefixes & PREFIX_ADR)
3148             aflag ^= 1;
3149     }
3150
3151     s->prefix = prefixes;
3152     s->aflag = aflag;
3153     s->dflag = dflag;
3154
3155     /* lock generation */
3156     if (prefixes & PREFIX_LOCK)
3157         gen_op_lock();
3158
3159     /* now check op code */
3160  reswitch:
3161     switch(b) {
3162     case 0x0f:
3163         /**************************/
3164         /* extended op code */
3165         b = ldub_code(s->pc++) | 0x100;
3166         goto reswitch;
3167         
3168         /**************************/
3169         /* arith & logic */
3170     case 0x00 ... 0x05:
3171     case 0x08 ... 0x0d:
3172     case 0x10 ... 0x15:
3173     case 0x18 ... 0x1d:
3174     case 0x20 ... 0x25:
3175     case 0x28 ... 0x2d:
3176     case 0x30 ... 0x35:
3177     case 0x38 ... 0x3d:
3178         {
3179             int op, f, val;
3180             op = (b >> 3) & 7;
3181             f = (b >> 1) & 3;
3182
3183             if ((b & 1) == 0)
3184                 ot = OT_BYTE;
3185             else
3186                 ot = dflag + OT_WORD;
3187             
3188             switch(f) {
3189             case 0: /* OP Ev, Gv */
3190                 modrm = ldub_code(s->pc++);
3191                 reg = ((modrm >> 3) & 7) | rex_r;
3192                 mod = (modrm >> 6) & 3;
3193                 rm = (modrm & 7) | REX_B(s);
3194                 if (mod != 3) {
3195                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3196                     opreg = OR_TMP0;
3197                 } else if (op == OP_XORL && rm == reg) {
3198                 xor_zero:
3199                     /* xor reg, reg optimisation */
3200                     gen_op_movl_T0_0();
3201                     s->cc_op = CC_OP_LOGICB + ot;
3202                     gen_op_mov_reg_T0[ot][reg]();
3203                     gen_op_update1_cc();
3204                     break;
3205                 } else {
3206                     opreg = rm;
3207                 }
3208                 gen_op_mov_TN_reg[ot][1][reg]();
3209                 gen_op(s, op, ot, opreg);
3210                 break;
3211             case 1: /* OP Gv, Ev */
3212                 modrm = ldub_code(s->pc++);
3213                 mod = (modrm >> 6) & 3;
3214                 reg = ((modrm >> 3) & 7) | rex_r;
3215                 rm = (modrm & 7) | REX_B(s);
3216                 if (mod != 3) {
3217                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3218                     gen_op_ld_T1_A0[ot + s->mem_index]();
3219                 } else if (op == OP_XORL && rm == reg) {
3220                     goto xor_zero;
3221                 } else {
3222                     gen_op_mov_TN_reg[ot][1][rm]();
3223                 }
3224                 gen_op(s, op, ot, reg);
3225                 break;
3226             case 2: /* OP A, Iv */
3227                 val = insn_get(s, ot);
3228                 gen_op_movl_T1_im(val);
3229                 gen_op(s, op, ot, OR_EAX);
3230                 break;
3231             }
3232         }
3233         break;
3234
3235     case 0x80: /* GRP1 */
3236     case 0x81:
3237     case 0x82:
3238     case 0x83:
3239         {
3240             int val;
3241
3242             if ((b & 1) == 0)
3243                 ot = OT_BYTE;
3244             else
3245                 ot = dflag + OT_WORD;
3246             
3247             modrm = ldub_code(s->pc++);
3248             mod = (modrm >> 6) & 3;
3249             rm = (modrm & 7) | REX_B(s);
3250             op = (modrm >> 3) & 7;
3251             
3252             if (mod != 3) {
3253                 if (b == 0x83)
3254                     s->rip_offset = 1;
3255                 else
3256                     s->rip_offset = insn_const_size(ot);
3257                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3258                 opreg = OR_TMP0;
3259             } else {
3260                 opreg = rm;
3261             }
3262
3263             switch(b) {
3264             default:
3265             case 0x80:
3266             case 0x81:
3267             case 0x82:
3268                 val = insn_get(s, ot);
3269                 break;
3270             case 0x83:
3271                 val = (int8_t)insn_get(s, OT_BYTE);
3272                 break;
3273             }
3274             gen_op_movl_T1_im(val);
3275             gen_op(s, op, ot, opreg);
3276         }
3277         break;
3278
3279         /**************************/
3280         /* inc, dec, and other misc arith */
3281     case 0x40 ... 0x47: /* inc Gv */
3282         ot = dflag ? OT_LONG : OT_WORD;
3283         gen_inc(s, ot, OR_EAX + (b & 7), 1);
3284         break;
3285     case 0x48 ... 0x4f: /* dec Gv */
3286         ot = dflag ? OT_LONG : OT_WORD;
3287         gen_inc(s, ot, OR_EAX + (b & 7), -1);
3288         break;
3289     case 0xf6: /* GRP3 */
3290     case 0xf7:
3291         if ((b & 1) == 0)
3292             ot = OT_BYTE;
3293         else
3294             ot = dflag + OT_WORD;
3295
3296         modrm = ldub_code(s->pc++);
3297         mod = (modrm >> 6) & 3;
3298         rm = (modrm & 7) | REX_B(s);
3299         op = (modrm >> 3) & 7;
3300         if (mod != 3) {
3301             if (op == 0)
3302                 s->rip_offset = insn_const_size(ot);
3303             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3304             gen_op_ld_T0_A0[ot + s->mem_index]();
3305         } else {
3306             gen_op_mov_TN_reg[ot][0][rm]();
3307         }
3308
3309         switch(op) {
3310         case 0: /* test */
3311             val = insn_get(s, ot);
3312             gen_op_movl_T1_im(val);
3313             gen_op_testl_T0_T1_cc();
3314             s->cc_op = CC_OP_LOGICB + ot;
3315             break;
3316         case 2: /* not */
3317             gen_op_notl_T0();
3318             if (mod != 3) {
3319                 gen_op_st_T0_A0[ot + s->mem_index]();
3320             } else {
3321                 gen_op_mov_reg_T0[ot][rm]();
3322             }
3323             break;
3324         case 3: /* neg */
3325             gen_op_negl_T0();
3326             if (mod != 3) {
3327                 gen_op_st_T0_A0[ot + s->mem_index]();
3328             } else {
3329                 gen_op_mov_reg_T0[ot][rm]();
3330             }
3331             gen_op_update_neg_cc();
3332             s->cc_op = CC_OP_SUBB + ot;
3333             break;
3334         case 4: /* mul */
3335             switch(ot) {
3336             case OT_BYTE:
3337                 gen_op_mulb_AL_T0();
3338                 s->cc_op = CC_OP_MULB;
3339                 break;
3340             case OT_WORD:
3341                 gen_op_mulw_AX_T0();
3342                 s->cc_op = CC_OP_MULW;
3343                 break;
3344             default:
3345             case OT_LONG:
3346                 gen_op_mull_EAX_T0();
3347                 s->cc_op = CC_OP_MULL;
3348                 break;
3349 #ifdef TARGET_X86_64
3350             case OT_QUAD:
3351                 gen_op_mulq_EAX_T0();
3352                 s->cc_op = CC_OP_MULQ;
3353                 break;
3354 #endif
3355             }
3356             break;
3357         case 5: /* imul */
3358             switch(ot) {
3359             case OT_BYTE:
3360                 gen_op_imulb_AL_T0();
3361                 s->cc_op = CC_OP_MULB;
3362                 break;
3363             case OT_WORD:
3364                 gen_op_imulw_AX_T0();
3365                 s->cc_op = CC_OP_MULW;
3366                 break;
3367             default:
3368             case OT_LONG:
3369                 gen_op_imull_EAX_T0();
3370                 s->cc_op = CC_OP_MULL;
3371                 break;
3372 #ifdef TARGET_X86_64
3373             case OT_QUAD:
3374                 gen_op_imulq_EAX_T0();
3375                 s->cc_op = CC_OP_MULQ;
3376                 break;
3377 #endif
3378             }
3379             break;
3380         case 6: /* div */
3381             switch(ot) {
3382             case OT_BYTE:
3383                 gen_jmp_im(pc_start - s->cs_base);
3384                 gen_op_divb_AL_T0();
3385                 break;
3386             case OT_WORD:
3387                 gen_jmp_im(pc_start - s->cs_base);
3388                 gen_op_divw_AX_T0();
3389                 break;
3390             default:
3391             case OT_LONG:
3392                 gen_jmp_im(pc_start - s->cs_base);
3393                 gen_op_divl_EAX_T0();
3394                 break;
3395 #ifdef TARGET_X86_64
3396             case OT_QUAD:
3397                 gen_jmp_im(pc_start - s->cs_base);
3398                 gen_op_divq_EAX_T0();
3399                 break;
3400 #endif
3401             }
3402             break;
3403         case 7: /* idiv */
3404             switch(ot) {
3405             case OT_BYTE:
3406                 gen_jmp_im(pc_start - s->cs_base);
3407                 gen_op_idivb_AL_T0();
3408                 break;
3409             case OT_WORD:
3410                 gen_jmp_im(pc_start - s->cs_base);
3411                 gen_op_idivw_AX_T0();
3412                 break;
3413             default:
3414             case OT_LONG:
3415                 gen_jmp_im(pc_start - s->cs_base);
3416                 gen_op_idivl_EAX_T0();
3417                 break;
3418 #ifdef TARGET_X86_64
3419             case OT_QUAD:
3420                 gen_jmp_im(pc_start - s->cs_base);
3421                 gen_op_idivq_EAX_T0();
3422                 break;
3423 #endif
3424             }
3425             break;
3426         default:
3427             goto illegal_op;
3428         }
3429         break;
3430
3431     case 0xfe: /* GRP4 */
3432     case 0xff: /* GRP5 */
3433         if ((b & 1) == 0)
3434             ot = OT_BYTE;
3435         else
3436             ot = dflag + OT_WORD;
3437
3438         modrm = ldub_code(s->pc++);
3439         mod = (modrm >> 6) & 3;
3440         rm = (modrm & 7) | REX_B(s);
3441         op = (modrm >> 3) & 7;
3442         if (op >= 2 && b == 0xfe) {
3443             goto illegal_op;
3444         }
3445         if (CODE64(s)) {
3446             if (op == 2 || op == 4) {
3447                 /* operand size for jumps is 64 bit */
3448                 ot = OT_QUAD;
3449             } else if (op == 3 || op == 5) {
3450                 /* for call calls, the operand is 16 or 32 bit, even
3451                    in long mode */
3452                 ot = dflag ? OT_LONG : OT_WORD;
3453             } else if (op == 6) {
3454                 /* default push size is 64 bit */
3455                 ot = dflag ? OT_QUAD : OT_WORD;
3456             }
3457         }
3458         if (mod != 3) {
3459             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3460             if (op >= 2 && op != 3 && op != 5)
3461                 gen_op_ld_T0_A0[ot + s->mem_index]();
3462         } else {
3463             gen_op_mov_TN_reg[ot][0][rm]();
3464         }
3465
3466         switch(op) {
3467         case 0: /* inc Ev */
3468             if (mod != 3)
3469                 opreg = OR_TMP0;
3470             else
3471                 opreg = rm;
3472             gen_inc(s, ot, opreg, 1);
3473             break;
3474         case 1: /* dec Ev */
3475             if (mod != 3)
3476                 opreg = OR_TMP0;
3477             else
3478                 opreg = rm;
3479             gen_inc(s, ot, opreg, -1);
3480             break;
3481         case 2: /* call Ev */
3482             /* XXX: optimize if memory (no 'and' is necessary) */
3483             if (s->dflag == 0)
3484                 gen_op_andl_T0_ffff();
3485             next_eip = s->pc - s->cs_base;
3486             gen_movtl_T1_im(next_eip);
3487             gen_push_T1(s);
3488             gen_op_jmp_T0();
3489             gen_eob(s);
3490             break;
3491         case 3: /* lcall Ev */
3492             gen_op_ld_T1_A0[ot + s->mem_index]();
3493             gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3494             gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3495         do_lcall:
3496             if (s->pe && !s->vm86) {
3497                 if (s->cc_op != CC_OP_DYNAMIC)
3498                     gen_op_set_cc_op(s->cc_op);
3499                 gen_jmp_im(pc_start - s->cs_base);
3500                 gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start);
3501             } else {
3502                 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
3503             }
3504             gen_eob(s);
3505             break;
3506         case 4: /* jmp Ev */
3507             if (s->dflag == 0)
3508                 gen_op_andl_T0_ffff();
3509             gen_op_jmp_T0();
3510             gen_eob(s);
3511             break;
3512         case 5: /* ljmp Ev */
3513             gen_op_ld_T1_A0[ot + s->mem_index]();
3514             gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
3515             gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
3516         do_ljmp:
3517             if (s->pe && !s->vm86) {
3518                 if (s->cc_op != CC_OP_DYNAMIC)
3519                     gen_op_set_cc_op(s->cc_op);
3520                 gen_jmp_im(pc_start - s->cs_base);
3521                 gen_op_ljmp_protected_T0_T1(s->pc - pc_start);
3522             } else {
3523                 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3524                 gen_op_movl_T0_T1();
3525                 gen_op_jmp_T0();
3526             }
3527             gen_eob(s);
3528             break;
3529         case 6: /* push Ev */
3530             gen_push_T0(s);
3531             break;
3532         default:
3533             goto illegal_op;
3534         }
3535         break;
3536
3537     case 0x84: /* test Ev, Gv */
3538     case 0x85: 
3539         if ((b & 1) == 0)
3540             ot = OT_BYTE;
3541         else
3542             ot = dflag + OT_WORD;
3543
3544         modrm = ldub_code(s->pc++);
3545         mod = (modrm >> 6) & 3;
3546         rm = (modrm & 7) | REX_B(s);
3547         reg = ((modrm >> 3) & 7) | rex_r;
3548         
3549         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3550         gen_op_mov_TN_reg[ot][1][reg]();
3551         gen_op_testl_T0_T1_cc();
3552         s->cc_op = CC_OP_LOGICB + ot;
3553         break;
3554         
3555     case 0xa8: /* test eAX, Iv */
3556     case 0xa9:
3557         if ((b & 1) == 0)
3558             ot = OT_BYTE;
3559         else
3560             ot = dflag + OT_WORD;
3561         val = insn_get(s, ot);
3562
3563         gen_op_mov_TN_reg[ot][0][OR_EAX]();
3564         gen_op_movl_T1_im(val);
3565         gen_op_testl_T0_T1_cc();
3566         s->cc_op = CC_OP_LOGICB + ot;
3567         break;
3568         
3569     case 0x98: /* CWDE/CBW */
3570 #ifdef TARGET_X86_64
3571         if (dflag == 2) {
3572             gen_op_movslq_RAX_EAX();
3573         } else
3574 #endif
3575         if (dflag == 1)
3576             gen_op_movswl_EAX_AX();
3577         else
3578             gen_op_movsbw_AX_AL();
3579         break;
3580     case 0x99: /* CDQ/CWD */
3581 #ifdef TARGET_X86_64
3582         if (dflag == 2) {
3583             gen_op_movsqo_RDX_RAX();
3584         } else
3585 #endif
3586         if (dflag == 1)
3587             gen_op_movslq_EDX_EAX();
3588         else
3589             gen_op_movswl_DX_AX();
3590         break;
3591     case 0x1af: /* imul Gv, Ev */
3592     case 0x69: /* imul Gv, Ev, I */
3593     case 0x6b:
3594         ot = dflag + OT_WORD;
3595         modrm = ldub_code(s->pc++);
3596         reg = ((modrm >> 3) & 7) | rex_r;
3597         if (b == 0x69)
3598             s->rip_offset = insn_const_size(ot);
3599         else if (b == 0x6b)
3600             s->rip_offset = 1;
3601         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3602         if (b == 0x69) {
3603             val = insn_get(s, ot);
3604             gen_op_movl_T1_im(val);
3605         } else if (b == 0x6b) {
3606             val = (int8_t)insn_get(s, OT_BYTE);
3607             gen_op_movl_T1_im(val);
3608         } else {
3609             gen_op_mov_TN_reg[ot][1][reg]();
3610         }
3611
3612 #ifdef TARGET_X86_64
3613         if (ot == OT_QUAD) {
3614             gen_op_imulq_T0_T1();
3615         } else
3616 #endif
3617         if (ot == OT_LONG) {
3618             gen_op_imull_T0_T1();
3619         } else {
3620             gen_op_imulw_T0_T1();
3621         }
3622         gen_op_mov_reg_T0[ot][reg]();
3623         s->cc_op = CC_OP_MULB + ot;
3624         break;
3625     case 0x1c0:
3626     case 0x1c1: /* xadd Ev, Gv */
3627         if ((b & 1) == 0)
3628             ot = OT_BYTE;
3629         else
3630             ot = dflag + OT_WORD;
3631         modrm = ldub_code(s->pc++);
3632         reg = ((modrm >> 3) & 7) | rex_r;
3633         mod = (modrm >> 6) & 3;
3634         if (mod == 3) {
3635             rm = (modrm & 7) | REX_B(s);
3636             gen_op_mov_TN_reg[ot][0][reg]();
3637             gen_op_mov_TN_reg[ot][1][rm]();
3638             gen_op_addl_T0_T1();
3639             gen_op_mov_reg_T1[ot][reg]();
3640             gen_op_mov_reg_T0[ot][rm]();
3641         } else {
3642             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3643             gen_op_mov_TN_reg[ot][0][reg]();
3644             gen_op_ld_T1_A0[ot + s->mem_index]();
3645             gen_op_addl_T0_T1();
3646             gen_op_st_T0_A0[ot + s->mem_index]();
3647             gen_op_mov_reg_T1[ot][reg]();
3648         }
3649         gen_op_update2_cc();
3650         s->cc_op = CC_OP_ADDB + ot;
3651         break;
3652     case 0x1b0:
3653     case 0x1b1: /* cmpxchg Ev, Gv */
3654         if ((b & 1) == 0)
3655             ot = OT_BYTE;
3656         else
3657             ot = dflag + OT_WORD;
3658         modrm = ldub_code(s->pc++);
3659         reg = ((modrm >> 3) & 7) | rex_r;
3660         mod = (modrm >> 6) & 3;
3661         gen_op_mov_TN_reg[ot][1][reg]();
3662         if (mod == 3) {
3663             rm = (modrm & 7) | REX_B(s);
3664             gen_op_mov_TN_reg[ot][0][rm]();
3665             gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
3666             gen_op_mov_reg_T0[ot][rm]();
3667         } else {
3668             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3669             gen_op_ld_T0_A0[ot + s->mem_index]();
3670             gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
3671         }
3672         s->cc_op = CC_OP_SUBB + ot;
3673         break;
3674     case 0x1c7: /* cmpxchg8b */
3675         modrm = ldub_code(s->pc++);
3676         mod = (modrm >> 6) & 3;
3677         if (mod == 3)
3678             goto illegal_op;
3679         if (s->cc_op != CC_OP_DYNAMIC)
3680             gen_op_set_cc_op(s->cc_op);
3681         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3682         gen_op_cmpxchg8b();
3683         s->cc_op = CC_OP_EFLAGS;
3684         break;
3685         
3686         /**************************/
3687         /* push/pop */
3688     case 0x50 ... 0x57: /* push */
3689         gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)]();
3690         gen_push_T0(s);
3691         break;
3692     case 0x58 ... 0x5f: /* pop */
3693         if (CODE64(s)) {
3694             ot = dflag ? OT_QUAD : OT_WORD;
3695         } else {
3696             ot = dflag + OT_WORD;
3697         }
3698         gen_pop_T0(s);
3699         /* NOTE: order is important for pop %sp */
3700         gen_pop_update(s);
3701         gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)]();
3702         break;
3703     case 0x60: /* pusha */
3704         if (CODE64(s))
3705             goto illegal_op;
3706         gen_pusha(s);
3707         break;
3708     case 0x61: /* popa */
3709         if (CODE64(s))
3710             goto illegal_op;
3711         gen_popa(s);
3712         break;
3713     case 0x68: /* push Iv */
3714     case 0x6a:
3715         if (CODE64(s)) {
3716             ot = dflag ? OT_QUAD : OT_WORD;
3717         } else {
3718             ot = dflag + OT_WORD;
3719         }
3720         if (b == 0x68)
3721             val = insn_get(s, ot);
3722         else
3723             val = (int8_t)insn_get(s, OT_BYTE);
3724         gen_op_movl_T0_im(val);
3725         gen_push_T0(s);
3726         break;
3727     case 0x8f: /* pop Ev */
3728         if (CODE64(s)) {
3729             ot = dflag ? OT_QUAD : OT_WORD;
3730         } else {
3731             ot = dflag + OT_WORD;
3732         }
3733         modrm = ldub_code(s->pc++);
3734         mod = (modrm >> 6) & 3;
3735         gen_pop_T0(s);
3736         if (mod == 3) {
3737             /* NOTE: order is important for pop %sp */
3738             gen_pop_update(s);
3739             rm = (modrm & 7) | REX_B(s);
3740             gen_op_mov_reg_T0[ot][rm]();
3741         } else {
3742             /* NOTE: order is important too for MMU exceptions */
3743             s->popl_esp_hack = 1 << ot;
3744             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3745             s->popl_esp_hack = 0;
3746             gen_pop_update(s);
3747         }
3748         break;
3749     case 0xc8: /* enter */
3750         {
3751             int level;
3752             val = lduw_code(s->pc);
3753             s->pc += 2;
3754             level = ldub_code(s->pc++);
3755             gen_enter(s, val, level);
3756         }
3757         break;
3758     case 0xc9: /* leave */
3759         /* XXX: exception not precise (ESP is updated before potential exception) */
3760         if (CODE64(s)) {
3761             gen_op_mov_TN_reg[OT_QUAD][0][R_EBP]();
3762             gen_op_mov_reg_T0[OT_QUAD][R_ESP]();
3763         } else if (s->ss32) {
3764             gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
3765             gen_op_mov_reg_T0[OT_LONG][R_ESP]();
3766         } else {
3767             gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
3768             gen_op_mov_reg_T0[OT_WORD][R_ESP]();
3769         }
3770         gen_pop_T0(s);
3771         if (CODE64(s)) {
3772             ot = dflag ? OT_QUAD : OT_WORD;
3773         } else {
3774             ot = dflag + OT_WORD;
3775         }
3776         gen_op_mov_reg_T0[ot][R_EBP]();
3777         gen_pop_update(s);
3778         break;
3779     case 0x06: /* push es */
3780     case 0x0e: /* push cs */
3781     case 0x16: /* push ss */
3782     case 0x1e: /* push ds */
3783         if (CODE64(s))
3784             goto illegal_op;
3785         gen_op_movl_T0_seg(b >> 3);
3786         gen_push_T0(s);
3787         break;
3788     case 0x1a0: /* push fs */
3789     case 0x1a8: /* push gs */
3790         gen_op_movl_T0_seg((b >> 3) & 7);
3791         gen_push_T0(s);
3792         break;
3793     case 0x07: /* pop es */
3794     case 0x17: /* pop ss */
3795     case 0x1f: /* pop ds */
3796         if (CODE64(s))
3797             goto illegal_op;
3798         reg = b >> 3;
3799         gen_pop_T0(s);
3800         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
3801         gen_pop_update(s);
3802         if (reg == R_SS) {
3803             /* if reg == SS, inhibit interrupts/trace. */
3804             /* If several instructions disable interrupts, only the
3805                _first_ does it */
3806             if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3807                 gen_op_set_inhibit_irq();
3808             s->tf = 0;
3809         }
3810         if (s->is_jmp) {
3811             gen_jmp_im(s->pc - s->cs_base);
3812             gen_eob(s);
3813         }
3814         break;
3815     case 0x1a1: /* pop fs */
3816     case 0x1a9: /* pop gs */
3817         gen_pop_T0(s);
3818         gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
3819         gen_pop_update(s);
3820         if (s->is_jmp) {
3821             gen_jmp_im(s->pc - s->cs_base);
3822             gen_eob(s);
3823         }
3824         break;
3825
3826         /**************************/
3827         /* mov */
3828     case 0x88:
3829     case 0x89: /* mov Gv, Ev */
3830         if ((b & 1) == 0)
3831             ot = OT_BYTE;
3832         else
3833             ot = dflag + OT_WORD;
3834         modrm = ldub_code(s->pc++);
3835         reg = ((modrm >> 3) & 7) | rex_r;
3836         
3837         /* generate a generic store */
3838         gen_ldst_modrm(s, modrm, ot, reg, 1);
3839         break;
3840     case 0xc6:
3841     case 0xc7: /* mov Ev, Iv */
3842         if ((b & 1) == 0)
3843             ot = OT_BYTE;
3844         else
3845             ot = dflag + OT_WORD;
3846         modrm = ldub_code(s->pc++);
3847         mod = (modrm >> 6) & 3;
3848         if (mod != 3) {
3849             s->rip_offset = insn_const_size(ot);
3850             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3851         }
3852         val = insn_get(s, ot);
3853         gen_op_movl_T0_im(val);
3854         if (mod != 3)
3855             gen_op_st_T0_A0[ot + s->mem_index]();
3856         else
3857             gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)]();
3858         break;
3859     case 0x8a:
3860     case 0x8b: /* mov Ev, Gv */
3861         if ((b & 1) == 0)
3862             ot = OT_BYTE;
3863         else
3864             ot = OT_WORD + dflag;
3865         modrm = ldub_code(s->pc++);
3866         reg = ((modrm >> 3) & 7) | rex_r;
3867         
3868         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3869         gen_op_mov_reg_T0[ot][reg]();
3870         break;
3871     case 0x8e: /* mov seg, Gv */
3872         modrm = ldub_code(s->pc++);
3873         reg = (modrm >> 3) & 7;
3874         if (reg >= 6 || reg == R_CS)
3875             goto illegal_op;
3876         gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3877         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
3878         if (reg == R_SS) {
3879             /* if reg == SS, inhibit interrupts/trace */
3880             /* If several instructions disable interrupts, only the
3881                _first_ does it */
3882             if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3883                 gen_op_set_inhibit_irq();
3884             s->tf = 0;
3885         }
3886         if (s->is_jmp) {
3887             gen_jmp_im(s->pc - s->cs_base);
3888             gen_eob(s);
3889         }
3890         break;
3891     case 0x8c: /* mov Gv, seg */
3892         modrm = ldub_code(s->pc++);
3893         reg = (modrm >> 3) & 7;
3894         mod = (modrm >> 6) & 3;
3895         if (reg >= 6)
3896             goto illegal_op;
3897         gen_op_movl_T0_seg(reg);
3898         if (mod == 3)
3899             ot = OT_WORD + dflag;
3900         else
3901             ot = OT_WORD;
3902         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3903         break;
3904
3905     case 0x1b6: /* movzbS Gv, Eb */
3906     case 0x1b7: /* movzwS Gv, Eb */
3907     case 0x1be: /* movsbS Gv, Eb */
3908     case 0x1bf: /* movswS Gv, Eb */
3909         {
3910             int d_ot;
3911             /* d_ot is the size of destination */
3912             d_ot = dflag + OT_WORD;
3913             /* ot is the size of source */
3914             ot = (b & 1) + OT_BYTE;
3915             modrm = ldub_code(s->pc++);
3916             reg = ((modrm >> 3) & 7) | rex_r;
3917             mod = (modrm >> 6) & 3;
3918             rm = (modrm & 7) | REX_B(s);
3919             
3920             if (mod == 3) {
3921                 gen_op_mov_TN_reg[ot][0][rm]();
3922                 switch(ot | (b & 8)) {
3923                 case OT_BYTE:
3924                     gen_op_movzbl_T0_T0();
3925                     break;
3926                 case OT_BYTE | 8:
3927                     gen_op_movsbl_T0_T0();
3928                     break;
3929                 case OT_WORD:
3930                     gen_op_movzwl_T0_T0();
3931                     break;
3932                 default:
3933                 case OT_WORD | 8:
3934                     gen_op_movswl_T0_T0();
3935                     break;
3936                 }
3937                 gen_op_mov_reg_T0[d_ot][reg]();
3938             } else {
3939                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3940                 if (b & 8) {
3941                     gen_op_lds_T0_A0[ot + s->mem_index]();
3942                 } else {
3943                     gen_op_ldu_T0_A0[ot + s->mem_index]();
3944                 }
3945                 gen_op_mov_reg_T0[d_ot][reg]();
3946             }
3947         }
3948         break;
3949
3950     case 0x8d: /* lea */
3951         ot = dflag + OT_WORD;
3952         modrm = ldub_code(s->pc++);
3953         mod = (modrm >> 6) & 3;
3954         if (mod == 3)
3955             goto illegal_op;
3956         reg = ((modrm >> 3) & 7) | rex_r;
3957         /* we must ensure that no segment is added */
3958         s->override = -1;
3959         val = s->addseg;
3960         s->addseg = 0;
3961         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3962         s->addseg = val;
3963         gen_op_mov_reg_A0[ot - OT_WORD][reg]();
3964         break;
3965         
3966     case 0xa0: /* mov EAX, Ov */
3967     case 0xa1:
3968     case 0xa2: /* mov Ov, EAX */
3969     case 0xa3:
3970         {
3971             target_ulong offset_addr;
3972
3973             if ((b & 1) == 0)
3974                 ot = OT_BYTE;
3975             else
3976                 ot = dflag + OT_WORD;
3977 #ifdef TARGET_X86_64
3978             if (s->aflag == 2) {
3979                 offset_addr = ldq_code(s->pc);
3980                 s->pc += 8;
3981                 if (offset_addr == (int32_t)offset_addr)
3982                     gen_op_movq_A0_im(offset_addr);
3983                 else
3984                     gen_op_movq_A0_im64(offset_addr >> 32, offset_addr);
3985             } else 
3986 #endif
3987             {
3988                 if (s->aflag) {
3989                     offset_addr = insn_get(s, OT_LONG);
3990                 } else {
3991                     offset_addr = insn_get(s, OT_WORD);
3992                 }
3993                 gen_op_movl_A0_im(offset_addr);
3994             }
3995             gen_add_A0_ds_seg(s);
3996             if ((b & 2) == 0) {
3997                 gen_op_ld_T0_A0[ot + s->mem_index]();
3998                 gen_op_mov_reg_T0[ot][R_EAX]();
3999             } else {
4000                 gen_op_mov_TN_reg[ot][0][R_EAX]();
4001                 gen_op_st_T0_A0[ot + s->mem_index]();
4002             }
4003         }
4004         break;
4005     case 0xd7: /* xlat */
4006 #ifdef TARGET_X86_64
4007         if (s->aflag == 2) {
4008             gen_op_movq_A0_reg[R_EBX]();
4009             gen_op_addq_A0_AL();
4010         } else 
4011 #endif
4012         {
4013             gen_op_movl_A0_reg[R_EBX]();
4014             gen_op_addl_A0_AL();
4015             if (s->aflag == 0)
4016                 gen_op_andl_A0_ffff();
4017         }
4018         gen_add_A0_ds_seg(s);
4019         gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
4020         gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
4021         break;
4022     case 0xb0 ... 0xb7: /* mov R, Ib */
4023         val = insn_get(s, OT_BYTE);
4024         gen_op_movl_T0_im(val);
4025         gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)]();
4026         break;
4027     case 0xb8 ... 0xbf: /* mov R, Iv */
4028 #ifdef TARGET_X86_64
4029         if (dflag == 2) {
4030             uint64_t tmp;
4031             /* 64 bit case */
4032             tmp = ldq_code(s->pc);
4033             s->pc += 8;
4034             reg = (b & 7) | REX_B(s);
4035             gen_movtl_T0_im(tmp);
4036             gen_op_mov_reg_T0[OT_QUAD][reg]();
4037         } else 
4038 #endif
4039         {
4040             ot = dflag ? OT_LONG : OT_WORD;
4041             val = insn_get(s, ot);
4042             reg = (b & 7) | REX_B(s);
4043             gen_op_movl_T0_im(val);
4044             gen_op_mov_reg_T0[ot][reg]();
4045         }
4046         break;
4047
4048     case 0x91 ... 0x97: /* xchg R, EAX */
4049         ot = dflag + OT_WORD;
4050         reg = (b & 7) | REX_B(s);
4051         rm = R_EAX;
4052         goto do_xchg_reg;
4053     case 0x86:
4054     case 0x87: /* xchg Ev, Gv */
4055         if ((b & 1) == 0)
4056             ot = OT_BYTE;
4057         else
4058             ot = dflag + OT_WORD;
4059         modrm = ldub_code(s->pc++);
4060         reg = ((modrm >> 3) & 7) | rex_r;
4061         mod = (modrm >> 6) & 3;
4062         if (mod == 3) {
4063             rm = (modrm & 7) | REX_B(s);
4064         do_xchg_reg:
4065             gen_op_mov_TN_reg[ot][0][reg]();
4066             gen_op_mov_TN_reg[ot][1][rm]();
4067             gen_op_mov_reg_T0[ot][rm]();
4068             gen_op_mov_reg_T1[ot][reg]();
4069         } else {
4070             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4071             gen_op_mov_TN_reg[ot][0][reg]();
4072             /* for xchg, lock is implicit */
4073             if (!(prefixes & PREFIX_LOCK))
4074                 gen_op_lock();
4075             gen_op_ld_T1_A0[ot + s->mem_index]();
4076             gen_op_st_T0_A0[ot + s->mem_index]();
4077             if (!(prefixes & PREFIX_LOCK))
4078                 gen_op_unlock();
4079             gen_op_mov_reg_T1[ot][reg]();
4080         }
4081         break;
4082     case 0xc4: /* les Gv */
4083         if (CODE64(s))
4084             goto illegal_op;
4085         op = R_ES;
4086         goto do_lxx;
4087     case 0xc5: /* lds Gv */
4088         if (CODE64(s))
4089             goto illegal_op;
4090         op = R_DS;
4091         goto do_lxx;
4092     case 0x1b2: /* lss Gv */
4093         op = R_SS;
4094         goto do_lxx;
4095     case 0x1b4: /* lfs Gv */
4096         op = R_FS;
4097         goto do_lxx;
4098     case 0x1b5: /* lgs Gv */
4099         op = R_GS;
4100     do_lxx:
4101         ot = dflag ? OT_LONG : OT_WORD;
4102         modrm = ldub_code(s->pc++);
4103         reg = ((modrm >> 3) & 7) | rex_r;
4104         mod = (modrm >> 6) & 3;
4105         if (mod == 3)
4106             goto illegal_op;
4107         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4108         gen_op_ld_T1_A0[ot + s->mem_index]();
4109         gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
4110         /* load the segment first to handle exceptions properly */
4111         gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
4112         gen_movl_seg_T0(s, op, pc_start - s->cs_base);
4113         /* then put the data */
4114         gen_op_mov_reg_T1[ot][reg]();
4115         if (s->is_jmp) {
4116             gen_jmp_im(s->pc - s->cs_base);
4117             gen_eob(s);
4118         }
4119         break;
4120         
4121         /************************/
4122         /* shifts */
4123     case 0xc0:
4124     case 0xc1:
4125         /* shift Ev,Ib */
4126         shift = 2;
4127     grp2:
4128         {
4129             if ((b & 1) == 0)
4130                 ot = OT_BYTE;
4131             else
4132                 ot = dflag + OT_WORD;
4133             
4134             modrm = ldub_code(s->pc++);
4135             mod = (modrm >> 6) & 3;
4136             op = (modrm >> 3) & 7;
4137             
4138             if (mod != 3) {
4139                 if (shift == 2) {
4140                     s->rip_offset = 1;
4141                 }
4142                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4143                 opreg = OR_TMP0;
4144             } else {
4145                 opreg = (modrm & 7) | REX_B(s);
4146             }
4147
4148             /* simpler op */
4149             if (shift == 0) {
4150                 gen_shift(s, op, ot, opreg, OR_ECX);
4151             } else {
4152                 if (shift == 2) {
4153                     shift = ldub_code(s->pc++);
4154                 }
4155                 gen_shifti(s, op, ot, opreg, shift);
4156             }
4157         }
4158         break;
4159     case 0xd0:
4160     case 0xd1:
4161         /* shift Ev,1 */
4162         shift = 1;
4163         goto grp2;
4164     case 0xd2:
4165     case 0xd3:
4166         /* shift Ev,cl */
4167         shift = 0;
4168         goto grp2;
4169
4170     case 0x1a4: /* shld imm */
4171         op = 0;
4172         shift = 1;
4173         goto do_shiftd;
4174     case 0x1a5: /* shld cl */
4175         op = 0;
4176         shift = 0;
4177         goto do_shiftd;
4178     case 0x1ac: /* shrd imm */
4179         op = 1;
4180         shift = 1;
4181         goto do_shiftd;
4182     case 0x1ad: /* shrd cl */
4183         op = 1;
4184         shift = 0;
4185     do_shiftd:
4186         ot = dflag + OT_WORD;
4187         modrm = ldub_code(s->pc++);
4188         mod = (modrm >> 6) & 3;
4189         rm = (modrm & 7) | REX_B(s);
4190         reg = ((modrm >> 3) & 7) | rex_r;
4191         
4192         if (mod != 3) {
4193             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4194             gen_op_ld_T0_A0[ot + s->mem_index]();
4195         } else {
4196             gen_op_mov_TN_reg[ot][0][rm]();
4197         }
4198         gen_op_mov_TN_reg[ot][1][reg]();
4199         
4200         if (shift) {
4201             val = ldub_code(s->pc++);
4202             if (ot == OT_QUAD)
4203                 val &= 0x3f;
4204             else
4205                 val &= 0x1f;
4206             if (val) {
4207                 if (mod == 3)
4208                     gen_op_shiftd_T0_T1_im_cc[ot][op](val);
4209                 else
4210                     gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
4211                 if (op == 0 && ot != OT_WORD)
4212                     s->cc_op = CC_OP_SHLB + ot;
4213                 else
4214                     s->cc_op = CC_OP_SARB + ot;
4215             }
4216         } else {
4217             if (s->cc_op != CC_OP_DYNAMIC)
4218                 gen_op_set_cc_op(s->cc_op);
4219             if (mod == 3)
4220                 gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
4221             else
4222                 gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
4223             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
4224         }
4225         if (mod == 3) {
4226             gen_op_mov_reg_T0[ot][rm]();
4227         }
4228         break;
4229
4230         /************************/
4231         /* floats */
4232     case 0xd8 ... 0xdf: 
4233         if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
4234             /* if CR0.EM or CR0.TS are set, generate an FPU exception */
4235             /* XXX: what to do if illegal op ? */
4236             gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
4237             break;
4238         }
4239         modrm = ldub_code(s->pc++);
4240         mod = (modrm >> 6) & 3;
4241         rm = modrm & 7;
4242         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
4243         if (mod != 3) {
4244             /* memory op */
4245             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4246             switch(op) {
4247             case 0x00 ... 0x07: /* fxxxs */
4248             case 0x10 ... 0x17: /* fixxxl */
4249             case 0x20 ... 0x27: /* fxxxl */
4250             case 0x30 ... 0x37: /* fixxx */
4251                 {
4252                     int op1;
4253                     op1 = op & 7;
4254
4255                     switch(op >> 4) {
4256                     case 0:
4257                         gen_op_flds_FT0_A0();
4258                         break;
4259                     case 1:
4260                         gen_op_fildl_FT0_A0();
4261                         break;
4262                     case 2:
4263                         gen_op_fldl_FT0_A0();
4264                         break;
4265                     case 3:
4266                     default:
4267                         gen_op_fild_FT0_A0();
4268                         break;
4269                     }
4270                     
4271                     gen_op_fp_arith_ST0_FT0[op1]();
4272                     if (op1 == 3) {
4273                         /* fcomp needs pop */
4274                         gen_op_fpop();
4275                     }
4276                 }
4277                 break;
4278             case 0x08: /* flds */
4279             case 0x0a: /* fsts */
4280             case 0x0b: /* fstps */
4281             case 0x18: /* fildl */
4282             case 0x1a: /* fistl */
4283             case 0x1b: /* fistpl */
4284             case 0x28: /* fldl */
4285             case 0x2a: /* fstl */
4286             case 0x2b: /* fstpl */
4287             case 0x38: /* filds */
4288             case 0x3a: /* fists */
4289             case 0x3b: /* fistps */
4290                 
4291                 switch(op & 7) {
4292                 case 0:
4293                     switch(op >> 4) {
4294                     case 0:
4295                         gen_op_flds_ST0_A0();
4296                         break;
4297                     case 1:
4298                         gen_op_fildl_ST0_A0();
4299                         break;
4300                     case 2:
4301                         gen_op_fldl_ST0_A0();
4302                         break;
4303                     case 3:
4304                     default:
4305                         gen_op_fild_ST0_A0();
4306                         break;
4307                     }
4308                     break;
4309                 default:
4310                     switch(op >> 4) {
4311                     case 0:
4312                         gen_op_fsts_ST0_A0();
4313                         break;
4314                     case 1:
4315                         gen_op_fistl_ST0_A0();
4316                         break;
4317                     case 2:
4318                         gen_op_fstl_ST0_A0();
4319                         break;
4320                     case 3:
4321                     default:
4322                         gen_op_fist_ST0_A0();
4323                         break;
4324                     }
4325                     if ((op & 7) == 3)
4326                         gen_op_fpop();
4327                     break;
4328                 }
4329                 break;
4330             case 0x0c: /* fldenv mem */
4331                 gen_op_fldenv_A0(s->dflag);
4332                 break;
4333             case 0x0d: /* fldcw mem */
4334                 gen_op_fldcw_A0();
4335                 break;
4336             case 0x0e: /* fnstenv mem */
4337                 gen_op_fnstenv_A0(s->dflag);
4338                 break;
4339             case 0x0f: /* fnstcw mem */
4340                 gen_op_fnstcw_A0();
4341                 break;
4342             case 0x1d: /* fldt mem */
4343                 gen_op_fldt_ST0_A0();
4344                 break;
4345             case 0x1f: /* fstpt mem */
4346                 gen_op_fstt_ST0_A0();
4347                 gen_op_fpop();
4348                 break;
4349             case 0x2c: /* frstor mem */
4350                 gen_op_frstor_A0(s->dflag);
4351                 break;
4352             case 0x2e: /* fnsave mem */
4353                 gen_op_fnsave_A0(s->dflag);
4354                 break;
4355             case 0x2f: /* fnstsw mem */
4356                 gen_op_fnstsw_A0();
4357                 break;
4358             case 0x3c: /* fbld */
4359                 gen_op_fbld_ST0_A0();
4360                 break;
4361             case 0x3e: /* fbstp */
4362                 gen_op_fbst_ST0_A0();
4363                 gen_op_fpop();
4364                 break;
4365             case 0x3d: /* fildll */
4366                 gen_op_fildll_ST0_A0();
4367                 break;
4368             case 0x3f: /* fistpll */
4369                 gen_op_fistll_ST0_A0();
4370                 gen_op_fpop();
4371                 break;
4372             default:
4373                 goto illegal_op;
4374             }
4375         } else {
4376             /* register float ops */
4377             opreg = rm;
4378
4379             switch(op) {
4380             case 0x08: /* fld sti */
4381                 gen_op_fpush();
4382                 gen_op_fmov_ST0_STN((opreg + 1) & 7);
4383                 break;
4384             case 0x09: /* fxchg sti */
4385             case 0x29: /* fxchg4 sti, undocumented op */
4386             case 0x39: /* fxchg7 sti, undocumented op */
4387                 gen_op_fxchg_ST0_STN(opreg);
4388                 break;
4389             case 0x0a: /* grp d9/2 */
4390                 switch(rm) {
4391                 case 0: /* fnop */
4392                     /* check exceptions (FreeBSD FPU probe) */
4393                     if (s->cc_op != CC_OP_DYNAMIC)
4394                         gen_op_set_cc_op(s->cc_op);
4395                     gen_jmp_im(pc_start - s->cs_base);
4396                     gen_op_fwait();
4397                     break;
4398                 default:
4399                     goto illegal_op;
4400                 }
4401                 break;
4402             case 0x0c: /* grp d9/4 */
4403                 switch(rm) {
4404                 case 0: /* fchs */
4405                     gen_op_fchs_ST0();
4406                     break;
4407                 case 1: /* fabs */
4408                     gen_op_fabs_ST0();
4409                     break;
4410                 case 4: /* ftst */
4411                     gen_op_fldz_FT0();
4412                     gen_op_fcom_ST0_FT0();
4413                     break;
4414                 case 5: /* fxam */
4415                     gen_op_fxam_ST0();
4416                     break;
4417                 default:
4418                     goto illegal_op;
4419                 }
4420                 break;
4421             case 0x0d: /* grp d9/5 */
4422                 {
4423                     switch(rm) {
4424                     case 0:
4425                         gen_op_fpush();
4426                         gen_op_fld1_ST0();
4427                         break;
4428                     case 1:
4429                         gen_op_fpush();
4430                         gen_op_fldl2t_ST0();
4431                         break;
4432                     case 2:
4433                         gen_op_fpush();
4434                         gen_op_fldl2e_ST0();
4435                         break;
4436                     case 3:
4437                         gen_op_fpush();
4438                         gen_op_fldpi_ST0();
4439                         break;
4440                     case 4:
4441                         gen_op_fpush();
4442                         gen_op_fldlg2_ST0();
4443                         break;
4444                     case 5:
4445                         gen_op_fpush();
4446                         gen_op_fldln2_ST0();
4447                         break;
4448                     case 6:
4449                         gen_op_fpush();
4450                         gen_op_fldz_ST0();
4451                         break;
4452                     default:
4453                         goto illegal_op;
4454                     }
4455                 }
4456                 break;
4457             case 0x0e: /* grp d9/6 */
4458                 switch(rm) {
4459                 case 0: /* f2xm1 */
4460                     gen_op_f2xm1();
4461                     break;
4462                 case 1: /* fyl2x */
4463                     gen_op_fyl2x();
4464                     break;
4465                 case 2: /* fptan */
4466                     gen_op_fptan();
4467                     break;
4468                 case 3: /* fpatan */
4469                     gen_op_fpatan();
4470                     break;
4471                 case 4: /* fxtract */
4472                     gen_op_fxtract();
4473                     break;
4474                 case 5: /* fprem1 */
4475                     gen_op_fprem1();
4476                     break;
4477                 case 6: /* fdecstp */
4478                     gen_op_fdecstp();
4479                     break;
4480                 default:
4481                 case 7: /* fincstp */
4482                     gen_op_fincstp();
4483                     break;
4484                 }
4485                 break;
4486             case 0x0f: /* grp d9/7 */
4487                 switch(rm) {
4488                 case 0: /* fprem */
4489                     gen_op_fprem();
4490                     break;
4491                 case 1: /* fyl2xp1 */
4492                     gen_op_fyl2xp1();
4493                     break;
4494                 case 2: /* fsqrt */
4495                     gen_op_fsqrt();
4496                     break;
4497                 case 3: /* fsincos */
4498                     gen_op_fsincos();
4499                     break;
4500                 case 5: /* fscale */
4501                     gen_op_fscale();
4502                     break;
4503                 case 4: /* frndint */
4504                     gen_op_frndint();
4505                     break;
4506                 case 6: /* fsin */
4507                     gen_op_fsin();
4508                     break;
4509                 default:
4510                 case 7: /* fcos */
4511                     gen_op_fcos();
4512                     break;
4513                 }
4514                 break;
4515             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
4516             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
4517             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
4518                 {
4519                     int op1;
4520                     
4521                     op1 = op & 7;
4522                     if (op >= 0x20) {
4523                         gen_op_fp_arith_STN_ST0[op1](opreg);
4524                         if (op >= 0x30)
4525                             gen_op_fpop();
4526                     } else {
4527                         gen_op_fmov_FT0_STN(opreg);
4528                         gen_op_fp_arith_ST0_FT0[op1]();
4529                     }
4530                 }
4531                 break;
4532             case 0x02: /* fcom */
4533             case 0x22: /* fcom2, undocumented op */
4534                 gen_op_fmov_FT0_STN(opreg);
4535                 gen_op_fcom_ST0_FT0();
4536                 break;
4537             case 0x03: /* fcomp */
4538             case 0x23: /* fcomp3, undocumented op */
4539             case 0x32: /* fcomp5, undocumented op */
4540                 gen_op_fmov_FT0_STN(opreg);
4541                 gen_op_fcom_ST0_FT0();
4542                 gen_op_fpop();
4543                 break;
4544             case 0x15: /* da/5 */
4545                 switch(rm) {
4546                 case 1: /* fucompp */
4547                     gen_op_fmov_FT0_STN(1);
4548                     gen_op_fucom_ST0_FT0();
4549                     gen_op_fpop();
4550                     gen_op_fpop();
4551                     break;
4552                 default:
4553                     goto illegal_op;
4554                 }
4555                 break;
4556             case 0x1c:
4557                 switch(rm) {
4558                 case 0: /* feni (287 only, just do nop here) */
4559                     break;
4560                 case 1: /* fdisi (287 only, just do nop here) */
4561                     break;
4562                 case 2: /* fclex */
4563                     gen_op_fclex();
4564                     break;
4565                 case 3: /* fninit */
4566                     gen_op_fninit();
4567                     break;
4568                 case 4: /* fsetpm (287 only, just do nop here) */
4569                     break;
4570                 default:
4571                     goto illegal_op;
4572                 }
4573                 break;
4574             case 0x1d: /* fucomi */
4575                 if (s->cc_op != CC_OP_DYNAMIC)
4576                     gen_op_set_cc_op(s->cc_op);
4577                 gen_op_fmov_FT0_STN(opreg);
4578                 gen_op_fucomi_ST0_FT0();
4579                 s->cc_op = CC_OP_EFLAGS;
4580                 break;
4581             case 0x1e: /* fcomi */
4582                 if (s->cc_op != CC_OP_DYNAMIC)
4583                     gen_op_set_cc_op(s->cc_op);
4584                 gen_op_fmov_FT0_STN(opreg);
4585                 gen_op_fcomi_ST0_FT0();
4586                 s->cc_op = CC_OP_EFLAGS;
4587                 break;
4588             case 0x28: /* ffree sti */
4589                 gen_op_ffree_STN(opreg);
4590                 break; 
4591             case 0x2a: /* fst sti */
4592                 gen_op_fmov_STN_ST0(opreg);
4593                 break;
4594             case 0x2b: /* fstp sti */
4595             case 0x0b: /* fstp1 sti, undocumented op */
4596             case 0x3a: /* fstp8 sti, undocumented op */
4597             case 0x3b: /* fstp9 sti, undocumented op */
4598                 gen_op_fmov_STN_ST0(opreg);
4599                 gen_op_fpop();
4600                 break;
4601             case 0x2c: /* fucom st(i) */
4602                 gen_op_fmov_FT0_STN(opreg);
4603                 gen_op_fucom_ST0_FT0();
4604                 break;
4605             case 0x2d: /* fucomp st(i) */
4606                 gen_op_fmov_FT0_STN(opreg);
4607                 gen_op_fucom_ST0_FT0();
4608                 gen_op_fpop();
4609                 break;
4610             case 0x33: /* de/3 */
4611                 switch(rm) {
4612                 case 1: /* fcompp */
4613                     gen_op_fmov_FT0_STN(1);
4614                     gen_op_fcom_ST0_FT0();
4615                     gen_op_fpop();
4616                     gen_op_fpop();
4617                     break;
4618                 default:
4619                     goto illegal_op;
4620                 }
4621                 break;
4622             case 0x38: /* ffreep sti, undocumented op */
4623                 gen_op_ffree_STN(opreg);
4624                 gen_op_fpop();
4625                 break;
4626             case 0x3c: /* df/4 */
4627                 switch(rm) {
4628                 case 0:
4629                     gen_op_fnstsw_EAX();
4630                     break;
4631                 default:
4632                     goto illegal_op;
4633                 }
4634                 break;
4635             case 0x3d: /* fucomip */
4636                 if (s->cc_op != CC_OP_DYNAMIC)
4637                     gen_op_set_cc_op(s->cc_op);
4638                 gen_op_fmov_FT0_STN(opreg);
4639                 gen_op_fucomi_ST0_FT0();
4640                 gen_op_fpop();
4641                 s->cc_op = CC_OP_EFLAGS;
4642                 break;
4643             case 0x3e: /* fcomip */
4644                 if (s->cc_op != CC_OP_DYNAMIC)
4645                     gen_op_set_cc_op(s->cc_op);
4646                 gen_op_fmov_FT0_STN(opreg);
4647                 gen_op_fcomi_ST0_FT0();
4648                 gen_op_fpop();
4649                 s->cc_op = CC_OP_EFLAGS;
4650                 break;
4651             case 0x10 ... 0x13: /* fcmovxx */
4652             case 0x18 ... 0x1b:
4653                 {
4654                     int op1;
4655                     const static uint8_t fcmov_cc[8] = {
4656                         (JCC_B << 1),
4657                         (JCC_Z << 1),
4658                         (JCC_BE << 1),
4659                         (JCC_P << 1),
4660                     };
4661                     op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
4662                     gen_setcc(s, op1);
4663                     gen_op_fcmov_ST0_STN_T0(opreg);
4664                 }
4665                 break;
4666             default:
4667                 goto illegal_op;
4668             }
4669         }
4670 #ifdef USE_CODE_COPY
4671         s->tb->cflags |= CF_TB_FP_USED;
4672 #endif
4673         break;
4674         /************************/
4675         /* string ops */
4676
4677     case 0xa4: /* movsS */
4678     case 0xa5:
4679         if ((b & 1) == 0)
4680             ot = OT_BYTE;
4681         else
4682             ot = dflag + OT_WORD;
4683
4684         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4685             gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4686         } else {
4687             gen_movs(s, ot);
4688         }
4689         break;
4690         
4691     case 0xaa: /* stosS */
4692     case 0xab:
4693         if ((b & 1) == 0)
4694             ot = OT_BYTE;
4695         else
4696             ot = dflag + OT_WORD;
4697
4698         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4699             gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4700         } else {
4701             gen_stos(s, ot);
4702         }
4703         break;
4704     case 0xac: /* lodsS */
4705     case 0xad:
4706         if ((b & 1) == 0)
4707             ot = OT_BYTE;
4708         else
4709             ot = dflag + OT_WORD;
4710         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4711             gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4712         } else {
4713             gen_lods(s, ot);
4714         }
4715         break;
4716     case 0xae: /* scasS */
4717     case 0xaf:
4718         if ((b & 1) == 0)
4719             ot = OT_BYTE;
4720         else
4721             ot = dflag + OT_WORD;
4722         if (prefixes & PREFIX_REPNZ) {
4723             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4724         } else if (prefixes & PREFIX_REPZ) {
4725             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4726         } else {
4727             gen_scas(s, ot);
4728             s->cc_op = CC_OP_SUBB + ot;
4729         }
4730         break;
4731
4732     case 0xa6: /* cmpsS */
4733     case 0xa7:
4734         if ((b & 1) == 0)
4735             ot = OT_BYTE;
4736         else
4737             ot = dflag + OT_WORD;
4738         if (prefixes & PREFIX_REPNZ) {
4739             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
4740         } else if (prefixes & PREFIX_REPZ) {
4741             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
4742         } else {
4743             gen_cmps(s, ot);
4744             s->cc_op = CC_OP_SUBB + ot;
4745         }
4746         break;
4747     case 0x6c: /* insS */
4748     case 0x6d:
4749         if ((b & 1) == 0)
4750             ot = OT_BYTE;
4751         else
4752             ot = dflag ? OT_LONG : OT_WORD;
4753         gen_check_io(s, ot, 1, pc_start - s->cs_base);
4754         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4755             gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4756         } else {
4757             gen_ins(s, ot);
4758         }
4759         break;
4760     case 0x6e: /* outsS */
4761     case 0x6f:
4762         if ((b & 1) == 0)
4763             ot = OT_BYTE;
4764         else
4765             ot = dflag ? OT_LONG : OT_WORD;
4766         gen_check_io(s, ot, 1, pc_start - s->cs_base);
4767         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
4768             gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
4769         } else {
4770             gen_outs(s, ot);
4771         }
4772         break;
4773
4774         /************************/
4775         /* port I/O */
4776     case 0xe4:
4777     case 0xe5:
4778         if ((b & 1) == 0)
4779             ot = OT_BYTE;
4780         else
4781             ot = dflag ? OT_LONG : OT_WORD;
4782         val = ldub_code(s->pc++);
4783         gen_op_movl_T0_im(val);
4784         gen_check_io(s, ot, 0, pc_start - s->cs_base);
4785         gen_op_in[ot]();
4786         gen_op_mov_reg_T1[ot][R_EAX]();
4787         break;
4788     case 0xe6:
4789     case 0xe7:
4790         if ((b & 1) == 0)
4791             ot = OT_BYTE;
4792         else
4793             ot = dflag ? OT_LONG : OT_WORD;
4794         val = ldub_code(s->pc++);
4795         gen_op_movl_T0_im(val);
4796         gen_check_io(s, ot, 0, pc_start - s->cs_base);
4797         gen_op_mov_TN_reg[ot][1][R_EAX]();
4798         gen_op_out[ot]();
4799         break;
4800     case 0xec:
4801     case 0xed:
4802         if ((b & 1) == 0)
4803             ot = OT_BYTE;
4804         else
4805             ot = dflag ? OT_LONG : OT_WORD;
4806         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4807         gen_op_andl_T0_ffff();
4808         gen_check_io(s, ot, 0, pc_start - s->cs_base);
4809         gen_op_in[ot]();
4810         gen_op_mov_reg_T1[ot][R_EAX]();
4811         break;
4812     case 0xee:
4813     case 0xef:
4814         if ((b & 1) == 0)
4815             ot = OT_BYTE;
4816         else
4817             ot = dflag ? OT_LONG : OT_WORD;
4818         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
4819         gen_op_andl_T0_ffff();
4820         gen_check_io(s, ot, 0, pc_start - s->cs_base);
4821         gen_op_mov_TN_reg[ot][1][R_EAX]();
4822         gen_op_out[ot]();
4823         break;
4824
4825         /************************/
4826         /* control */
4827     case 0xc2: /* ret im */
4828         val = ldsw_code(s->pc);
4829         s->pc += 2;
4830         gen_pop_T0(s);
4831         if (CODE64(s) && s->dflag)
4832             s->dflag = 2;
4833         gen_stack_update(s, val + (2 << s->dflag));
4834         if (s->dflag == 0)
4835             gen_op_andl_T0_ffff();
4836         gen_op_jmp_T0();
4837         gen_eob(s);
4838         break;
4839     case 0xc3: /* ret */
4840         gen_pop_T0(s);
4841         gen_pop_update(s);
4842         if (s->dflag == 0)
4843             gen_op_andl_T0_ffff();
4844         gen_op_jmp_T0();
4845         gen_eob(s);
4846         break;
4847     case 0xca: /* lret im */
4848         val = ldsw_code(s->pc);
4849         s->pc += 2;
4850     do_lret:
4851         if (s->pe && !s->vm86) {
4852             if (s->cc_op != CC_OP_DYNAMIC)
4853                 gen_op_set_cc_op(s->cc_op);
4854             gen_jmp_im(pc_start - s->cs_base);
4855             gen_op_lret_protected(s->dflag, val);
4856         } else {
4857             gen_stack_A0(s);
4858             /* pop offset */
4859             gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4860             if (s->dflag == 0)
4861                 gen_op_andl_T0_ffff();
4862             /* NOTE: keeping EIP updated is not a problem in case of
4863                exception */
4864             gen_op_jmp_T0();
4865             /* pop selector */
4866             gen_op_addl_A0_im(2 << s->dflag);
4867             gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
4868             gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
4869             /* add stack offset */
4870             gen_stack_update(s, val + (4 << s->dflag));
4871         }
4872         gen_eob(s);
4873         break;
4874     case 0xcb: /* lret */
4875         val = 0;
4876         goto do_lret;
4877     case 0xcf: /* iret */
4878         if (!s->pe) {
4879             /* real mode */
4880             gen_op_iret_real(s->dflag);
4881             s->cc_op = CC_OP_EFLAGS;
4882         } else if (s->vm86) {
4883             if (s->iopl != 3) {
4884                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4885             } else {
4886                 gen_op_iret_real(s->dflag);
4887                 s->cc_op = CC_OP_EFLAGS;
4888             }
4889         } else {
4890             if (s->cc_op != CC_OP_DYNAMIC)
4891                 gen_op_set_cc_op(s->cc_op);
4892             gen_jmp_im(pc_start - s->cs_base);
4893             gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
4894             s->cc_op = CC_OP_EFLAGS;
4895         }
4896         gen_eob(s);
4897         break;
4898     case 0xe8: /* call im */
4899         {
4900             if (dflag)
4901                 tval = (int32_t)insn_get(s, OT_LONG);
4902             else
4903                 tval = (int16_t)insn_get(s, OT_WORD);
4904             next_eip = s->pc - s->cs_base;
4905             tval += next_eip;
4906             if (s->dflag == 0)
4907                 tval &= 0xffff;
4908             gen_movtl_T0_im(next_eip);
4909             gen_push_T0(s);
4910             gen_jmp(s, tval);
4911         }
4912         break;
4913     case 0x9a: /* lcall im */
4914         {
4915             unsigned int selector, offset;
4916             
4917             if (CODE64(s))
4918                 goto illegal_op;
4919             ot = dflag ? OT_LONG : OT_WORD;
4920             offset = insn_get(s, ot);
4921             selector = insn_get(s, OT_WORD);
4922             
4923             gen_op_movl_T0_im(selector);
4924             gen_op_movl_T1_imu(offset);
4925         }
4926         goto do_lcall;
4927     case 0xe9: /* jmp im */
4928         if (dflag)
4929             tval = (int32_t)insn_get(s, OT_LONG);
4930         else
4931             tval = (int16_t)insn_get(s, OT_WORD);
4932         tval += s->pc - s->cs_base;
4933         if (s->dflag == 0)
4934             tval &= 0xffff;
4935         gen_jmp(s, tval);
4936         break;
4937     case 0xea: /* ljmp im */
4938         {
4939             unsigned int selector, offset;
4940
4941             if (CODE64(s))
4942                 goto illegal_op;
4943             ot = dflag ? OT_LONG : OT_WORD;
4944             offset = insn_get(s, ot);
4945             selector = insn_get(s, OT_WORD);
4946             
4947             gen_op_movl_T0_im(selector);
4948             gen_op_movl_T1_imu(offset);
4949         }
4950         goto do_ljmp;
4951     case 0xeb: /* jmp Jb */
4952         tval = (int8_t)insn_get(s, OT_BYTE);
4953         tval += s->pc - s->cs_base;
4954         if (s->dflag == 0)
4955             tval &= 0xffff;
4956         gen_jmp(s, tval);
4957         break;
4958     case 0x70 ... 0x7f: /* jcc Jb */
4959         tval = (int8_t)insn_get(s, OT_BYTE);
4960         goto do_jcc;
4961     case 0x180 ... 0x18f: /* jcc Jv */
4962         if (dflag) {
4963             tval = (int32_t)insn_get(s, OT_LONG);
4964         } else {
4965             tval = (int16_t)insn_get(s, OT_WORD); 
4966         }
4967     do_jcc:
4968         next_eip = s->pc - s->cs_base;
4969         tval += next_eip;
4970         if (s->dflag == 0)
4971             tval &= 0xffff;
4972         gen_jcc(s, b, tval, next_eip);
4973         break;
4974
4975     case 0x190 ... 0x19f: /* setcc Gv */
4976         modrm = ldub_code(s->pc++);
4977         gen_setcc(s, b);
4978         gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
4979         break;
4980     case 0x140 ... 0x14f: /* cmov Gv, Ev */
4981         ot = dflag + OT_WORD;
4982         modrm = ldub_code(s->pc++);
4983         reg = ((modrm >> 3) & 7) | rex_r;
4984         mod = (modrm >> 6) & 3;
4985         gen_setcc(s, b);
4986         if (mod != 3) {
4987             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4988             gen_op_ld_T1_A0[ot + s->mem_index]();
4989         } else {
4990             rm = (modrm & 7) | REX_B(s);
4991             gen_op_mov_TN_reg[ot][1][rm]();
4992         }
4993         gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
4994         break;
4995         
4996         /************************/
4997         /* flags */
4998     case 0x9c: /* pushf */
4999         if (s->vm86 && s->iopl != 3) {
5000             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5001         } else {
5002             if (s->cc_op != CC_OP_DYNAMIC)
5003                 gen_op_set_cc_op(s->cc_op);
5004             gen_op_movl_T0_eflags();
5005             gen_push_T0(s);
5006         }
5007         break;
5008     case 0x9d: /* popf */
5009         if (s->vm86 && s->iopl != 3) {
5010             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5011         } else {
5012             gen_pop_T0(s);
5013             if (s->cpl == 0) {
5014                 if (s->dflag) {
5015                     gen_op_movl_eflags_T0_cpl0();
5016                 } else {
5017                     gen_op_movw_eflags_T0_cpl0();
5018                 }
5019             } else {
5020                 if (s->cpl <= s->iopl) {
5021                     if (s->dflag) {
5022                         gen_op_movl_eflags_T0_io();
5023                     } else {
5024                         gen_op_movw_eflags_T0_io();
5025                     }
5026                 } else {
5027                     if (s->dflag) {
5028                         gen_op_movl_eflags_T0();
5029                     } else {
5030                         gen_op_movw_eflags_T0();
5031                     }
5032                 }
5033             }
5034             gen_pop_update(s);
5035             s->cc_op = CC_OP_EFLAGS;
5036             /* abort translation because TF flag may change */
5037             gen_jmp_im(s->pc - s->cs_base);
5038             gen_eob(s);
5039         }
5040         break;
5041     case 0x9e: /* sahf */
5042         if (CODE64(s))
5043             goto illegal_op;
5044         gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
5045         if (s->cc_op != CC_OP_DYNAMIC)
5046             gen_op_set_cc_op(s->cc_op);
5047         gen_op_movb_eflags_T0();
5048         s->cc_op = CC_OP_EFLAGS;
5049         break;
5050     case 0x9f: /* lahf */
5051         if (CODE64(s))
5052             goto illegal_op;
5053         if (s->cc_op != CC_OP_DYNAMIC)
5054             gen_op_set_cc_op(s->cc_op);
5055         gen_op_movl_T0_eflags();
5056         gen_op_mov_reg_T0[OT_BYTE][R_AH]();
5057         break;
5058     case 0xf5: /* cmc */
5059         if (s->cc_op != CC_OP_DYNAMIC)
5060             gen_op_set_cc_op(s->cc_op);
5061         gen_op_cmc();
5062         s->cc_op = CC_OP_EFLAGS;
5063         break;
5064     case 0xf8: /* clc */
5065         if (s->cc_op != CC_OP_DYNAMIC)
5066             gen_op_set_cc_op(s->cc_op);
5067         gen_op_clc();
5068         s->cc_op = CC_OP_EFLAGS;
5069         break;
5070     case 0xf9: /* stc */
5071         if (s->cc_op != CC_OP_DYNAMIC)
5072             gen_op_set_cc_op(s->cc_op);
5073         gen_op_stc();
5074         s->cc_op = CC_OP_EFLAGS;
5075         break;
5076     case 0xfc: /* cld */
5077         gen_op_cld();
5078         break;
5079     case 0xfd: /* std */
5080         gen_op_std();
5081         break;
5082
5083         /************************/
5084         /* bit operations */
5085     case 0x1ba: /* bt/bts/btr/btc Gv, im */
5086         ot = dflag + OT_WORD;
5087         modrm = ldub_code(s->pc++);
5088         op = ((modrm >> 3) & 7) | rex_r;
5089         mod = (modrm >> 6) & 3;
5090         rm = (modrm & 7) | REX_B(s);
5091         if (mod != 3) {
5092             s->rip_offset = 1;
5093             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5094             gen_op_ld_T0_A0[ot + s->mem_index]();
5095         } else {
5096             gen_op_mov_TN_reg[ot][0][rm]();
5097         }
5098         /* load shift */
5099         val = ldub_code(s->pc++);
5100         gen_op_movl_T1_im(val);
5101         if (op < 4)
5102             goto illegal_op;
5103         op -= 4;
5104         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5105         s->cc_op = CC_OP_SARB + ot;
5106         if (op != 0) {
5107             if (mod != 3)
5108                 gen_op_st_T0_A0[ot + s->mem_index]();
5109             else
5110                 gen_op_mov_reg_T0[ot][rm]();
5111             gen_op_update_bt_cc();
5112         }
5113         break;
5114     case 0x1a3: /* bt Gv, Ev */
5115         op = 0;
5116         goto do_btx;
5117     case 0x1ab: /* bts */
5118         op = 1;
5119         goto do_btx;
5120     case 0x1b3: /* btr */
5121         op = 2;
5122         goto do_btx;
5123     case 0x1bb: /* btc */
5124         op = 3;
5125     do_btx:
5126         ot = dflag + OT_WORD;
5127         modrm = ldub_code(s->pc++);
5128         reg = ((modrm >> 3) & 7) | rex_r;
5129         mod = (modrm >> 6) & 3;
5130         rm = (modrm & 7) | REX_B(s);
5131         gen_op_mov_TN_reg[OT_LONG][1][reg]();
5132         if (mod != 3) {
5133             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5134             /* specific case: we need to add a displacement */
5135             gen_op_add_bit_A0_T1[ot - OT_WORD]();
5136             gen_op_ld_T0_A0[ot + s->mem_index]();
5137         } else {
5138             gen_op_mov_TN_reg[ot][0][rm]();
5139         }
5140         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
5141         s->cc_op = CC_OP_SARB + ot;
5142         if (op != 0) {
5143             if (mod != 3)
5144                 gen_op_st_T0_A0[ot + s->mem_index]();
5145             else
5146                 gen_op_mov_reg_T0[ot][rm]();
5147             gen_op_update_bt_cc();
5148         }
5149         break;
5150     case 0x1bc: /* bsf */
5151     case 0x1bd: /* bsr */
5152         ot = dflag + OT_WORD;
5153         modrm = ldub_code(s->pc++);
5154         reg = ((modrm >> 3) & 7) | rex_r;
5155         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5156         /* NOTE: in order to handle the 0 case, we must load the
5157            result. It could be optimized with a generated jump */
5158         gen_op_mov_TN_reg[ot][1][reg]();
5159         gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
5160         gen_op_mov_reg_T1[ot][reg]();
5161         s->cc_op = CC_OP_LOGICB + ot;
5162         break;
5163         /************************/
5164         /* bcd */
5165     case 0x27: /* daa */
5166         if (CODE64(s))
5167             goto illegal_op;
5168         if (s->cc_op != CC_OP_DYNAMIC)
5169             gen_op_set_cc_op(s->cc_op);
5170         gen_op_daa();
5171         s->cc_op = CC_OP_EFLAGS;
5172         break;
5173     case 0x2f: /* das */
5174         if (CODE64(s))
5175             goto illegal_op;
5176         if (s->cc_op != CC_OP_DYNAMIC)
5177             gen_op_set_cc_op(s->cc_op);
5178         gen_op_das();
5179         s->cc_op = CC_OP_EFLAGS;
5180         break;
5181     case 0x37: /* aaa */
5182         if (CODE64(s))
5183             goto illegal_op;
5184         if (s->cc_op != CC_OP_DYNAMIC)
5185             gen_op_set_cc_op(s->cc_op);
5186         gen_op_aaa();
5187         s->cc_op = CC_OP_EFLAGS;
5188         break;
5189     case 0x3f: /* aas */
5190         if (CODE64(s))
5191             goto illegal_op;
5192         if (s->cc_op != CC_OP_DYNAMIC)
5193             gen_op_set_cc_op(s->cc_op);
5194         gen_op_aas();
5195         s->cc_op = CC_OP_EFLAGS;
5196         break;
5197     case 0xd4: /* aam */
5198         if (CODE64(s))
5199             goto illegal_op;
5200         val = ldub_code(s->pc++);
5201         gen_op_aam(val);
5202         s->cc_op = CC_OP_LOGICB;
5203         break;
5204     case 0xd5: /* aad */
5205         if (CODE64(s))
5206             goto illegal_op;
5207         val = ldub_code(s->pc++);
5208         gen_op_aad(val);
5209         s->cc_op = CC_OP_LOGICB;
5210         break;
5211         /************************/
5212         /* misc */
5213     case 0x90: /* nop */
5214         /* XXX: xchg + rex handling */
5215         /* XXX: correct lock test for all insn */
5216         if (prefixes & PREFIX_LOCK)
5217             goto illegal_op;
5218         break;
5219     case 0x9b: /* fwait */
5220         if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == 
5221             (HF_MP_MASK | HF_TS_MASK)) {
5222             gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5223         } else {
5224             if (s->cc_op != CC_OP_DYNAMIC)
5225                 gen_op_set_cc_op(s->cc_op);
5226             gen_jmp_im(pc_start - s->cs_base);
5227             gen_op_fwait();
5228         }
5229         break;
5230     case 0xcc: /* int3 */
5231         gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
5232         break;
5233     case 0xcd: /* int N */
5234         val = ldub_code(s->pc++);
5235         if (s->vm86 && s->iopl != 3) {
5236             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 
5237         } else {
5238             gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
5239         }
5240         break;
5241     case 0xce: /* into */
5242         if (CODE64(s))
5243             goto illegal_op;
5244         if (s->cc_op != CC_OP_DYNAMIC)
5245             gen_op_set_cc_op(s->cc_op);
5246         gen_jmp_im(pc_start - s->cs_base);
5247         gen_op_into(s->pc - pc_start);
5248         break;
5249     case 0xf1: /* icebp (undocumented, exits to external debugger) */
5250 #if 1
5251         gen_debug(s, pc_start - s->cs_base);
5252 #else
5253         /* start debug */
5254         tb_flush(cpu_single_env);
5255         cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
5256 #endif
5257         break;
5258     case 0xfa: /* cli */
5259         if (!s->vm86) {
5260             if (s->cpl <= s->iopl) {
5261                 gen_op_cli();
5262             } else {
5263                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5264             }
5265         } else {
5266             if (s->iopl == 3) {
5267                 gen_op_cli();
5268             } else {
5269                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5270             }
5271         }
5272         break;
5273     case 0xfb: /* sti */
5274         if (!s->vm86) {
5275             if (s->cpl <= s->iopl) {
5276             gen_sti:
5277                 gen_op_sti();
5278                 /* interruptions are enabled only the first insn after sti */
5279                 /* If several instructions disable interrupts, only the
5280                    _first_ does it */
5281                 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
5282                     gen_op_set_inhibit_irq();
5283                 /* give a chance to handle pending irqs */
5284                 gen_jmp_im(s->pc - s->cs_base);
5285                 gen_eob(s);
5286             } else {
5287                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5288             }
5289         } else {
5290             if (s->iopl == 3) {
5291                 goto gen_sti;
5292             } else {
5293                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5294             }
5295         }
5296         break;
5297     case 0x62: /* bound */
5298         if (CODE64(s))
5299             goto illegal_op;
5300         ot = dflag ? OT_LONG : OT_WORD;
5301         modrm = ldub_code(s->pc++);
5302         reg = (modrm >> 3) & 7;
5303         mod = (modrm >> 6) & 3;
5304         if (mod == 3)
5305             goto illegal_op;
5306         gen_op_mov_TN_reg[ot][0][reg]();
5307         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5308         gen_jmp_im(pc_start - s->cs_base);
5309         if (ot == OT_WORD)
5310             gen_op_boundw();
5311         else
5312             gen_op_boundl();
5313         break;
5314     case 0x1c8 ... 0x1cf: /* bswap reg */
5315         reg = (b & 7) | REX_B(s);
5316 #ifdef TARGET_X86_64
5317         if (dflag == 2) {
5318             gen_op_mov_TN_reg[OT_QUAD][0][reg]();
5319             gen_op_bswapq_T0();
5320             gen_op_mov_reg_T0[OT_QUAD][reg]();
5321         } else 
5322 #endif
5323         {
5324             gen_op_mov_TN_reg[OT_LONG][0][reg]();
5325             gen_op_bswapl_T0();
5326             gen_op_mov_reg_T0[OT_LONG][reg]();
5327         }
5328         break;
5329     case 0xd6: /* salc */
5330         if (CODE64(s))
5331             goto illegal_op;
5332         if (s->cc_op != CC_OP_DYNAMIC)
5333             gen_op_set_cc_op(s->cc_op);
5334         gen_op_salc();
5335         break;
5336     case 0xe0: /* loopnz */
5337     case 0xe1: /* loopz */
5338         if (s->cc_op != CC_OP_DYNAMIC)
5339             gen_op_set_cc_op(s->cc_op);
5340         /* FALL THRU */
5341     case 0xe2: /* loop */
5342     case 0xe3: /* jecxz */
5343         {
5344             int l1, l2;
5345
5346             tval = (int8_t)insn_get(s, OT_BYTE);
5347             next_eip = s->pc - s->cs_base;
5348             tval += next_eip;
5349             if (s->dflag == 0)
5350                 tval &= 0xffff;
5351             
5352             l1 = gen_new_label();
5353             l2 = gen_new_label();
5354             b &= 3;
5355             if (b == 3) {
5356                 gen_op_jz_ecx[s->aflag](l1);
5357             } else {
5358                 gen_op_dec_ECX[s->aflag]();
5359                 if (b <= 1)
5360                     gen_op_mov_T0_cc();
5361                 gen_op_loop[s->aflag][b](l1);
5362             }
5363
5364             gen_jmp_im(next_eip);
5365             gen_op_jmp_label(l2);
5366             gen_set_label(l1);
5367             gen_jmp_im(tval);
5368             gen_set_label(l2);
5369             gen_eob(s);
5370         }
5371         break;
5372     case 0x130: /* wrmsr */
5373     case 0x132: /* rdmsr */
5374         if (s->cpl != 0) {
5375             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5376         } else {
5377             if (b & 2)
5378                 gen_op_rdmsr();
5379             else
5380                 gen_op_wrmsr();
5381         }
5382         break;
5383     case 0x131: /* rdtsc */
5384         gen_jmp_im(pc_start - s->cs_base);
5385         gen_op_rdtsc();
5386         break;
5387     case 0x134: /* sysenter */
5388         if (CODE64(s))
5389             goto illegal_op;
5390         if (!s->pe) {
5391             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5392         } else {
5393             if (s->cc_op != CC_OP_DYNAMIC) {
5394                 gen_op_set_cc_op(s->cc_op);
5395                 s->cc_op = CC_OP_DYNAMIC;
5396             }
5397             gen_jmp_im(pc_start - s->cs_base);
5398             gen_op_sysenter();
5399             gen_eob(s);
5400         }
5401         break;
5402     case 0x135: /* sysexit */
5403         if (CODE64(s))
5404             goto illegal_op;
5405         if (!s->pe) {
5406             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5407         } else {
5408             if (s->cc_op != CC_OP_DYNAMIC) {
5409                 gen_op_set_cc_op(s->cc_op);
5410                 s->cc_op = CC_OP_DYNAMIC;
5411             }
5412             gen_jmp_im(pc_start - s->cs_base);
5413             gen_op_sysexit();
5414             gen_eob(s);
5415         }
5416         break;
5417 #ifdef TARGET_X86_64
5418     case 0x105: /* syscall */
5419         /* XXX: is it usable in real mode ? */
5420         if (s->cc_op != CC_OP_DYNAMIC) {
5421             gen_op_set_cc_op(s->cc_op);
5422             s->cc_op = CC_OP_DYNAMIC;
5423         }
5424         gen_jmp_im(pc_start - s->cs_base);
5425         gen_op_syscall(s->pc - pc_start);
5426         gen_eob(s);
5427         break;
5428     case 0x107: /* sysret */
5429         if (!s->pe) {
5430             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5431         } else {
5432             if (s->cc_op != CC_OP_DYNAMIC) {
5433                 gen_op_set_cc_op(s->cc_op);
5434                 s->cc_op = CC_OP_DYNAMIC;
5435             }
5436             gen_jmp_im(pc_start - s->cs_base);
5437             gen_op_sysret(s->dflag);
5438             /* condition codes are modified only in long mode */
5439             if (s->lma)
5440                 s->cc_op = CC_OP_EFLAGS;
5441             gen_eob(s);
5442         }
5443         break;
5444 #endif
5445     case 0x1a2: /* cpuid */
5446         gen_op_cpuid();
5447         break;
5448     case 0xf4: /* hlt */
5449         if (s->cpl != 0) {
5450             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5451         } else {
5452             if (s->cc_op != CC_OP_DYNAMIC)
5453                 gen_op_set_cc_op(s->cc_op);
5454             gen_jmp_im(s->pc - s->cs_base);
5455             gen_op_hlt();
5456             s->is_jmp = 3;
5457         }
5458         break;
5459     case 0x100:
5460         modrm = ldub_code(s->pc++);
5461         mod = (modrm >> 6) & 3;
5462         op = (modrm >> 3) & 7;
5463         switch(op) {
5464         case 0: /* sldt */
5465             if (!s->pe || s->vm86)
5466                 goto illegal_op;
5467             gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
5468             ot = OT_WORD;
5469             if (mod == 3)
5470                 ot += s->dflag;
5471             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5472             break;
5473         case 2: /* lldt */
5474             if (!s->pe || s->vm86)
5475                 goto illegal_op;
5476             if (s->cpl != 0) {
5477                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5478             } else {
5479                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5480                 gen_jmp_im(pc_start - s->cs_base);
5481                 gen_op_lldt_T0();
5482             }
5483             break;
5484         case 1: /* str */
5485             if (!s->pe || s->vm86)
5486                 goto illegal_op;
5487             gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
5488             ot = OT_WORD;
5489             if (mod == 3)
5490                 ot += s->dflag;
5491             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
5492             break;
5493         case 3: /* ltr */
5494             if (!s->pe || s->vm86)
5495                 goto illegal_op;
5496             if (s->cpl != 0) {
5497                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5498             } else {
5499                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5500                 gen_jmp_im(pc_start - s->cs_base);
5501                 gen_op_ltr_T0();
5502             }
5503             break;
5504         case 4: /* verr */
5505         case 5: /* verw */
5506             if (!s->pe || s->vm86)
5507                 goto illegal_op;
5508             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5509             if (s->cc_op != CC_OP_DYNAMIC)
5510                 gen_op_set_cc_op(s->cc_op);
5511             if (op == 4)
5512                 gen_op_verr();
5513             else
5514                 gen_op_verw();
5515             s->cc_op = CC_OP_EFLAGS;
5516             break;
5517         default:
5518             goto illegal_op;
5519         }
5520         break;
5521     case 0x101:
5522         modrm = ldub_code(s->pc++);
5523         mod = (modrm >> 6) & 3;
5524         op = (modrm >> 3) & 7;
5525         switch(op) {
5526         case 0: /* sgdt */
5527         case 1: /* sidt */
5528             if (mod == 3)
5529                 goto illegal_op;
5530             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5531             if (op == 0)
5532                 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
5533             else
5534                 gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
5535             gen_op_st_T0_A0[OT_WORD + s->mem_index]();
5536             gen_add_A0_im(s, 2);
5537             if (op == 0)
5538                 gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base));
5539             else
5540                 gen_op_movtl_T0_env(offsetof(CPUX86State,idt.base));
5541             if (!s->dflag)
5542                 gen_op_andl_T0_im(0xffffff);
5543             gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5544             break;
5545         case 2: /* lgdt */
5546         case 3: /* lidt */
5547             if (mod == 3)
5548                 goto illegal_op;
5549             if (s->cpl != 0) {
5550                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5551             } else {
5552                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5553                 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
5554                 gen_add_A0_im(s, 2);
5555                 gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index]();
5556                 if (!s->dflag)
5557                     gen_op_andl_T0_im(0xffffff);
5558                 if (op == 2) {
5559                     gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base));
5560                     gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
5561                 } else {
5562                     gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base));
5563                     gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
5564                 }
5565             }
5566             break;
5567         case 4: /* smsw */
5568             gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
5569             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
5570             break;
5571         case 6: /* lmsw */
5572             if (s->cpl != 0) {
5573                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5574             } else {
5575                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
5576                 gen_op_lmsw_T0();
5577                 gen_jmp_im(s->pc - s->cs_base);
5578                 gen_eob(s);
5579             }
5580             break;
5581         case 7: /* invlpg */
5582             if (s->cpl != 0) {
5583                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5584             } else {
5585                 if (mod == 3) {
5586 #ifdef TARGET_X86_64
5587                     if (CODE64(s) && (modrm & 7) == 0) {
5588                         /* swapgs */
5589                         gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base));
5590                         gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase));
5591                         gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base));
5592                         gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase));
5593                     } else 
5594 #endif
5595                     {
5596                         goto illegal_op;
5597                     }
5598                 } else {
5599                     gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5600                     gen_op_invlpg_A0();
5601                     gen_jmp_im(s->pc - s->cs_base);
5602                     gen_eob(s);
5603                 }
5604             }
5605             break;
5606         default:
5607             goto illegal_op;
5608         }
5609         break;
5610     case 0x108: /* invd */
5611     case 0x109: /* wbinvd */
5612         if (s->cpl != 0) {
5613             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5614         } else {
5615             /* nothing to do */
5616         }
5617         break;
5618     case 0x63: /* arpl or movslS (x86_64) */
5619 #ifdef TARGET_X86_64
5620         if (CODE64(s)) {
5621             int d_ot;
5622             /* d_ot is the size of destination */
5623             d_ot = dflag + OT_WORD;
5624
5625             modrm = ldub_code(s->pc++);
5626             reg = ((modrm >> 3) & 7) | rex_r;
5627             mod = (modrm >> 6) & 3;
5628             rm = (modrm & 7) | REX_B(s);
5629             
5630             if (mod == 3) {
5631                 gen_op_mov_TN_reg[OT_LONG][0][rm]();
5632                 /* sign extend */
5633                 if (d_ot == OT_QUAD)
5634                     gen_op_movslq_T0_T0();
5635                 gen_op_mov_reg_T0[d_ot][reg]();
5636             } else {
5637                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5638                 if (d_ot == OT_QUAD) {
5639                     gen_op_lds_T0_A0[OT_LONG + s->mem_index]();
5640                 } else {
5641                     gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
5642                 }
5643                 gen_op_mov_reg_T0[d_ot][reg]();
5644             }
5645         } else 
5646 #endif
5647         {
5648             if (!s->pe || s->vm86)
5649                 goto illegal_op;
5650             ot = dflag ? OT_LONG : OT_WORD;
5651             modrm = ldub_code(s->pc++);
5652             reg = (modrm >> 3) & 7;
5653             mod = (modrm >> 6) & 3;
5654             rm = modrm & 7;
5655             if (mod != 3) {
5656                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5657                 gen_op_ld_T0_A0[ot + s->mem_index]();
5658             } else {
5659                 gen_op_mov_TN_reg[ot][0][rm]();
5660             }
5661             if (s->cc_op != CC_OP_DYNAMIC)
5662                 gen_op_set_cc_op(s->cc_op);
5663             gen_op_arpl();
5664             s->cc_op = CC_OP_EFLAGS;
5665             if (mod != 3) {
5666                 gen_op_st_T0_A0[ot + s->mem_index]();
5667             } else {
5668                 gen_op_mov_reg_T0[ot][rm]();
5669             }
5670             gen_op_arpl_update();
5671         }
5672         break;
5673     case 0x102: /* lar */
5674     case 0x103: /* lsl */
5675         if (!s->pe || s->vm86)
5676             goto illegal_op;
5677         ot = dflag ? OT_LONG : OT_WORD;
5678         modrm = ldub_code(s->pc++);
5679         reg = ((modrm >> 3) & 7) | rex_r;
5680         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
5681         gen_op_mov_TN_reg[ot][1][reg]();
5682         if (s->cc_op != CC_OP_DYNAMIC)
5683             gen_op_set_cc_op(s->cc_op);
5684         if (b == 0x102)
5685             gen_op_lar();
5686         else
5687             gen_op_lsl();
5688         s->cc_op = CC_OP_EFLAGS;
5689         gen_op_mov_reg_T1[ot][reg]();
5690         break;
5691     case 0x118:
5692         modrm = ldub_code(s->pc++);
5693         mod = (modrm >> 6) & 3;
5694         op = (modrm >> 3) & 7;
5695         switch(op) {
5696         case 0: /* prefetchnta */
5697         case 1: /* prefetchnt0 */
5698         case 2: /* prefetchnt0 */
5699         case 3: /* prefetchnt0 */
5700             if (mod == 3)
5701                 goto illegal_op;
5702             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5703             /* nothing more to do */
5704             break;
5705         default:
5706             goto illegal_op;
5707         }
5708         break;
5709     case 0x120: /* mov reg, crN */
5710     case 0x122: /* mov crN, reg */
5711         if (s->cpl != 0) {
5712             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5713         } else {
5714             modrm = ldub_code(s->pc++);
5715             if ((modrm & 0xc0) != 0xc0)
5716                 goto illegal_op;
5717             rm = (modrm & 7) | REX_B(s);
5718             reg = ((modrm >> 3) & 7) | rex_r;
5719             if (CODE64(s))
5720                 ot = OT_QUAD;
5721             else
5722                 ot = OT_LONG;
5723             switch(reg) {
5724             case 0:
5725             case 2:
5726             case 3:
5727             case 4:
5728             case 8:
5729                 if (b & 2) {
5730                     gen_op_mov_TN_reg[ot][0][rm]();
5731                     gen_op_movl_crN_T0(reg);
5732                     gen_jmp_im(s->pc - s->cs_base);
5733                     gen_eob(s);
5734                 } else {
5735 #if !defined(CONFIG_USER_ONLY) 
5736                     if (reg == 8)
5737                         gen_op_movtl_T0_cr8();
5738                     else
5739 #endif
5740                         gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg]));
5741                     gen_op_mov_reg_T0[ot][rm]();
5742                 }
5743                 break;
5744             default:
5745                 goto illegal_op;
5746             }
5747         }
5748         break;
5749     case 0x121: /* mov reg, drN */
5750     case 0x123: /* mov drN, reg */
5751         if (s->cpl != 0) {
5752             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5753         } else {
5754             modrm = ldub_code(s->pc++);
5755             if ((modrm & 0xc0) != 0xc0)
5756                 goto illegal_op;
5757             rm = (modrm & 7) | REX_B(s);
5758             reg = ((modrm >> 3) & 7) | rex_r;
5759             if (CODE64(s))
5760                 ot = OT_QUAD;
5761             else
5762                 ot = OT_LONG;
5763             /* XXX: do it dynamically with CR4.DE bit */
5764             if (reg == 4 || reg == 5 || reg >= 8)
5765                 goto illegal_op;
5766             if (b & 2) {
5767                 gen_op_mov_TN_reg[ot][0][rm]();
5768                 gen_op_movl_drN_T0(reg);
5769                 gen_jmp_im(s->pc - s->cs_base);
5770                 gen_eob(s);
5771             } else {
5772                 gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg]));
5773                 gen_op_mov_reg_T0[ot][rm]();
5774             }
5775         }
5776         break;
5777     case 0x106: /* clts */
5778         if (s->cpl != 0) {
5779             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
5780         } else {
5781             gen_op_clts();
5782             /* abort block because static cpu state changed */
5783             gen_jmp_im(s->pc - s->cs_base);
5784             gen_eob(s);
5785         }
5786         break;
5787     /* MMX/SSE/SSE2/PNI support */
5788     case 0x1c3: /* MOVNTI reg, mem */
5789         if (!(s->cpuid_features & CPUID_SSE2))
5790             goto illegal_op;
5791         ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
5792         modrm = ldub_code(s->pc++);
5793         mod = (modrm >> 6) & 3;
5794         if (mod == 3)
5795             goto illegal_op;
5796         reg = ((modrm >> 3) & 7) | rex_r;
5797         /* generate a generic store */
5798         gen_ldst_modrm(s, modrm, ot, reg, 1);
5799         break;
5800     case 0x1ae:
5801         modrm = ldub_code(s->pc++);
5802         mod = (modrm >> 6) & 3;
5803         op = (modrm >> 3) & 7;
5804         switch(op) {
5805         case 0: /* fxsave */
5806             if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
5807                 goto illegal_op;
5808             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5809             gen_op_fxsave_A0((s->dflag == 2));
5810             break;
5811         case 1: /* fxrstor */
5812             if (mod == 3 || !(s->cpuid_features & CPUID_FXSR))
5813                 goto illegal_op;
5814             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5815             gen_op_fxrstor_A0((s->dflag == 2));
5816             break;
5817         case 2: /* ldmxcsr */
5818         case 3: /* stmxcsr */
5819             if (s->flags & HF_TS_MASK) {
5820                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5821                 break;
5822             }
5823             if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
5824                 mod == 3)
5825                 goto illegal_op;
5826             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5827             if (op == 2) {
5828                 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
5829                 gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr));
5830             } else {
5831                 gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr));
5832                 gen_op_st_T0_A0[OT_LONG + s->mem_index]();
5833             }
5834             break;
5835         case 5: /* lfence */
5836         case 6: /* mfence */
5837             if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE))
5838                 goto illegal_op;
5839             break;
5840         case 7: /* sfence / clflush */
5841             if ((modrm & 0xc7) == 0xc0) {
5842                 /* sfence */
5843                 if (!(s->cpuid_features & CPUID_SSE))
5844                     goto illegal_op;
5845             } else {
5846                 /* clflush */
5847                 if (!(s->cpuid_features & CPUID_CLFLUSH))
5848                     goto illegal_op;
5849                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5850             }
5851             break;
5852         default:
5853             goto illegal_op;
5854         }
5855         break;
5856     case 0x10d: /* prefetch */
5857         modrm = ldub_code(s->pc++);
5858         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
5859         /* ignore for now */
5860         break;
5861     case 0x110 ... 0x117:
5862     case 0x128 ... 0x12f:
5863     case 0x150 ... 0x177:
5864     case 0x17c ... 0x17f:
5865     case 0x1c2:
5866     case 0x1c4 ... 0x1c6:
5867     case 0x1d0 ... 0x1fe:
5868         gen_sse(s, b, pc_start, rex_r);
5869         break;
5870     default:
5871         goto illegal_op;
5872     }
5873     /* lock generation */
5874     if (s->prefix & PREFIX_LOCK)
5875         gen_op_unlock();
5876     return s->pc;
5877  illegal_op:
5878     if (s->prefix & PREFIX_LOCK)
5879         gen_op_unlock();
5880     /* XXX: ensure that no lock was generated */
5881     gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
5882     return s->pc;
5883 }
5884
5885 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
5886 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
5887
5888 /* flags read by an operation */
5889 static uint16_t opc_read_flags[NB_OPS] = { 
5890     [INDEX_op_aas] = CC_A,
5891     [INDEX_op_aaa] = CC_A,
5892     [INDEX_op_das] = CC_A | CC_C,
5893     [INDEX_op_daa] = CC_A | CC_C,
5894
5895     /* subtle: due to the incl/decl implementation, C is used */
5896     [INDEX_op_update_inc_cc] = CC_C, 
5897
5898     [INDEX_op_into] = CC_O,
5899
5900     [INDEX_op_jb_subb] = CC_C,
5901     [INDEX_op_jb_subw] = CC_C,
5902     [INDEX_op_jb_subl] = CC_C,
5903
5904     [INDEX_op_jz_subb] = CC_Z,
5905     [INDEX_op_jz_subw] = CC_Z,
5906     [INDEX_op_jz_subl] = CC_Z,
5907
5908     [INDEX_op_jbe_subb] = CC_Z | CC_C,
5909     [INDEX_op_jbe_subw] = CC_Z | CC_C,
5910     [INDEX_op_jbe_subl] = CC_Z | CC_C,
5911
5912     [INDEX_op_js_subb] = CC_S,
5913     [INDEX_op_js_subw] = CC_S,
5914     [INDEX_op_js_subl] = CC_S,
5915
5916     [INDEX_op_jl_subb] = CC_O | CC_S,
5917     [INDEX_op_jl_subw] = CC_O | CC_S,
5918     [INDEX_op_jl_subl] = CC_O | CC_S,
5919
5920     [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
5921     [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
5922     [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
5923
5924     [INDEX_op_loopnzw] = CC_Z,
5925     [INDEX_op_loopnzl] = CC_Z,
5926     [INDEX_op_loopzw] = CC_Z,
5927     [INDEX_op_loopzl] = CC_Z,
5928
5929     [INDEX_op_seto_T0_cc] = CC_O,
5930     [INDEX_op_setb_T0_cc] = CC_C,
5931     [INDEX_op_setz_T0_cc] = CC_Z,
5932     [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
5933     [INDEX_op_sets_T0_cc] = CC_S,
5934     [INDEX_op_setp_T0_cc] = CC_P,
5935     [INDEX_op_setl_T0_cc] = CC_O | CC_S,
5936     [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
5937
5938     [INDEX_op_setb_T0_subb] = CC_C,
5939     [INDEX_op_setb_T0_subw] = CC_C,
5940     [INDEX_op_setb_T0_subl] = CC_C,
5941
5942     [INDEX_op_setz_T0_subb] = CC_Z,
5943     [INDEX_op_setz_T0_subw] = CC_Z,
5944     [INDEX_op_setz_T0_subl] = CC_Z,
5945
5946     [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
5947     [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
5948     [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
5949
5950     [INDEX_op_sets_T0_subb] = CC_S,
5951     [INDEX_op_sets_T0_subw] = CC_S,
5952     [INDEX_op_sets_T0_subl] = CC_S,
5953
5954     [INDEX_op_setl_T0_subb] = CC_O | CC_S,
5955     [INDEX_op_setl_T0_subw] = CC_O | CC_S,
5956     [INDEX_op_setl_T0_subl] = CC_O | CC_S,
5957
5958     [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
5959     [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
5960     [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
5961
5962     [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
5963     [INDEX_op_cmc] = CC_C,
5964     [INDEX_op_salc] = CC_C,
5965
5966     /* needed for correct flag optimisation before string ops */
5967     [INDEX_op_jnz_ecxw] = CC_OSZAPC,
5968     [INDEX_op_jnz_ecxl] = CC_OSZAPC,
5969     [INDEX_op_jz_ecxw] = CC_OSZAPC,
5970     [INDEX_op_jz_ecxl] = CC_OSZAPC,
5971
5972 #ifdef TARGET_X86_64
5973     [INDEX_op_jb_subq] = CC_C,
5974     [INDEX_op_jz_subq] = CC_Z,
5975     [INDEX_op_jbe_subq] = CC_Z | CC_C,
5976     [INDEX_op_js_subq] = CC_S,
5977     [INDEX_op_jl_subq] = CC_O | CC_S,
5978     [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z,
5979
5980     [INDEX_op_loopnzq] = CC_Z,
5981     [INDEX_op_loopzq] = CC_Z,
5982
5983     [INDEX_op_setb_T0_subq] = CC_C,
5984     [INDEX_op_setz_T0_subq] = CC_Z,
5985     [INDEX_op_setbe_T0_subq] = CC_Z | CC_C,
5986     [INDEX_op_sets_T0_subq] = CC_S,
5987     [INDEX_op_setl_T0_subq] = CC_O | CC_S,
5988     [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z,
5989
5990     [INDEX_op_jnz_ecxq] = CC_OSZAPC,
5991     [INDEX_op_jz_ecxq] = CC_OSZAPC,
5992 #endif
5993
5994 #define DEF_READF(SUFFIX)\
5995     [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
5996     [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
5997     [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
5998     X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
5999     [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6000     [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6001     [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6002     X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6003 \
6004     [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6005     [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6006     [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
6007     X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\
6008     [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
6009     [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
6010     [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\
6011     X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,)
6012
6013     DEF_READF( )
6014     DEF_READF(_raw)
6015 #ifndef CONFIG_USER_ONLY
6016     DEF_READF(_kernel)
6017     DEF_READF(_user)
6018 #endif
6019 };
6020
6021 /* flags written by an operation */
6022 static uint16_t opc_write_flags[NB_OPS] = { 
6023     [INDEX_op_update2_cc] = CC_OSZAPC,
6024     [INDEX_op_update1_cc] = CC_OSZAPC,
6025     [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
6026     [INDEX_op_update_neg_cc] = CC_OSZAPC,
6027     /* subtle: due to the incl/decl implementation, C is used */
6028     [INDEX_op_update_inc_cc] = CC_OSZAPC, 
6029     [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
6030
6031     [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
6032     [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
6033     [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
6034     X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,)
6035     [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
6036     [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
6037     [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
6038     X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,)
6039     [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
6040     [INDEX_op_imull_T0_T1] = CC_OSZAPC,
6041     X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,)
6042
6043     /* sse */
6044     [INDEX_op_ucomiss] = CC_OSZAPC,
6045     [INDEX_op_ucomisd] = CC_OSZAPC,
6046     [INDEX_op_comiss] = CC_OSZAPC,
6047     [INDEX_op_comisd] = CC_OSZAPC,
6048
6049     /* bcd */
6050     [INDEX_op_aam] = CC_OSZAPC,
6051     [INDEX_op_aad] = CC_OSZAPC,
6052     [INDEX_op_aas] = CC_OSZAPC,
6053     [INDEX_op_aaa] = CC_OSZAPC,
6054     [INDEX_op_das] = CC_OSZAPC,
6055     [INDEX_op_daa] = CC_OSZAPC,
6056
6057     [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
6058     [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
6059     [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
6060     [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
6061     [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
6062     [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
6063     [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
6064     [INDEX_op_clc] = CC_C,
6065     [INDEX_op_stc] = CC_C,
6066     [INDEX_op_cmc] = CC_C,
6067
6068     [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
6069     [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
6070     X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,)
6071     [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
6072     [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
6073     X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,)
6074     [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
6075     [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
6076     X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,)
6077     [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
6078     [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
6079     X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,)
6080
6081     [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
6082     [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
6083     X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,)
6084     [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
6085     [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
6086     X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,)
6087
6088     [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
6089     [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
6090     [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
6091     X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,)
6092
6093     [INDEX_op_cmpxchg8b] = CC_Z,
6094     [INDEX_op_lar] = CC_Z,
6095     [INDEX_op_lsl] = CC_Z,
6096     [INDEX_op_verr] = CC_Z,
6097     [INDEX_op_verw] = CC_Z,
6098     [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6099     [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
6100
6101 #define DEF_WRITEF(SUFFIX)\
6102     [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6103     [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6104     [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6105     X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6106     [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6107     [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6108     [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6109     X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6110 \
6111     [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6112     [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6113     [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6114     X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6115     [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6116     [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6117     [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6118     X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6119 \
6120     [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6121     [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6122     [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6123     X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6124     [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6125     [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6126     [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
6127     X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\
6128 \
6129     [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6130     [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6131     [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6132     X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6133 \
6134     [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6135     [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6136     [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6137     X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6138 \
6139     [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6140     [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6141     [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
6142     X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\
6143 \
6144     [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6145     [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6146     X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6147     [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6148     [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6149     X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6150 \
6151     [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6152     [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
6153     X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\
6154     [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6155     [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
6156     X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\
6157 \
6158     [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6159     [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6160     [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
6161     X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,)
6162
6163
6164     DEF_WRITEF( )
6165     DEF_WRITEF(_raw)
6166 #ifndef CONFIG_USER_ONLY
6167     DEF_WRITEF(_kernel)
6168     DEF_WRITEF(_user)
6169 #endif
6170 };
6171
6172 /* simpler form of an operation if no flags need to be generated */
6173 static uint16_t opc_simpler[NB_OPS] = { 
6174     [INDEX_op_update2_cc] = INDEX_op_nop,
6175     [INDEX_op_update1_cc] = INDEX_op_nop,
6176     [INDEX_op_update_neg_cc] = INDEX_op_nop,
6177 #if 0
6178     /* broken: CC_OP logic must be rewritten */
6179     [INDEX_op_update_inc_cc] = INDEX_op_nop,
6180 #endif
6181
6182     [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
6183     [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
6184     [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
6185     X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,)
6186
6187     [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
6188     [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
6189     [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
6190     X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,)
6191
6192     [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
6193     [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
6194     [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
6195     X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,)
6196
6197 #define DEF_SIMPLER(SUFFIX)\
6198     [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
6199     [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
6200     [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
6201     X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\
6202 \
6203     [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
6204     [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
6205     [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\
6206     X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,)
6207
6208     DEF_SIMPLER( )
6209     DEF_SIMPLER(_raw)
6210 #ifndef CONFIG_USER_ONLY
6211     DEF_SIMPLER(_kernel)
6212     DEF_SIMPLER(_user)
6213 #endif
6214 };
6215
6216 void optimize_flags_init(void)
6217 {
6218     int i;
6219     /* put default values in arrays */
6220     for(i = 0; i < NB_OPS; i++) {
6221         if (opc_simpler[i] == 0)
6222             opc_simpler[i] = i;
6223     }
6224 }
6225
6226 /* CPU flags computation optimization: we move backward thru the
6227    generated code to see which flags are needed. The operation is
6228    modified if suitable */
6229 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
6230 {
6231     uint16_t *opc_ptr;
6232     int live_flags, write_flags, op;
6233
6234     opc_ptr = opc_buf + opc_buf_len;
6235     /* live_flags contains the flags needed by the next instructions
6236        in the code. At the end of the bloc, we consider that all the
6237        flags are live. */
6238     live_flags = CC_OSZAPC;
6239     while (opc_ptr > opc_buf) {
6240         op = *--opc_ptr;
6241         /* if none of the flags written by the instruction is used,
6242            then we can try to find a simpler instruction */
6243         write_flags = opc_write_flags[op];
6244         if ((live_flags & write_flags) == 0) {
6245             *opc_ptr = opc_simpler[op];
6246         }
6247         /* compute the live flags before the instruction */
6248         live_flags &= ~write_flags;
6249         live_flags |= opc_read_flags[op];
6250     }
6251 }
6252
6253 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
6254    basic block 'tb'. If search_pc is TRUE, also generate PC
6255    information for each intermediate instruction. */
6256 static inline int gen_intermediate_code_internal(CPUState *env,
6257                                                  TranslationBlock *tb, 
6258                                                  int search_pc)
6259 {
6260     DisasContext dc1, *dc = &dc1;
6261     target_ulong pc_ptr;
6262     uint16_t *gen_opc_end;
6263     int flags, j, lj, cflags;
6264     target_ulong pc_start;
6265     target_ulong cs_base;
6266     
6267     /* generate intermediate code */
6268     pc_start = tb->pc;
6269     cs_base = tb->cs_base;
6270     flags = tb->flags;
6271     cflags = tb->cflags;
6272
6273     dc->pe = (flags >> HF_PE_SHIFT) & 1;
6274     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
6275     dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
6276     dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
6277     dc->f_st = 0;
6278     dc->vm86 = (flags >> VM_SHIFT) & 1;
6279     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
6280     dc->iopl = (flags >> IOPL_SHIFT) & 3;
6281     dc->tf = (flags >> TF_SHIFT) & 1;
6282     dc->singlestep_enabled = env->singlestep_enabled;
6283     dc->cc_op = CC_OP_DYNAMIC;
6284     dc->cs_base = cs_base;
6285     dc->tb = tb;
6286     dc->popl_esp_hack = 0;
6287     /* select memory access functions */
6288     dc->mem_index = 0;
6289     if (flags & HF_SOFTMMU_MASK) {
6290         if (dc->cpl == 3)
6291             dc->mem_index = 2 * 4;
6292         else
6293             dc->mem_index = 1 * 4;
6294     }
6295     dc->cpuid_features = env->cpuid_features;
6296 #ifdef TARGET_X86_64
6297     dc->lma = (flags >> HF_LMA_SHIFT) & 1;
6298     dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
6299 #endif
6300     dc->flags = flags;
6301     dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
6302                     (flags & HF_INHIBIT_IRQ_MASK)
6303 #ifndef CONFIG_SOFTMMU
6304                     || (flags & HF_SOFTMMU_MASK)
6305 #endif
6306                     );
6307 #if 0
6308     /* check addseg logic */
6309     if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
6310         printf("ERROR addseg\n");
6311 #endif
6312
6313     gen_opc_ptr = gen_opc_buf;
6314     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6315     gen_opparam_ptr = gen_opparam_buf;
6316     nb_gen_labels = 0;
6317
6318     dc->is_jmp = DISAS_NEXT;
6319     pc_ptr = pc_start;
6320     lj = -1;
6321
6322     for(;;) {
6323         if (env->nb_breakpoints > 0) {
6324             for(j = 0; j < env->nb_breakpoints; j++) {
6325                 if (env->breakpoints[j] == pc_ptr) {
6326                     gen_debug(dc, pc_ptr - dc->cs_base);
6327                     break;
6328                 }
6329             }
6330         }
6331         if (search_pc) {
6332             j = gen_opc_ptr - gen_opc_buf;
6333             if (lj < j) {
6334                 lj++;
6335                 while (lj < j)
6336                     gen_opc_instr_start[lj++] = 0;
6337             }
6338             gen_opc_pc[lj] = pc_ptr;
6339             gen_opc_cc_op[lj] = dc->cc_op;
6340             gen_opc_instr_start[lj] = 1;
6341         }
6342         pc_ptr = disas_insn(dc, pc_ptr);
6343         /* stop translation if indicated */
6344         if (dc->is_jmp)
6345             break;
6346         /* if single step mode, we generate only one instruction and
6347            generate an exception */
6348         /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
6349            the flag and abort the translation to give the irqs a
6350            change to be happen */
6351         if (dc->tf || dc->singlestep_enabled || 
6352             (flags & HF_INHIBIT_IRQ_MASK) ||
6353             (cflags & CF_SINGLE_INSN)) {
6354             gen_jmp_im(pc_ptr - dc->cs_base);
6355             gen_eob(dc);
6356             break;
6357         }
6358         /* if too long translation, stop generation too */
6359         if (gen_opc_ptr >= gen_opc_end ||
6360             (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
6361             gen_jmp_im(pc_ptr - dc->cs_base);
6362             gen_eob(dc);
6363             break;
6364         }
6365     }
6366     *gen_opc_ptr = INDEX_op_end;
6367     /* we don't forget to fill the last values */
6368     if (search_pc) {
6369         j = gen_opc_ptr - gen_opc_buf;
6370         lj++;
6371         while (lj <= j)
6372             gen_opc_instr_start[lj++] = 0;
6373     }
6374         
6375 #ifdef DEBUG_DISAS
6376     if (loglevel & CPU_LOG_TB_CPU) {
6377         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
6378     }
6379     if (loglevel & CPU_LOG_TB_IN_ASM) {
6380         int disas_flags;
6381         fprintf(logfile, "----------------\n");
6382         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6383 #ifdef TARGET_X86_64
6384         if (dc->code64)
6385             disas_flags = 2;
6386         else
6387 #endif
6388             disas_flags = !dc->code32;
6389         target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags);
6390         fprintf(logfile, "\n");
6391         if (loglevel & CPU_LOG_TB_OP) {
6392             fprintf(logfile, "OP:\n");
6393             dump_ops(gen_opc_buf, gen_opparam_buf);
6394             fprintf(logfile, "\n");
6395         }
6396     }
6397 #endif
6398
6399     /* optimize flag computations */
6400     optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
6401
6402 #ifdef DEBUG_DISAS
6403     if (loglevel & CPU_LOG_TB_OP_OPT) {
6404         fprintf(logfile, "AFTER FLAGS OPT:\n");
6405         dump_ops(gen_opc_buf, gen_opparam_buf);
6406         fprintf(logfile, "\n");
6407     }
6408 #endif
6409     if (!search_pc)
6410         tb->size = pc_ptr - pc_start;
6411     return 0;
6412 }
6413
6414 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
6415 {
6416     return gen_intermediate_code_internal(env, tb, 0);
6417 }
6418
6419 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
6420 {
6421     return gen_intermediate_code_internal(env, tb, 1);
6422 }
6423