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