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