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