precise self modifying code support
[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 0x82:
1942     case 0x83:
1943         {
1944             int val;
1945
1946             if ((b & 1) == 0)
1947                 ot = OT_BYTE;
1948             else
1949                 ot = dflag ? OT_LONG : OT_WORD;
1950             
1951             modrm = ldub_code(s->pc++);
1952             mod = (modrm >> 6) & 3;
1953             rm = modrm & 7;
1954             op = (modrm >> 3) & 7;
1955             
1956             if (mod != 3) {
1957                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
1958                 opreg = OR_TMP0;
1959             } else {
1960                 opreg = rm + OR_EAX;
1961             }
1962
1963             switch(b) {
1964             default:
1965             case 0x80:
1966             case 0x81:
1967             case 0x82:
1968                 val = insn_get(s, ot);
1969                 break;
1970             case 0x83:
1971                 val = (int8_t)insn_get(s, OT_BYTE);
1972                 break;
1973             }
1974             gen_op_movl_T1_im(val);
1975             gen_op(s, op, ot, opreg);
1976         }
1977         break;
1978
1979         /**************************/
1980         /* inc, dec, and other misc arith */
1981     case 0x40 ... 0x47: /* inc Gv */
1982         ot = dflag ? OT_LONG : OT_WORD;
1983         gen_inc(s, ot, OR_EAX + (b & 7), 1);
1984         break;
1985     case 0x48 ... 0x4f: /* dec Gv */
1986         ot = dflag ? OT_LONG : OT_WORD;
1987         gen_inc(s, ot, OR_EAX + (b & 7), -1);
1988         break;
1989     case 0xf6: /* GRP3 */
1990     case 0xf7:
1991         if ((b & 1) == 0)
1992             ot = OT_BYTE;
1993         else
1994             ot = dflag ? OT_LONG : OT_WORD;
1995
1996         modrm = ldub_code(s->pc++);
1997         mod = (modrm >> 6) & 3;
1998         rm = modrm & 7;
1999         op = (modrm >> 3) & 7;
2000         if (mod != 3) {
2001             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2002             gen_op_ld_T0_A0[ot + s->mem_index]();
2003         } else {
2004             gen_op_mov_TN_reg[ot][0][rm]();
2005         }
2006
2007         switch(op) {
2008         case 0: /* test */
2009             val = insn_get(s, ot);
2010             gen_op_movl_T1_im(val);
2011             gen_op_testl_T0_T1_cc();
2012             s->cc_op = CC_OP_LOGICB + ot;
2013             break;
2014         case 2: /* not */
2015             gen_op_notl_T0();
2016             if (mod != 3) {
2017                 gen_op_st_T0_A0[ot + s->mem_index]();
2018             } else {
2019                 gen_op_mov_reg_T0[ot][rm]();
2020             }
2021             break;
2022         case 3: /* neg */
2023             gen_op_negl_T0();
2024             if (mod != 3) {
2025                 gen_op_st_T0_A0[ot + s->mem_index]();
2026             } else {
2027                 gen_op_mov_reg_T0[ot][rm]();
2028             }
2029             gen_op_update_neg_cc();
2030             s->cc_op = CC_OP_SUBB + ot;
2031             break;
2032         case 4: /* mul */
2033             switch(ot) {
2034             case OT_BYTE:
2035                 gen_op_mulb_AL_T0();
2036                 s->cc_op = CC_OP_MULB;
2037                 break;
2038             case OT_WORD:
2039                 gen_op_mulw_AX_T0();
2040                 s->cc_op = CC_OP_MULW;
2041                 break;
2042             default:
2043             case OT_LONG:
2044                 gen_op_mull_EAX_T0();
2045                 s->cc_op = CC_OP_MULL;
2046                 break;
2047             }
2048             break;
2049         case 5: /* imul */
2050             switch(ot) {
2051             case OT_BYTE:
2052                 gen_op_imulb_AL_T0();
2053                 s->cc_op = CC_OP_MULB;
2054                 break;
2055             case OT_WORD:
2056                 gen_op_imulw_AX_T0();
2057                 s->cc_op = CC_OP_MULW;
2058                 break;
2059             default:
2060             case OT_LONG:
2061                 gen_op_imull_EAX_T0();
2062                 s->cc_op = CC_OP_MULL;
2063                 break;
2064             }
2065             break;
2066         case 6: /* div */
2067             switch(ot) {
2068             case OT_BYTE:
2069                 gen_op_divb_AL_T0(pc_start - s->cs_base);
2070                 break;
2071             case OT_WORD:
2072                 gen_op_divw_AX_T0(pc_start - s->cs_base);
2073                 break;
2074             default:
2075             case OT_LONG:
2076                 gen_op_divl_EAX_T0(pc_start - s->cs_base);
2077                 break;
2078             }
2079             break;
2080         case 7: /* idiv */
2081             switch(ot) {
2082             case OT_BYTE:
2083                 gen_op_idivb_AL_T0(pc_start - s->cs_base);
2084                 break;
2085             case OT_WORD:
2086                 gen_op_idivw_AX_T0(pc_start - s->cs_base);
2087                 break;
2088             default:
2089             case OT_LONG:
2090                 gen_op_idivl_EAX_T0(pc_start - s->cs_base);
2091                 break;
2092             }
2093             break;
2094         default:
2095             goto illegal_op;
2096         }
2097         break;
2098
2099     case 0xfe: /* GRP4 */
2100     case 0xff: /* GRP5 */
2101         if ((b & 1) == 0)
2102             ot = OT_BYTE;
2103         else
2104             ot = dflag ? OT_LONG : OT_WORD;
2105
2106         modrm = ldub_code(s->pc++);
2107         mod = (modrm >> 6) & 3;
2108         rm = modrm & 7;
2109         op = (modrm >> 3) & 7;
2110         if (op >= 2 && b == 0xfe) {
2111             goto illegal_op;
2112         }
2113         if (mod != 3) {
2114             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2115             if (op >= 2 && op != 3 && op != 5)
2116                 gen_op_ld_T0_A0[ot + s->mem_index]();
2117         } else {
2118             gen_op_mov_TN_reg[ot][0][rm]();
2119         }
2120
2121         switch(op) {
2122         case 0: /* inc Ev */
2123             if (mod != 3)
2124                 opreg = OR_TMP0;
2125             else
2126                 opreg = rm;
2127             gen_inc(s, ot, opreg, 1);
2128             break;
2129         case 1: /* dec Ev */
2130             if (mod != 3)
2131                 opreg = OR_TMP0;
2132             else
2133                 opreg = rm;
2134             gen_inc(s, ot, opreg, -1);
2135             break;
2136         case 2: /* call Ev */
2137             /* XXX: optimize if memory (no 'and' is necessary) */
2138             if (s->dflag == 0)
2139                 gen_op_andl_T0_ffff();
2140             next_eip = s->pc - s->cs_base;
2141             gen_op_movl_T1_im(next_eip);
2142             gen_push_T1(s);
2143             gen_op_jmp_T0();
2144             gen_eob(s);
2145             break;
2146         case 3: /* lcall Ev */
2147             gen_op_ld_T1_A0[ot + s->mem_index]();
2148             gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2149             gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2150         do_lcall:
2151             if (s->pe && !s->vm86) {
2152                 if (s->cc_op != CC_OP_DYNAMIC)
2153                     gen_op_set_cc_op(s->cc_op);
2154                 gen_op_jmp_im(pc_start - s->cs_base);
2155                 gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
2156             } else {
2157                 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
2158             }
2159             gen_eob(s);
2160             break;
2161         case 4: /* jmp Ev */
2162             if (s->dflag == 0)
2163                 gen_op_andl_T0_ffff();
2164             gen_op_jmp_T0();
2165             gen_eob(s);
2166             break;
2167         case 5: /* ljmp Ev */
2168             gen_op_ld_T1_A0[ot + s->mem_index]();
2169             gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2170             gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2171         do_ljmp:
2172             if (s->pe && !s->vm86) {
2173                 if (s->cc_op != CC_OP_DYNAMIC)
2174                     gen_op_set_cc_op(s->cc_op);
2175                 gen_op_jmp_im(pc_start - s->cs_base);
2176                 gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base);
2177             } else {
2178                 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
2179                 gen_op_movl_T0_T1();
2180                 gen_op_jmp_T0();
2181             }
2182             gen_eob(s);
2183             break;
2184         case 6: /* push Ev */
2185             gen_push_T0(s);
2186             break;
2187         default:
2188             goto illegal_op;
2189         }
2190         break;
2191
2192     case 0x84: /* test Ev, Gv */
2193     case 0x85: 
2194         if ((b & 1) == 0)
2195             ot = OT_BYTE;
2196         else
2197             ot = dflag ? OT_LONG : OT_WORD;
2198
2199         modrm = ldub_code(s->pc++);
2200         mod = (modrm >> 6) & 3;
2201         rm = modrm & 7;
2202         reg = (modrm >> 3) & 7;
2203         
2204         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2205         gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
2206         gen_op_testl_T0_T1_cc();
2207         s->cc_op = CC_OP_LOGICB + ot;
2208         break;
2209         
2210     case 0xa8: /* test eAX, Iv */
2211     case 0xa9:
2212         if ((b & 1) == 0)
2213             ot = OT_BYTE;
2214         else
2215             ot = dflag ? OT_LONG : OT_WORD;
2216         val = insn_get(s, ot);
2217
2218         gen_op_mov_TN_reg[ot][0][OR_EAX]();
2219         gen_op_movl_T1_im(val);
2220         gen_op_testl_T0_T1_cc();
2221         s->cc_op = CC_OP_LOGICB + ot;
2222         break;
2223         
2224     case 0x98: /* CWDE/CBW */
2225         if (dflag)
2226             gen_op_movswl_EAX_AX();
2227         else
2228             gen_op_movsbw_AX_AL();
2229         break;
2230     case 0x99: /* CDQ/CWD */
2231         if (dflag)
2232             gen_op_movslq_EDX_EAX();
2233         else
2234             gen_op_movswl_DX_AX();
2235         break;
2236     case 0x1af: /* imul Gv, Ev */
2237     case 0x69: /* imul Gv, Ev, I */
2238     case 0x6b:
2239         ot = dflag ? OT_LONG : OT_WORD;
2240         modrm = ldub_code(s->pc++);
2241         reg = ((modrm >> 3) & 7) + OR_EAX;
2242         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2243         if (b == 0x69) {
2244             val = insn_get(s, ot);
2245             gen_op_movl_T1_im(val);
2246         } else if (b == 0x6b) {
2247             val = (int8_t)insn_get(s, OT_BYTE);
2248             gen_op_movl_T1_im(val);
2249         } else {
2250             gen_op_mov_TN_reg[ot][1][reg]();
2251         }
2252
2253         if (ot == OT_LONG) {
2254             gen_op_imull_T0_T1();
2255         } else {
2256             gen_op_imulw_T0_T1();
2257         }
2258         gen_op_mov_reg_T0[ot][reg]();
2259         s->cc_op = CC_OP_MULB + ot;
2260         break;
2261     case 0x1c0:
2262     case 0x1c1: /* xadd Ev, Gv */
2263         if ((b & 1) == 0)
2264             ot = OT_BYTE;
2265         else
2266             ot = dflag ? OT_LONG : OT_WORD;
2267         modrm = ldub_code(s->pc++);
2268         reg = (modrm >> 3) & 7;
2269         mod = (modrm >> 6) & 3;
2270         if (mod == 3) {
2271             rm = modrm & 7;
2272             gen_op_mov_TN_reg[ot][0][reg]();
2273             gen_op_mov_TN_reg[ot][1][rm]();
2274             gen_op_addl_T0_T1();
2275             gen_op_mov_reg_T1[ot][reg]();
2276             gen_op_mov_reg_T0[ot][rm]();
2277         } else {
2278             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2279             gen_op_mov_TN_reg[ot][0][reg]();
2280             gen_op_ld_T1_A0[ot + s->mem_index]();
2281             gen_op_addl_T0_T1();
2282             gen_op_st_T0_A0[ot + s->mem_index]();
2283             gen_op_mov_reg_T1[ot][reg]();
2284         }
2285         gen_op_update2_cc();
2286         s->cc_op = CC_OP_ADDB + ot;
2287         break;
2288     case 0x1b0:
2289     case 0x1b1: /* cmpxchg Ev, Gv */
2290         if ((b & 1) == 0)
2291             ot = OT_BYTE;
2292         else
2293             ot = dflag ? OT_LONG : OT_WORD;
2294         modrm = ldub_code(s->pc++);
2295         reg = (modrm >> 3) & 7;
2296         mod = (modrm >> 6) & 3;
2297         gen_op_mov_TN_reg[ot][1][reg]();
2298         if (mod == 3) {
2299             rm = modrm & 7;
2300             gen_op_mov_TN_reg[ot][0][rm]();
2301             gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
2302             gen_op_mov_reg_T0[ot][rm]();
2303         } else {
2304             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2305             gen_op_ld_T0_A0[ot + s->mem_index]();
2306             gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
2307         }
2308         s->cc_op = CC_OP_SUBB + ot;
2309         break;
2310     case 0x1c7: /* cmpxchg8b */
2311         modrm = ldub_code(s->pc++);
2312         mod = (modrm >> 6) & 3;
2313         if (mod == 3)
2314             goto illegal_op;
2315         if (s->cc_op != CC_OP_DYNAMIC)
2316             gen_op_set_cc_op(s->cc_op);
2317         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2318         gen_op_cmpxchg8b();
2319         s->cc_op = CC_OP_EFLAGS;
2320         break;
2321         
2322         /**************************/
2323         /* push/pop */
2324     case 0x50 ... 0x57: /* push */
2325         gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
2326         gen_push_T0(s);
2327         break;
2328     case 0x58 ... 0x5f: /* pop */
2329         ot = dflag ? OT_LONG : OT_WORD;
2330         gen_pop_T0(s);
2331         /* NOTE: order is important for pop %sp */
2332         gen_pop_update(s);
2333         gen_op_mov_reg_T0[ot][b & 7]();
2334         break;
2335     case 0x60: /* pusha */
2336         gen_pusha(s);
2337         break;
2338     case 0x61: /* popa */
2339         gen_popa(s);
2340         break;
2341     case 0x68: /* push Iv */
2342     case 0x6a:
2343         ot = dflag ? OT_LONG : OT_WORD;
2344         if (b == 0x68)
2345             val = insn_get(s, ot);
2346         else
2347             val = (int8_t)insn_get(s, OT_BYTE);
2348         gen_op_movl_T0_im(val);
2349         gen_push_T0(s);
2350         break;
2351     case 0x8f: /* pop Ev */
2352         ot = dflag ? OT_LONG : OT_WORD;
2353         modrm = ldub_code(s->pc++);
2354         mod = (modrm >> 6) & 3;
2355         gen_pop_T0(s);
2356         if (mod == 3) {
2357             /* NOTE: order is important for pop %sp */
2358             gen_pop_update(s);
2359             rm = modrm & 7;
2360             gen_op_mov_reg_T0[ot][rm]();
2361         } else {
2362             /* NOTE: order is important too for MMU exceptions */
2363             s->popl_esp_hack = 2 << dflag;
2364             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2365             s->popl_esp_hack = 0;
2366             gen_pop_update(s);
2367         }
2368         break;
2369     case 0xc8: /* enter */
2370         {
2371             int level;
2372             val = lduw_code(s->pc);
2373             s->pc += 2;
2374             level = ldub_code(s->pc++);
2375             gen_enter(s, val, level);
2376         }
2377         break;
2378     case 0xc9: /* leave */
2379         /* XXX: exception not precise (ESP is updated before potential exception) */
2380         if (s->ss32) {
2381             gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2382             gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2383         } else {
2384             gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2385             gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2386         }
2387         gen_pop_T0(s);
2388         ot = dflag ? OT_LONG : OT_WORD;
2389         gen_op_mov_reg_T0[ot][R_EBP]();
2390         gen_pop_update(s);
2391         break;
2392     case 0x06: /* push es */
2393     case 0x0e: /* push cs */
2394     case 0x16: /* push ss */
2395     case 0x1e: /* push ds */
2396         gen_op_movl_T0_seg(b >> 3);
2397         gen_push_T0(s);
2398         break;
2399     case 0x1a0: /* push fs */
2400     case 0x1a8: /* push gs */
2401         gen_op_movl_T0_seg((b >> 3) & 7);
2402         gen_push_T0(s);
2403         break;
2404     case 0x07: /* pop es */
2405     case 0x17: /* pop ss */
2406     case 0x1f: /* pop ds */
2407         reg = b >> 3;
2408         gen_pop_T0(s);
2409         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2410         gen_pop_update(s);
2411         if (reg == R_SS) {
2412             /* if reg == SS, inhibit interrupts/trace. */
2413             /* If several instructions disable interrupts, only the
2414                _first_ does it */
2415             if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
2416                 gen_op_set_inhibit_irq();
2417             s->tf = 0;
2418         }
2419         if (s->is_jmp) {
2420             gen_op_jmp_im(s->pc - s->cs_base);
2421             gen_eob(s);
2422         }
2423         break;
2424     case 0x1a1: /* pop fs */
2425     case 0x1a9: /* pop gs */
2426         gen_pop_T0(s);
2427         gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2428         gen_pop_update(s);
2429         if (s->is_jmp) {
2430             gen_op_jmp_im(s->pc - s->cs_base);
2431             gen_eob(s);
2432         }
2433         break;
2434
2435         /**************************/
2436         /* mov */
2437     case 0x88:
2438     case 0x89: /* mov Gv, Ev */
2439         if ((b & 1) == 0)
2440             ot = OT_BYTE;
2441         else
2442             ot = dflag ? OT_LONG : OT_WORD;
2443         modrm = ldub_code(s->pc++);
2444         reg = (modrm >> 3) & 7;
2445         
2446         /* generate a generic store */
2447         gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2448         break;
2449     case 0xc6:
2450     case 0xc7: /* mov Ev, Iv */
2451         if ((b & 1) == 0)
2452             ot = OT_BYTE;
2453         else
2454             ot = dflag ? OT_LONG : OT_WORD;
2455         modrm = ldub_code(s->pc++);
2456         mod = (modrm >> 6) & 3;
2457         if (mod != 3)
2458             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2459         val = insn_get(s, ot);
2460         gen_op_movl_T0_im(val);
2461         if (mod != 3)
2462             gen_op_st_T0_A0[ot + s->mem_index]();
2463         else
2464             gen_op_mov_reg_T0[ot][modrm & 7]();
2465         break;
2466     case 0x8a:
2467     case 0x8b: /* mov Ev, Gv */
2468         if ((b & 1) == 0)
2469             ot = OT_BYTE;
2470         else
2471             ot = dflag ? OT_LONG : OT_WORD;
2472         modrm = ldub_code(s->pc++);
2473         reg = (modrm >> 3) & 7;
2474         
2475         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2476         gen_op_mov_reg_T0[ot][reg]();
2477         break;
2478     case 0x8e: /* mov seg, Gv */
2479         modrm = ldub_code(s->pc++);
2480         reg = (modrm >> 3) & 7;
2481         if (reg >= 6 || reg == R_CS)
2482             goto illegal_op;
2483         gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2484         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2485         if (reg == R_SS) {
2486             /* if reg == SS, inhibit interrupts/trace */
2487             /* If several instructions disable interrupts, only the
2488                _first_ does it */
2489             if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
2490                 gen_op_set_inhibit_irq();
2491             s->tf = 0;
2492         }
2493         if (s->is_jmp) {
2494             gen_op_jmp_im(s->pc - s->cs_base);
2495             gen_eob(s);
2496         }
2497         break;
2498     case 0x8c: /* mov Gv, seg */
2499         modrm = ldub_code(s->pc++);
2500         reg = (modrm >> 3) & 7;
2501         mod = (modrm >> 6) & 3;
2502         if (reg >= 6)
2503             goto illegal_op;
2504         gen_op_movl_T0_seg(reg);
2505         ot = OT_WORD;
2506         if (mod == 3 && dflag)
2507             ot = OT_LONG;
2508         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2509         break;
2510
2511     case 0x1b6: /* movzbS Gv, Eb */
2512     case 0x1b7: /* movzwS Gv, Eb */
2513     case 0x1be: /* movsbS Gv, Eb */
2514     case 0x1bf: /* movswS Gv, Eb */
2515         {
2516             int d_ot;
2517             /* d_ot is the size of destination */
2518             d_ot = dflag + OT_WORD;
2519             /* ot is the size of source */
2520             ot = (b & 1) + OT_BYTE;
2521             modrm = ldub_code(s->pc++);
2522             reg = ((modrm >> 3) & 7) + OR_EAX;
2523             mod = (modrm >> 6) & 3;
2524             rm = modrm & 7;
2525             
2526             if (mod == 3) {
2527                 gen_op_mov_TN_reg[ot][0][rm]();
2528                 switch(ot | (b & 8)) {
2529                 case OT_BYTE:
2530                     gen_op_movzbl_T0_T0();
2531                     break;
2532                 case OT_BYTE | 8:
2533                     gen_op_movsbl_T0_T0();
2534                     break;
2535                 case OT_WORD:
2536                     gen_op_movzwl_T0_T0();
2537                     break;
2538                 default:
2539                 case OT_WORD | 8:
2540                     gen_op_movswl_T0_T0();
2541                     break;
2542                 }
2543                 gen_op_mov_reg_T0[d_ot][reg]();
2544             } else {
2545                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2546                 if (b & 8) {
2547                     gen_op_lds_T0_A0[ot + s->mem_index]();
2548                 } else {
2549                     gen_op_ldu_T0_A0[ot + s->mem_index]();
2550                 }
2551                 gen_op_mov_reg_T0[d_ot][reg]();
2552             }
2553         }
2554         break;
2555
2556     case 0x8d: /* lea */
2557         ot = dflag ? OT_LONG : OT_WORD;
2558         modrm = ldub_code(s->pc++);
2559         mod = (modrm >> 6) & 3;
2560         if (mod == 3)
2561             goto illegal_op;
2562         reg = (modrm >> 3) & 7;
2563         /* we must ensure that no segment is added */
2564         s->override = -1;
2565         val = s->addseg;
2566         s->addseg = 0;
2567         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2568         s->addseg = val;
2569         gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2570         break;
2571         
2572     case 0xa0: /* mov EAX, Ov */
2573     case 0xa1:
2574     case 0xa2: /* mov Ov, EAX */
2575     case 0xa3:
2576         if ((b & 1) == 0)
2577             ot = OT_BYTE;
2578         else
2579             ot = dflag ? OT_LONG : OT_WORD;
2580         if (s->aflag)
2581             offset_addr = insn_get(s, OT_LONG);
2582         else
2583             offset_addr = insn_get(s, OT_WORD);
2584         gen_op_movl_A0_im(offset_addr);
2585         /* handle override */
2586         {
2587             int override, must_add_seg;
2588             must_add_seg = s->addseg;
2589             if (s->override >= 0) {
2590                 override = s->override;
2591                 must_add_seg = 1;
2592             } else {
2593                 override = R_DS;
2594             }
2595             if (must_add_seg) {
2596                 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2597             }
2598         }
2599         if ((b & 2) == 0) {
2600             gen_op_ld_T0_A0[ot + s->mem_index]();
2601             gen_op_mov_reg_T0[ot][R_EAX]();
2602         } else {
2603             gen_op_mov_TN_reg[ot][0][R_EAX]();
2604             gen_op_st_T0_A0[ot + s->mem_index]();
2605         }
2606         break;
2607     case 0xd7: /* xlat */
2608         gen_op_movl_A0_reg[R_EBX]();
2609         gen_op_addl_A0_AL();
2610         if (s->aflag == 0)
2611             gen_op_andl_A0_ffff();
2612         /* handle override */
2613         {
2614             int override, must_add_seg;
2615             must_add_seg = s->addseg;
2616             override = R_DS;
2617             if (s->override >= 0) {
2618                 override = s->override;
2619                 must_add_seg = 1;
2620             } else {
2621                 override = R_DS;
2622             }
2623             if (must_add_seg) {
2624                 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2625             }
2626         }
2627         gen_op_ldu_T0_A0[OT_BYTE + s->mem_index]();
2628         gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2629         break;
2630     case 0xb0 ... 0xb7: /* mov R, Ib */
2631         val = insn_get(s, OT_BYTE);
2632         gen_op_movl_T0_im(val);
2633         gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2634         break;
2635     case 0xb8 ... 0xbf: /* mov R, Iv */
2636         ot = dflag ? OT_LONG : OT_WORD;
2637         val = insn_get(s, ot);
2638         reg = OR_EAX + (b & 7);
2639         gen_op_movl_T0_im(val);
2640         gen_op_mov_reg_T0[ot][reg]();
2641         break;
2642
2643     case 0x91 ... 0x97: /* xchg R, EAX */
2644         ot = dflag ? OT_LONG : OT_WORD;
2645         reg = b & 7;
2646         rm = R_EAX;
2647         goto do_xchg_reg;
2648     case 0x86:
2649     case 0x87: /* xchg Ev, Gv */
2650         if ((b & 1) == 0)
2651             ot = OT_BYTE;
2652         else
2653             ot = dflag ? OT_LONG : OT_WORD;
2654         modrm = ldub_code(s->pc++);
2655         reg = (modrm >> 3) & 7;
2656         mod = (modrm >> 6) & 3;
2657         if (mod == 3) {
2658             rm = modrm & 7;
2659         do_xchg_reg:
2660             gen_op_mov_TN_reg[ot][0][reg]();
2661             gen_op_mov_TN_reg[ot][1][rm]();
2662             gen_op_mov_reg_T0[ot][rm]();
2663             gen_op_mov_reg_T1[ot][reg]();
2664         } else {
2665             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2666             gen_op_mov_TN_reg[ot][0][reg]();
2667             /* for xchg, lock is implicit */
2668             if (!(prefixes & PREFIX_LOCK))
2669                 gen_op_lock();
2670             gen_op_ld_T1_A0[ot + s->mem_index]();
2671             gen_op_st_T0_A0[ot + s->mem_index]();
2672             if (!(prefixes & PREFIX_LOCK))
2673                 gen_op_unlock();
2674             gen_op_mov_reg_T1[ot][reg]();
2675         }
2676         break;
2677     case 0xc4: /* les Gv */
2678         op = R_ES;
2679         goto do_lxx;
2680     case 0xc5: /* lds Gv */
2681         op = R_DS;
2682         goto do_lxx;
2683     case 0x1b2: /* lss Gv */
2684         op = R_SS;
2685         goto do_lxx;
2686     case 0x1b4: /* lfs Gv */
2687         op = R_FS;
2688         goto do_lxx;
2689     case 0x1b5: /* lgs Gv */
2690         op = R_GS;
2691     do_lxx:
2692         ot = dflag ? OT_LONG : OT_WORD;
2693         modrm = ldub_code(s->pc++);
2694         reg = (modrm >> 3) & 7;
2695         mod = (modrm >> 6) & 3;
2696         if (mod == 3)
2697             goto illegal_op;
2698         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2699         gen_op_ld_T1_A0[ot + s->mem_index]();
2700         gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2701         /* load the segment first to handle exceptions properly */
2702         gen_op_ldu_T0_A0[OT_WORD + s->mem_index]();
2703         gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2704         /* then put the data */
2705         gen_op_mov_reg_T1[ot][reg]();
2706         if (s->is_jmp) {
2707             gen_op_jmp_im(s->pc - s->cs_base);
2708             gen_eob(s);
2709         }
2710         break;
2711         
2712         /************************/
2713         /* shifts */
2714     case 0xc0:
2715     case 0xc1:
2716         /* shift Ev,Ib */
2717         shift = 2;
2718     grp2:
2719         {
2720             if ((b & 1) == 0)
2721                 ot = OT_BYTE;
2722             else
2723                 ot = dflag ? OT_LONG : OT_WORD;
2724             
2725             modrm = ldub_code(s->pc++);
2726             mod = (modrm >> 6) & 3;
2727             rm = modrm & 7;
2728             op = (modrm >> 3) & 7;
2729             
2730             if (mod != 3) {
2731                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2732                 opreg = OR_TMP0;
2733             } else {
2734                 opreg = rm + OR_EAX;
2735             }
2736
2737             /* simpler op */
2738             if (shift == 0) {
2739                 gen_shift(s, op, ot, opreg, OR_ECX);
2740             } else {
2741                 if (shift == 2) {
2742                     shift = ldub_code(s->pc++);
2743                 }
2744                 gen_shifti(s, op, ot, opreg, shift);
2745             }
2746         }
2747         break;
2748     case 0xd0:
2749     case 0xd1:
2750         /* shift Ev,1 */
2751         shift = 1;
2752         goto grp2;
2753     case 0xd2:
2754     case 0xd3:
2755         /* shift Ev,cl */
2756         shift = 0;
2757         goto grp2;
2758
2759     case 0x1a4: /* shld imm */
2760         op = 0;
2761         shift = 1;
2762         goto do_shiftd;
2763     case 0x1a5: /* shld cl */
2764         op = 0;
2765         shift = 0;
2766         goto do_shiftd;
2767     case 0x1ac: /* shrd imm */
2768         op = 1;
2769         shift = 1;
2770         goto do_shiftd;
2771     case 0x1ad: /* shrd cl */
2772         op = 1;
2773         shift = 0;
2774     do_shiftd:
2775         ot = dflag ? OT_LONG : OT_WORD;
2776         modrm = ldub_code(s->pc++);
2777         mod = (modrm >> 6) & 3;
2778         rm = modrm & 7;
2779         reg = (modrm >> 3) & 7;
2780         
2781         if (mod != 3) {
2782             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2783             gen_op_ld_T0_A0[ot + s->mem_index]();
2784         } else {
2785             gen_op_mov_TN_reg[ot][0][rm]();
2786         }
2787         gen_op_mov_TN_reg[ot][1][reg]();
2788         
2789         if (shift) {
2790             val = ldub_code(s->pc++);
2791             val &= 0x1f;
2792             if (val) {
2793                 if (mod == 3)
2794                     gen_op_shiftd_T0_T1_im_cc[ot][op](val);
2795                 else
2796                     gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
2797                 if (op == 0 && ot != OT_WORD)
2798                     s->cc_op = CC_OP_SHLB + ot;
2799                 else
2800                     s->cc_op = CC_OP_SARB + ot;
2801             }
2802         } else {
2803             if (s->cc_op != CC_OP_DYNAMIC)
2804                 gen_op_set_cc_op(s->cc_op);
2805             if (mod == 3)
2806                 gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
2807             else
2808                 gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
2809             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2810         }
2811         if (mod == 3) {
2812             gen_op_mov_reg_T0[ot][rm]();
2813         }
2814         break;
2815
2816         /************************/
2817         /* floats */
2818     case 0xd8 ... 0xdf: 
2819         if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
2820             /* if CR0.EM or CR0.TS are set, generate an FPU exception */
2821             /* XXX: what to do if illegal op ? */
2822             gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2823             break;
2824         }
2825         modrm = ldub_code(s->pc++);
2826         mod = (modrm >> 6) & 3;
2827         rm = modrm & 7;
2828         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2829         if (mod != 3) {
2830             /* memory op */
2831             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
2832             switch(op) {
2833             case 0x00 ... 0x07: /* fxxxs */
2834             case 0x10 ... 0x17: /* fixxxl */
2835             case 0x20 ... 0x27: /* fxxxl */
2836             case 0x30 ... 0x37: /* fixxx */
2837                 {
2838                     int op1;
2839                     op1 = op & 7;
2840
2841                     switch(op >> 4) {
2842                     case 0:
2843                         gen_op_flds_FT0_A0();
2844                         break;
2845                     case 1:
2846                         gen_op_fildl_FT0_A0();
2847                         break;
2848                     case 2:
2849                         gen_op_fldl_FT0_A0();
2850                         break;
2851                     case 3:
2852                     default:
2853                         gen_op_fild_FT0_A0();
2854                         break;
2855                     }
2856                     
2857                     gen_op_fp_arith_ST0_FT0[op1]();
2858                     if (op1 == 3) {
2859                         /* fcomp needs pop */
2860                         gen_op_fpop();
2861                     }
2862                 }
2863                 break;
2864             case 0x08: /* flds */
2865             case 0x0a: /* fsts */
2866             case 0x0b: /* fstps */
2867             case 0x18: /* fildl */
2868             case 0x1a: /* fistl */
2869             case 0x1b: /* fistpl */
2870             case 0x28: /* fldl */
2871             case 0x2a: /* fstl */
2872             case 0x2b: /* fstpl */
2873             case 0x38: /* filds */
2874             case 0x3a: /* fists */
2875             case 0x3b: /* fistps */
2876                 
2877                 switch(op & 7) {
2878                 case 0:
2879                     switch(op >> 4) {
2880                     case 0:
2881                         gen_op_flds_ST0_A0();
2882                         break;
2883                     case 1:
2884                         gen_op_fildl_ST0_A0();
2885                         break;
2886                     case 2:
2887                         gen_op_fldl_ST0_A0();
2888                         break;
2889                     case 3:
2890                     default:
2891                         gen_op_fild_ST0_A0();
2892                         break;
2893                     }
2894                     break;
2895                 default:
2896                     switch(op >> 4) {
2897                     case 0:
2898                         gen_op_fsts_ST0_A0();
2899                         break;
2900                     case 1:
2901                         gen_op_fistl_ST0_A0();
2902                         break;
2903                     case 2:
2904                         gen_op_fstl_ST0_A0();
2905                         break;
2906                     case 3:
2907                     default:
2908                         gen_op_fist_ST0_A0();
2909                         break;
2910                     }
2911                     if ((op & 7) == 3)
2912                         gen_op_fpop();
2913                     break;
2914                 }
2915                 break;
2916             case 0x0c: /* fldenv mem */
2917                 gen_op_fldenv_A0(s->dflag);
2918                 break;
2919             case 0x0d: /* fldcw mem */
2920                 gen_op_fldcw_A0();
2921                 break;
2922             case 0x0e: /* fnstenv mem */
2923                 gen_op_fnstenv_A0(s->dflag);
2924                 break;
2925             case 0x0f: /* fnstcw mem */
2926                 gen_op_fnstcw_A0();
2927                 break;
2928             case 0x1d: /* fldt mem */
2929                 gen_op_fldt_ST0_A0();
2930                 break;
2931             case 0x1f: /* fstpt mem */
2932                 gen_op_fstt_ST0_A0();
2933                 gen_op_fpop();
2934                 break;
2935             case 0x2c: /* frstor mem */
2936                 gen_op_frstor_A0(s->dflag);
2937                 break;
2938             case 0x2e: /* fnsave mem */
2939                 gen_op_fnsave_A0(s->dflag);
2940                 break;
2941             case 0x2f: /* fnstsw mem */
2942                 gen_op_fnstsw_A0();
2943                 break;
2944             case 0x3c: /* fbld */
2945                 gen_op_fbld_ST0_A0();
2946                 break;
2947             case 0x3e: /* fbstp */
2948                 gen_op_fbst_ST0_A0();
2949                 gen_op_fpop();
2950                 break;
2951             case 0x3d: /* fildll */
2952                 gen_op_fildll_ST0_A0();
2953                 break;
2954             case 0x3f: /* fistpll */
2955                 gen_op_fistll_ST0_A0();
2956                 gen_op_fpop();
2957                 break;
2958             default:
2959                 goto illegal_op;
2960             }
2961         } else {
2962             /* register float ops */
2963             opreg = rm;
2964
2965             switch(op) {
2966             case 0x08: /* fld sti */
2967                 gen_op_fpush();
2968                 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2969                 break;
2970             case 0x09: /* fxchg sti */
2971                 gen_op_fxchg_ST0_STN(opreg);
2972                 break;
2973             case 0x0a: /* grp d9/2 */
2974                 switch(rm) {
2975                 case 0: /* fnop */
2976                     break;
2977                 default:
2978                     goto illegal_op;
2979                 }
2980                 break;
2981             case 0x0c: /* grp d9/4 */
2982                 switch(rm) {
2983                 case 0: /* fchs */
2984                     gen_op_fchs_ST0();
2985                     break;
2986                 case 1: /* fabs */
2987                     gen_op_fabs_ST0();
2988                     break;
2989                 case 4: /* ftst */
2990                     gen_op_fldz_FT0();
2991                     gen_op_fcom_ST0_FT0();
2992                     break;
2993                 case 5: /* fxam */
2994                     gen_op_fxam_ST0();
2995                     break;
2996                 default:
2997                     goto illegal_op;
2998                 }
2999                 break;
3000             case 0x0d: /* grp d9/5 */
3001                 {
3002                     switch(rm) {
3003                     case 0:
3004                         gen_op_fpush();
3005                         gen_op_fld1_ST0();
3006                         break;
3007                     case 1:
3008                         gen_op_fpush();
3009                         gen_op_fldl2t_ST0();
3010                         break;
3011                     case 2:
3012                         gen_op_fpush();
3013                         gen_op_fldl2e_ST0();
3014                         break;
3015                     case 3:
3016                         gen_op_fpush();
3017                         gen_op_fldpi_ST0();
3018                         break;
3019                     case 4:
3020                         gen_op_fpush();
3021                         gen_op_fldlg2_ST0();
3022                         break;
3023                     case 5:
3024                         gen_op_fpush();
3025                         gen_op_fldln2_ST0();
3026                         break;
3027                     case 6:
3028                         gen_op_fpush();
3029                         gen_op_fldz_ST0();
3030                         break;
3031                     default:
3032                         goto illegal_op;
3033                     }
3034                 }
3035                 break;
3036             case 0x0e: /* grp d9/6 */
3037                 switch(rm) {
3038                 case 0: /* f2xm1 */
3039                     gen_op_f2xm1();
3040                     break;
3041                 case 1: /* fyl2x */
3042                     gen_op_fyl2x();
3043                     break;
3044                 case 2: /* fptan */
3045                     gen_op_fptan();
3046                     break;
3047                 case 3: /* fpatan */
3048                     gen_op_fpatan();
3049                     break;
3050                 case 4: /* fxtract */
3051                     gen_op_fxtract();
3052                     break;
3053                 case 5: /* fprem1 */
3054                     gen_op_fprem1();
3055                     break;
3056                 case 6: /* fdecstp */
3057                     gen_op_fdecstp();
3058                     break;
3059                 default:
3060                 case 7: /* fincstp */
3061                     gen_op_fincstp();
3062                     break;
3063                 }
3064                 break;
3065             case 0x0f: /* grp d9/7 */
3066                 switch(rm) {
3067                 case 0: /* fprem */
3068                     gen_op_fprem();
3069                     break;
3070                 case 1: /* fyl2xp1 */
3071                     gen_op_fyl2xp1();
3072                     break;
3073                 case 2: /* fsqrt */
3074                     gen_op_fsqrt();
3075                     break;
3076                 case 3: /* fsincos */
3077                     gen_op_fsincos();
3078                     break;
3079                 case 5: /* fscale */
3080                     gen_op_fscale();
3081                     break;
3082                 case 4: /* frndint */
3083                     gen_op_frndint();
3084                     break;
3085                 case 6: /* fsin */
3086                     gen_op_fsin();
3087                     break;
3088                 default:
3089                 case 7: /* fcos */
3090                     gen_op_fcos();
3091                     break;
3092                 }
3093                 break;
3094             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
3095             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
3096             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
3097                 {
3098                     int op1;
3099                     
3100                     op1 = op & 7;
3101                     if (op >= 0x20) {
3102                         gen_op_fp_arith_STN_ST0[op1](opreg);
3103                         if (op >= 0x30)
3104                             gen_op_fpop();
3105                     } else {
3106                         gen_op_fmov_FT0_STN(opreg);
3107                         gen_op_fp_arith_ST0_FT0[op1]();
3108                     }
3109                 }
3110                 break;
3111             case 0x02: /* fcom */
3112                 gen_op_fmov_FT0_STN(opreg);
3113                 gen_op_fcom_ST0_FT0();
3114                 break;
3115             case 0x03: /* fcomp */
3116                 gen_op_fmov_FT0_STN(opreg);
3117                 gen_op_fcom_ST0_FT0();
3118                 gen_op_fpop();
3119                 break;
3120             case 0x15: /* da/5 */
3121                 switch(rm) {
3122                 case 1: /* fucompp */
3123                     gen_op_fmov_FT0_STN(1);
3124                     gen_op_fucom_ST0_FT0();
3125                     gen_op_fpop();
3126                     gen_op_fpop();
3127                     break;
3128                 default:
3129                     goto illegal_op;
3130                 }
3131                 break;
3132             case 0x1c:
3133                 switch(rm) {
3134                 case 0: /* feni (287 only, just do nop here) */
3135                     break;
3136                 case 1: /* fdisi (287 only, just do nop here) */
3137                     break;
3138                 case 2: /* fclex */
3139                     gen_op_fclex();
3140                     break;
3141                 case 3: /* fninit */
3142                     gen_op_fninit();
3143                     break;
3144                 case 4: /* fsetpm (287 only, just do nop here) */
3145                     break;
3146                 default:
3147                     goto illegal_op;
3148                 }
3149                 break;
3150             case 0x1d: /* fucomi */
3151                 if (s->cc_op != CC_OP_DYNAMIC)
3152                     gen_op_set_cc_op(s->cc_op);
3153                 gen_op_fmov_FT0_STN(opreg);
3154                 gen_op_fucomi_ST0_FT0();
3155                 s->cc_op = CC_OP_EFLAGS;
3156                 break;
3157             case 0x1e: /* fcomi */
3158                 if (s->cc_op != CC_OP_DYNAMIC)
3159                     gen_op_set_cc_op(s->cc_op);
3160                 gen_op_fmov_FT0_STN(opreg);
3161                 gen_op_fcomi_ST0_FT0();
3162                 s->cc_op = CC_OP_EFLAGS;
3163                 break;
3164             case 0x2a: /* fst sti */
3165                 gen_op_fmov_STN_ST0(opreg);
3166                 break;
3167             case 0x2b: /* fstp sti */
3168                 gen_op_fmov_STN_ST0(opreg);
3169                 gen_op_fpop();
3170                 break;
3171             case 0x2c: /* fucom st(i) */
3172                 gen_op_fmov_FT0_STN(opreg);
3173                 gen_op_fucom_ST0_FT0();
3174                 break;
3175             case 0x2d: /* fucomp st(i) */
3176                 gen_op_fmov_FT0_STN(opreg);
3177                 gen_op_fucom_ST0_FT0();
3178                 gen_op_fpop();
3179                 break;
3180             case 0x33: /* de/3 */
3181                 switch(rm) {
3182                 case 1: /* fcompp */
3183                     gen_op_fmov_FT0_STN(1);
3184                     gen_op_fcom_ST0_FT0();
3185                     gen_op_fpop();
3186                     gen_op_fpop();
3187                     break;
3188                 default:
3189                     goto illegal_op;
3190                 }
3191                 break;
3192             case 0x3c: /* df/4 */
3193                 switch(rm) {
3194                 case 0:
3195                     gen_op_fnstsw_EAX();
3196                     break;
3197                 default:
3198                     goto illegal_op;
3199                 }
3200                 break;
3201             case 0x3d: /* fucomip */
3202                 if (s->cc_op != CC_OP_DYNAMIC)
3203                     gen_op_set_cc_op(s->cc_op);
3204                 gen_op_fmov_FT0_STN(opreg);
3205                 gen_op_fucomi_ST0_FT0();
3206                 gen_op_fpop();
3207                 s->cc_op = CC_OP_EFLAGS;
3208                 break;
3209             case 0x3e: /* fcomip */
3210                 if (s->cc_op != CC_OP_DYNAMIC)
3211                     gen_op_set_cc_op(s->cc_op);
3212                 gen_op_fmov_FT0_STN(opreg);
3213                 gen_op_fcomi_ST0_FT0();
3214                 gen_op_fpop();
3215                 s->cc_op = CC_OP_EFLAGS;
3216                 break;
3217             case 0x10 ... 0x13: /* fcmovxx */
3218             case 0x18 ... 0x1b:
3219                 {
3220                     int op1;
3221                     const static uint8_t fcmov_cc[8] = {
3222                         (JCC_B << 1),
3223                         (JCC_Z << 1),
3224                         (JCC_BE << 1),
3225                         (JCC_P << 1),
3226                     };
3227                     op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
3228                     gen_setcc(s, op1);
3229                     gen_op_fcmov_ST0_STN_T0(opreg);
3230                 }
3231                 break;
3232             default:
3233                 goto illegal_op;
3234             }
3235         }
3236 #ifdef USE_CODE_COPY
3237         s->tb->cflags |= CF_TB_FP_USED;
3238 #endif
3239         break;
3240         /************************/
3241         /* string ops */
3242
3243     case 0xa4: /* movsS */
3244     case 0xa5:
3245         if ((b & 1) == 0)
3246             ot = OT_BYTE;
3247         else
3248             ot = dflag ? OT_LONG : OT_WORD;
3249
3250         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3251             gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3252         } else {
3253             gen_movs(s, ot);
3254         }
3255         break;
3256         
3257     case 0xaa: /* stosS */
3258     case 0xab:
3259         if ((b & 1) == 0)
3260             ot = OT_BYTE;
3261         else
3262             ot = dflag ? OT_LONG : OT_WORD;
3263
3264         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3265             gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3266         } else {
3267             gen_stos(s, ot);
3268         }
3269         break;
3270     case 0xac: /* lodsS */
3271     case 0xad:
3272         if ((b & 1) == 0)
3273             ot = OT_BYTE;
3274         else
3275             ot = dflag ? OT_LONG : OT_WORD;
3276         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3277             gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3278         } else {
3279             gen_lods(s, ot);
3280         }
3281         break;
3282     case 0xae: /* scasS */
3283     case 0xaf:
3284         if ((b & 1) == 0)
3285             ot = OT_BYTE;
3286         else
3287                 ot = dflag ? OT_LONG : OT_WORD;
3288         if (prefixes & PREFIX_REPNZ) {
3289             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3290         } else if (prefixes & PREFIX_REPZ) {
3291             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3292         } else {
3293             gen_scas(s, ot);
3294             s->cc_op = CC_OP_SUBB + ot;
3295         }
3296         break;
3297
3298     case 0xa6: /* cmpsS */
3299     case 0xa7:
3300         if ((b & 1) == 0)
3301             ot = OT_BYTE;
3302         else
3303             ot = dflag ? OT_LONG : OT_WORD;
3304         if (prefixes & PREFIX_REPNZ) {
3305             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3306         } else if (prefixes & PREFIX_REPZ) {
3307             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3308         } else {
3309             gen_cmps(s, ot);
3310             s->cc_op = CC_OP_SUBB + ot;
3311         }
3312         break;
3313     case 0x6c: /* insS */
3314     case 0x6d:
3315         if ((b & 1) == 0)
3316             ot = OT_BYTE;
3317         else
3318             ot = dflag ? OT_LONG : OT_WORD;
3319         gen_check_io(s, ot, 1, pc_start - s->cs_base);
3320         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3321             gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3322         } else {
3323             gen_ins(s, ot);
3324         }
3325         break;
3326     case 0x6e: /* outsS */
3327     case 0x6f:
3328         if ((b & 1) == 0)
3329             ot = OT_BYTE;
3330         else
3331             ot = dflag ? OT_LONG : OT_WORD;
3332         gen_check_io(s, ot, 1, pc_start - s->cs_base);
3333         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
3334             gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
3335         } else {
3336             gen_outs(s, ot);
3337         }
3338         break;
3339
3340         /************************/
3341         /* port I/O */
3342     case 0xe4:
3343     case 0xe5:
3344         if ((b & 1) == 0)
3345             ot = OT_BYTE;
3346         else
3347             ot = dflag ? OT_LONG : OT_WORD;
3348         val = ldub_code(s->pc++);
3349         gen_op_movl_T0_im(val);
3350         gen_check_io(s, ot, 0, pc_start - s->cs_base);
3351         gen_op_in[ot]();
3352         gen_op_mov_reg_T1[ot][R_EAX]();
3353         break;
3354     case 0xe6:
3355     case 0xe7:
3356         if ((b & 1) == 0)
3357             ot = OT_BYTE;
3358         else
3359             ot = dflag ? OT_LONG : OT_WORD;
3360         val = ldub_code(s->pc++);
3361         gen_op_movl_T0_im(val);
3362         gen_check_io(s, ot, 0, pc_start - s->cs_base);
3363         gen_op_mov_TN_reg[ot][1][R_EAX]();
3364         gen_op_out[ot]();
3365         break;
3366     case 0xec:
3367     case 0xed:
3368         if ((b & 1) == 0)
3369             ot = OT_BYTE;
3370         else
3371             ot = dflag ? OT_LONG : OT_WORD;
3372         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3373         gen_op_andl_T0_ffff();
3374         gen_check_io(s, ot, 0, pc_start - s->cs_base);
3375         gen_op_in[ot]();
3376         gen_op_mov_reg_T1[ot][R_EAX]();
3377         break;
3378     case 0xee:
3379     case 0xef:
3380         if ((b & 1) == 0)
3381             ot = OT_BYTE;
3382         else
3383             ot = dflag ? OT_LONG : OT_WORD;
3384         gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3385         gen_op_andl_T0_ffff();
3386         gen_check_io(s, ot, 0, pc_start - s->cs_base);
3387         gen_op_mov_TN_reg[ot][1][R_EAX]();
3388         gen_op_out[ot]();
3389         break;
3390
3391         /************************/
3392         /* control */
3393     case 0xc2: /* ret im */
3394         val = ldsw_code(s->pc);
3395         s->pc += 2;
3396         gen_pop_T0(s);
3397         gen_stack_update(s, val + (2 << s->dflag));
3398         if (s->dflag == 0)
3399             gen_op_andl_T0_ffff();
3400         gen_op_jmp_T0();
3401         gen_eob(s);
3402         break;
3403     case 0xc3: /* ret */
3404         gen_pop_T0(s);
3405         gen_pop_update(s);
3406         if (s->dflag == 0)
3407             gen_op_andl_T0_ffff();
3408         gen_op_jmp_T0();
3409         gen_eob(s);
3410         break;
3411     case 0xca: /* lret im */
3412         val = ldsw_code(s->pc);
3413         s->pc += 2;
3414     do_lret:
3415         if (s->pe && !s->vm86) {
3416             if (s->cc_op != CC_OP_DYNAMIC)
3417                 gen_op_set_cc_op(s->cc_op);
3418             gen_op_jmp_im(pc_start - s->cs_base);
3419             gen_op_lret_protected(s->dflag, val);
3420         } else {
3421             gen_stack_A0(s);
3422             /* pop offset */
3423             gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3424             if (s->dflag == 0)
3425                 gen_op_andl_T0_ffff();
3426             /* NOTE: keeping EIP updated is not a problem in case of
3427                exception */
3428             gen_op_jmp_T0();
3429             /* pop selector */
3430             gen_op_addl_A0_im(2 << s->dflag);
3431             gen_op_ld_T0_A0[1 + s->dflag + s->mem_index]();
3432             gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3433             /* add stack offset */
3434             gen_stack_update(s, val + (4 << s->dflag));
3435         }
3436         gen_eob(s);
3437         break;
3438     case 0xcb: /* lret */
3439         val = 0;
3440         goto do_lret;
3441     case 0xcf: /* iret */
3442         if (!s->pe) {
3443             /* real mode */
3444             gen_op_iret_real(s->dflag);
3445             s->cc_op = CC_OP_EFLAGS;
3446         } else if (s->vm86) {
3447             if (s->iopl != 3) {
3448                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3449             } else {
3450                 gen_op_iret_real(s->dflag);
3451                 s->cc_op = CC_OP_EFLAGS;
3452             }
3453         } else {
3454             if (s->cc_op != CC_OP_DYNAMIC)
3455                 gen_op_set_cc_op(s->cc_op);
3456             gen_op_jmp_im(pc_start - s->cs_base);
3457             gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
3458             s->cc_op = CC_OP_EFLAGS;
3459         }
3460         gen_eob(s);
3461         break;
3462     case 0xe8: /* call im */
3463         {
3464             unsigned int next_eip;
3465             ot = dflag ? OT_LONG : OT_WORD;
3466             val = insn_get(s, ot);
3467             next_eip = s->pc - s->cs_base;
3468             val += next_eip;
3469             if (s->dflag == 0)
3470                 val &= 0xffff;
3471             gen_op_movl_T0_im(next_eip);
3472             gen_push_T0(s);
3473             gen_jmp(s, val);
3474         }
3475         break;
3476     case 0x9a: /* lcall im */
3477         {
3478             unsigned int selector, offset;
3479
3480             ot = dflag ? OT_LONG : OT_WORD;
3481             offset = insn_get(s, ot);
3482             selector = insn_get(s, OT_WORD);
3483             
3484             gen_op_movl_T0_im(selector);
3485             gen_op_movl_T1_im(offset);
3486         }
3487         goto do_lcall;
3488     case 0xe9: /* jmp */
3489         ot = dflag ? OT_LONG : OT_WORD;
3490         val = insn_get(s, ot);
3491         val += s->pc - s->cs_base;
3492         if (s->dflag == 0)
3493             val = val & 0xffff;
3494         gen_jmp(s, val);
3495         break;
3496     case 0xea: /* ljmp im */
3497         {
3498             unsigned int selector, offset;
3499
3500             ot = dflag ? OT_LONG : OT_WORD;
3501             offset = insn_get(s, ot);
3502             selector = insn_get(s, OT_WORD);
3503             
3504             gen_op_movl_T0_im(selector);
3505             gen_op_movl_T1_im(offset);
3506         }
3507         goto do_ljmp;
3508     case 0xeb: /* jmp Jb */
3509         val = (int8_t)insn_get(s, OT_BYTE);
3510         val += s->pc - s->cs_base;
3511         if (s->dflag == 0)
3512             val = val & 0xffff;
3513         gen_jmp(s, val);
3514         break;
3515     case 0x70 ... 0x7f: /* jcc Jb */
3516         val = (int8_t)insn_get(s, OT_BYTE);
3517         goto do_jcc;
3518     case 0x180 ... 0x18f: /* jcc Jv */
3519         if (dflag) {
3520             val = insn_get(s, OT_LONG);
3521         } else {
3522             val = (int16_t)insn_get(s, OT_WORD); 
3523         }
3524     do_jcc:
3525         next_eip = s->pc - s->cs_base;
3526         val += next_eip;
3527         if (s->dflag == 0)
3528             val &= 0xffff;
3529         gen_jcc(s, b, val, next_eip);
3530         break;
3531
3532     case 0x190 ... 0x19f: /* setcc Gv */
3533         modrm = ldub_code(s->pc++);
3534         gen_setcc(s, b);
3535         gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3536         break;
3537     case 0x140 ... 0x14f: /* cmov Gv, Ev */
3538         ot = dflag ? OT_LONG : OT_WORD;
3539         modrm = ldub_code(s->pc++);
3540         reg = (modrm >> 3) & 7;
3541         mod = (modrm >> 6) & 3;
3542         gen_setcc(s, b);
3543         if (mod != 3) {
3544             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3545             gen_op_ld_T1_A0[ot + s->mem_index]();
3546         } else {
3547             rm = modrm & 7;
3548             gen_op_mov_TN_reg[ot][1][rm]();
3549         }
3550         gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3551         break;
3552         
3553         /************************/
3554         /* flags */
3555     case 0x9c: /* pushf */
3556         if (s->vm86 && s->iopl != 3) {
3557             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3558         } else {
3559             if (s->cc_op != CC_OP_DYNAMIC)
3560                 gen_op_set_cc_op(s->cc_op);
3561             gen_op_movl_T0_eflags();
3562             gen_push_T0(s);
3563         }
3564         break;
3565     case 0x9d: /* popf */
3566         if (s->vm86 && s->iopl != 3) {
3567             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3568         } else {
3569             gen_pop_T0(s);
3570             if (s->cpl == 0) {
3571                 if (s->dflag) {
3572                     gen_op_movl_eflags_T0_cpl0();
3573                 } else {
3574                     gen_op_movw_eflags_T0_cpl0();
3575                 }
3576             } else {
3577                 if (s->cpl <= s->iopl) {
3578                     if (s->dflag) {
3579                         gen_op_movl_eflags_T0_io();
3580                     } else {
3581                         gen_op_movw_eflags_T0_io();
3582                     }
3583                 } else {
3584                     if (s->dflag) {
3585                         gen_op_movl_eflags_T0();
3586                     } else {
3587                         gen_op_movw_eflags_T0();
3588                     }
3589                 }
3590             }
3591             gen_pop_update(s);
3592             s->cc_op = CC_OP_EFLAGS;
3593             /* abort translation because TF flag may change */
3594             gen_op_jmp_im(s->pc - s->cs_base);
3595             gen_eob(s);
3596         }
3597         break;
3598     case 0x9e: /* sahf */
3599         gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3600         if (s->cc_op != CC_OP_DYNAMIC)
3601             gen_op_set_cc_op(s->cc_op);
3602         gen_op_movb_eflags_T0();
3603         s->cc_op = CC_OP_EFLAGS;
3604         break;
3605     case 0x9f: /* lahf */
3606         if (s->cc_op != CC_OP_DYNAMIC)
3607             gen_op_set_cc_op(s->cc_op);
3608         gen_op_movl_T0_eflags();
3609         gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3610         break;
3611     case 0xf5: /* cmc */
3612         if (s->cc_op != CC_OP_DYNAMIC)
3613             gen_op_set_cc_op(s->cc_op);
3614         gen_op_cmc();
3615         s->cc_op = CC_OP_EFLAGS;
3616         break;
3617     case 0xf8: /* clc */
3618         if (s->cc_op != CC_OP_DYNAMIC)
3619             gen_op_set_cc_op(s->cc_op);
3620         gen_op_clc();
3621         s->cc_op = CC_OP_EFLAGS;
3622         break;
3623     case 0xf9: /* stc */
3624         if (s->cc_op != CC_OP_DYNAMIC)
3625             gen_op_set_cc_op(s->cc_op);
3626         gen_op_stc();
3627         s->cc_op = CC_OP_EFLAGS;
3628         break;
3629     case 0xfc: /* cld */
3630         gen_op_cld();
3631         break;
3632     case 0xfd: /* std */
3633         gen_op_std();
3634         break;
3635
3636         /************************/
3637         /* bit operations */
3638     case 0x1ba: /* bt/bts/btr/btc Gv, im */
3639         ot = dflag ? OT_LONG : OT_WORD;
3640         modrm = ldub_code(s->pc++);
3641         op = (modrm >> 3) & 7;
3642         mod = (modrm >> 6) & 3;
3643         rm = modrm & 7;
3644         if (mod != 3) {
3645             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3646             gen_op_ld_T0_A0[ot + s->mem_index]();
3647         } else {
3648             gen_op_mov_TN_reg[ot][0][rm]();
3649         }
3650         /* load shift */
3651         val = ldub_code(s->pc++);
3652         gen_op_movl_T1_im(val);
3653         if (op < 4)
3654             goto illegal_op;
3655         op -= 4;
3656         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3657         s->cc_op = CC_OP_SARB + ot;
3658         if (op != 0) {
3659             if (mod != 3)
3660                 gen_op_st_T0_A0[ot + s->mem_index]();
3661             else
3662                 gen_op_mov_reg_T0[ot][rm]();
3663             gen_op_update_bt_cc();
3664         }
3665         break;
3666     case 0x1a3: /* bt Gv, Ev */
3667         op = 0;
3668         goto do_btx;
3669     case 0x1ab: /* bts */
3670         op = 1;
3671         goto do_btx;
3672     case 0x1b3: /* btr */
3673         op = 2;
3674         goto do_btx;
3675     case 0x1bb: /* btc */
3676         op = 3;
3677     do_btx:
3678         ot = dflag ? OT_LONG : OT_WORD;
3679         modrm = ldub_code(s->pc++);
3680         reg = (modrm >> 3) & 7;
3681         mod = (modrm >> 6) & 3;
3682         rm = modrm & 7;
3683         gen_op_mov_TN_reg[OT_LONG][1][reg]();
3684         if (mod != 3) {
3685             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3686             /* specific case: we need to add a displacement */
3687             if (ot == OT_WORD)
3688                 gen_op_add_bitw_A0_T1();
3689             else
3690                 gen_op_add_bitl_A0_T1();
3691             gen_op_ld_T0_A0[ot + s->mem_index]();
3692         } else {
3693             gen_op_mov_TN_reg[ot][0][rm]();
3694         }
3695         gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3696         s->cc_op = CC_OP_SARB + ot;
3697         if (op != 0) {
3698             if (mod != 3)
3699                 gen_op_st_T0_A0[ot + s->mem_index]();
3700             else
3701                 gen_op_mov_reg_T0[ot][rm]();
3702             gen_op_update_bt_cc();
3703         }
3704         break;
3705     case 0x1bc: /* bsf */
3706     case 0x1bd: /* bsr */
3707         ot = dflag ? OT_LONG : OT_WORD;
3708         modrm = ldub_code(s->pc++);
3709         reg = (modrm >> 3) & 7;
3710         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3711         gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3712         /* NOTE: we always write back the result. Intel doc says it is
3713            undefined if T0 == 0 */
3714         gen_op_mov_reg_T0[ot][reg]();
3715         s->cc_op = CC_OP_LOGICB + ot;
3716         break;
3717         /************************/
3718         /* bcd */
3719     case 0x27: /* daa */
3720         if (s->cc_op != CC_OP_DYNAMIC)
3721             gen_op_set_cc_op(s->cc_op);
3722         gen_op_daa();
3723         s->cc_op = CC_OP_EFLAGS;
3724         break;
3725     case 0x2f: /* das */
3726         if (s->cc_op != CC_OP_DYNAMIC)
3727             gen_op_set_cc_op(s->cc_op);
3728         gen_op_das();
3729         s->cc_op = CC_OP_EFLAGS;
3730         break;
3731     case 0x37: /* aaa */
3732         if (s->cc_op != CC_OP_DYNAMIC)
3733             gen_op_set_cc_op(s->cc_op);
3734         gen_op_aaa();
3735         s->cc_op = CC_OP_EFLAGS;
3736         break;
3737     case 0x3f: /* aas */
3738         if (s->cc_op != CC_OP_DYNAMIC)
3739             gen_op_set_cc_op(s->cc_op);
3740         gen_op_aas();
3741         s->cc_op = CC_OP_EFLAGS;
3742         break;
3743     case 0xd4: /* aam */
3744         val = ldub_code(s->pc++);
3745         gen_op_aam(val);
3746         s->cc_op = CC_OP_LOGICB;
3747         break;
3748     case 0xd5: /* aad */
3749         val = ldub_code(s->pc++);
3750         gen_op_aad(val);
3751         s->cc_op = CC_OP_LOGICB;
3752         break;
3753         /************************/
3754         /* misc */
3755     case 0x90: /* nop */
3756         /* XXX: correct lock test for all insn */
3757         if (prefixes & PREFIX_LOCK)
3758             goto illegal_op;
3759         break;
3760     case 0x9b: /* fwait */
3761         if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == 
3762             (HF_MP_MASK | HF_TS_MASK)) {
3763             gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3764         }
3765         break;
3766     case 0xcc: /* int3 */
3767         gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3768         break;
3769     case 0xcd: /* int N */
3770         val = ldub_code(s->pc++);
3771         if (s->vm86 && s->iopl != 3) {
3772             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 
3773         } else {
3774             gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3775         }
3776         break;
3777     case 0xce: /* into */
3778         if (s->cc_op != CC_OP_DYNAMIC)
3779             gen_op_set_cc_op(s->cc_op);
3780         gen_op_into(s->pc - s->cs_base);
3781         break;
3782     case 0xf1: /* icebp (undocumented, exits to external debugger) */
3783         gen_debug(s, pc_start - s->cs_base);
3784         break;
3785     case 0xfa: /* cli */
3786         if (!s->vm86) {
3787             if (s->cpl <= s->iopl) {
3788                 gen_op_cli();
3789             } else {
3790                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3791             }
3792         } else {
3793             if (s->iopl == 3) {
3794                 gen_op_cli();
3795             } else {
3796                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3797             }
3798         }
3799         break;
3800     case 0xfb: /* sti */
3801         if (!s->vm86) {
3802             if (s->cpl <= s->iopl) {
3803             gen_sti:
3804                 gen_op_sti();
3805                 /* interruptions are enabled only the first insn after sti */
3806                 /* If several instructions disable interrupts, only the
3807                    _first_ does it */
3808                 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
3809                     gen_op_set_inhibit_irq();
3810                 /* give a chance to handle pending irqs */
3811                 gen_op_jmp_im(s->pc - s->cs_base);
3812                 gen_eob(s);
3813             } else {
3814                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3815             }
3816         } else {
3817             if (s->iopl == 3) {
3818                 goto gen_sti;
3819             } else {
3820                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3821             }
3822         }
3823         break;
3824     case 0x62: /* bound */
3825         ot = dflag ? OT_LONG : OT_WORD;
3826         modrm = ldub_code(s->pc++);
3827         reg = (modrm >> 3) & 7;
3828         mod = (modrm >> 6) & 3;
3829         if (mod == 3)
3830             goto illegal_op;
3831         gen_op_mov_reg_T0[ot][reg]();
3832         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3833         if (ot == OT_WORD)
3834             gen_op_boundw(pc_start - s->cs_base);
3835         else
3836             gen_op_boundl(pc_start - s->cs_base);
3837         break;
3838     case 0x1c8 ... 0x1cf: /* bswap reg */
3839         reg = b & 7;
3840         gen_op_mov_TN_reg[OT_LONG][0][reg]();
3841         gen_op_bswapl_T0();
3842         gen_op_mov_reg_T0[OT_LONG][reg]();
3843         break;
3844     case 0xd6: /* salc */
3845         if (s->cc_op != CC_OP_DYNAMIC)
3846             gen_op_set_cc_op(s->cc_op);
3847         gen_op_salc();
3848         break;
3849     case 0xe0: /* loopnz */
3850     case 0xe1: /* loopz */
3851         if (s->cc_op != CC_OP_DYNAMIC)
3852             gen_op_set_cc_op(s->cc_op);
3853         /* FALL THRU */
3854     case 0xe2: /* loop */
3855     case 0xe3: /* jecxz */
3856         val = (int8_t)insn_get(s, OT_BYTE);
3857         next_eip = s->pc - s->cs_base;
3858         val += next_eip;
3859         if (s->dflag == 0)
3860             val &= 0xffff;
3861         gen_op_loop[s->aflag][b & 3](val, next_eip);
3862         gen_eob(s);
3863         break;
3864     case 0x130: /* wrmsr */
3865     case 0x132: /* rdmsr */
3866         if (s->cpl != 0) {
3867             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3868         } else {
3869             if (b & 2)
3870                 gen_op_rdmsr();
3871             else
3872                 gen_op_wrmsr();
3873         }
3874         break;
3875     case 0x131: /* rdtsc */
3876         gen_op_rdtsc();
3877         break;
3878     case 0x1a2: /* cpuid */
3879         gen_op_cpuid();
3880         break;
3881     case 0xf4: /* hlt */
3882         if (s->cpl != 0) {
3883             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3884         } else {
3885             if (s->cc_op != CC_OP_DYNAMIC)
3886                 gen_op_set_cc_op(s->cc_op);
3887             gen_op_jmp_im(s->pc - s->cs_base);
3888             gen_op_hlt();
3889             s->is_jmp = 3;
3890         }
3891         break;
3892     case 0x100:
3893         modrm = ldub_code(s->pc++);
3894         mod = (modrm >> 6) & 3;
3895         op = (modrm >> 3) & 7;
3896         switch(op) {
3897         case 0: /* sldt */
3898             if (!s->pe || s->vm86)
3899                 goto illegal_op;
3900             gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3901             ot = OT_WORD;
3902             if (mod == 3)
3903                 ot += s->dflag;
3904             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3905             break;
3906         case 2: /* lldt */
3907             if (!s->pe || s->vm86)
3908                 goto illegal_op;
3909             if (s->cpl != 0) {
3910                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3911             } else {
3912                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3913                 gen_op_jmp_im(pc_start - s->cs_base);
3914                 gen_op_lldt_T0();
3915             }
3916             break;
3917         case 1: /* str */
3918             if (!s->pe || s->vm86)
3919                 goto illegal_op;
3920             gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3921             ot = OT_WORD;
3922             if (mod == 3)
3923                 ot += s->dflag;
3924             gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3925             break;
3926         case 3: /* ltr */
3927             if (!s->pe || s->vm86)
3928                 goto illegal_op;
3929             if (s->cpl != 0) {
3930                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3931             } else {
3932                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3933                 gen_op_jmp_im(pc_start - s->cs_base);
3934                 gen_op_ltr_T0();
3935             }
3936             break;
3937         case 4: /* verr */
3938         case 5: /* verw */
3939             if (!s->pe || s->vm86)
3940                 goto illegal_op;
3941             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3942             if (s->cc_op != CC_OP_DYNAMIC)
3943                 gen_op_set_cc_op(s->cc_op);
3944             if (op == 4)
3945                 gen_op_verr();
3946             else
3947                 gen_op_verw();
3948             s->cc_op = CC_OP_EFLAGS;
3949             break;
3950         default:
3951             goto illegal_op;
3952         }
3953         break;
3954     case 0x101:
3955         modrm = ldub_code(s->pc++);
3956         mod = (modrm >> 6) & 3;
3957         op = (modrm >> 3) & 7;
3958         switch(op) {
3959         case 0: /* sgdt */
3960         case 1: /* sidt */
3961             if (mod == 3)
3962                 goto illegal_op;
3963             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3964             if (op == 0)
3965                 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3966             else
3967                 gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3968             gen_op_st_T0_A0[OT_WORD + s->mem_index]();
3969             gen_op_addl_A0_im(2);
3970             if (op == 0)
3971                 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3972             else
3973                 gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3974             if (!s->dflag)
3975                 gen_op_andl_T0_im(0xffffff);
3976             gen_op_st_T0_A0[OT_LONG + s->mem_index]();
3977             break;
3978         case 2: /* lgdt */
3979         case 3: /* lidt */
3980             if (mod == 3)
3981                 goto illegal_op;
3982             if (s->cpl != 0) {
3983                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3984             } else {
3985                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3986                 gen_op_ld_T1_A0[OT_WORD + s->mem_index]();
3987                 gen_op_addl_A0_im(2);
3988                 gen_op_ld_T0_A0[OT_LONG + s->mem_index]();
3989                 if (!s->dflag)
3990                     gen_op_andl_T0_im(0xffffff);
3991                 if (op == 2) {
3992                     gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3993                     gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3994                 } else {
3995                     gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3996                     gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3997                 }
3998             }
3999             break;
4000         case 4: /* smsw */
4001             gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
4002             gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
4003             break;
4004         case 6: /* lmsw */
4005             if (s->cpl != 0) {
4006                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4007             } else {
4008                 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
4009                 gen_op_lmsw_T0();
4010                 gen_op_jmp_im(s->pc - s->cs_base);
4011                 gen_eob(s);
4012             }
4013             break;
4014         case 7: /* invlpg */
4015             if (s->cpl != 0) {
4016                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4017             } else {
4018                 if (mod == 3)
4019                     goto illegal_op;
4020                 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4021                 gen_op_invlpg_A0();
4022                 gen_op_jmp_im(s->pc - s->cs_base);
4023                 gen_eob(s);
4024             }
4025             break;
4026         default:
4027             goto illegal_op;
4028         }
4029         break;
4030     case 0x108: /* invd */
4031     case 0x109: /* wbinvd */
4032         if (s->cpl != 0) {
4033             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4034         } else {
4035             /* nothing to do */
4036         }
4037         break;
4038     case 0x63: /* arpl */
4039         if (!s->pe || s->vm86)
4040             goto illegal_op;
4041         ot = dflag ? OT_LONG : OT_WORD;
4042         modrm = ldub_code(s->pc++);
4043         reg = (modrm >> 3) & 7;
4044         mod = (modrm >> 6) & 3;
4045         rm = modrm & 7;
4046         if (mod != 3) {
4047             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4048             gen_op_ld_T0_A0[ot + s->mem_index]();
4049         } else {
4050             gen_op_mov_TN_reg[ot][0][rm]();
4051         }
4052         if (s->cc_op != CC_OP_DYNAMIC)
4053             gen_op_set_cc_op(s->cc_op);
4054         gen_op_arpl();
4055         s->cc_op = CC_OP_EFLAGS;
4056         if (mod != 3) {
4057             gen_op_st_T0_A0[ot + s->mem_index]();
4058         } else {
4059             gen_op_mov_reg_T0[ot][rm]();
4060         }
4061         gen_op_arpl_update();
4062         break;
4063     case 0x102: /* lar */
4064     case 0x103: /* lsl */
4065         if (!s->pe || s->vm86)
4066             goto illegal_op;
4067         ot = dflag ? OT_LONG : OT_WORD;
4068         modrm = ldub_code(s->pc++);
4069         reg = (modrm >> 3) & 7;
4070         gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
4071         gen_op_mov_TN_reg[ot][1][reg]();
4072         if (s->cc_op != CC_OP_DYNAMIC)
4073             gen_op_set_cc_op(s->cc_op);
4074         if (b == 0x102)
4075             gen_op_lar();
4076         else
4077             gen_op_lsl();
4078         s->cc_op = CC_OP_EFLAGS;
4079         gen_op_mov_reg_T1[ot][reg]();
4080         break;
4081     case 0x118:
4082         modrm = ldub_code(s->pc++);
4083         mod = (modrm >> 6) & 3;
4084         op = (modrm >> 3) & 7;
4085         switch(op) {
4086         case 0: /* prefetchnta */
4087         case 1: /* prefetchnt0 */
4088         case 2: /* prefetchnt0 */
4089         case 3: /* prefetchnt0 */
4090             if (mod == 3)
4091                 goto illegal_op;
4092             gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
4093             /* nothing more to do */
4094             break;
4095         default:
4096             goto illegal_op;
4097         }
4098         break;
4099     case 0x120: /* mov reg, crN */
4100     case 0x122: /* mov crN, reg */
4101         if (s->cpl != 0) {
4102             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4103         } else {
4104             modrm = ldub_code(s->pc++);
4105             if ((modrm & 0xc0) != 0xc0)
4106                 goto illegal_op;
4107             rm = modrm & 7;
4108             reg = (modrm >> 3) & 7;
4109             switch(reg) {
4110             case 0:
4111             case 2:
4112             case 3:
4113             case 4:
4114                 if (b & 2) {
4115                     gen_op_mov_TN_reg[OT_LONG][0][rm]();
4116                     gen_op_movl_crN_T0(reg);
4117                     gen_op_jmp_im(s->pc - s->cs_base);
4118                     gen_eob(s);
4119                 } else {
4120                     gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
4121                     gen_op_mov_reg_T0[OT_LONG][rm]();
4122                 }
4123                 break;
4124             default:
4125                 goto illegal_op;
4126             }
4127         }
4128         break;
4129     case 0x121: /* mov reg, drN */
4130     case 0x123: /* mov drN, reg */
4131         if (s->cpl != 0) {
4132             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4133         } else {
4134             modrm = ldub_code(s->pc++);
4135             if ((modrm & 0xc0) != 0xc0)
4136                 goto illegal_op;
4137             rm = modrm & 7;
4138             reg = (modrm >> 3) & 7;
4139             /* XXX: do it dynamically with CR4.DE bit */
4140             if (reg == 4 || reg == 5)
4141                 goto illegal_op;
4142             if (b & 2) {
4143                 gen_op_mov_TN_reg[OT_LONG][0][rm]();
4144                 gen_op_movl_drN_T0(reg);
4145                 gen_op_jmp_im(s->pc - s->cs_base);
4146                 gen_eob(s);
4147             } else {
4148                 gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
4149                 gen_op_mov_reg_T0[OT_LONG][rm]();
4150             }
4151         }
4152         break;
4153     case 0x106: /* clts */
4154         if (s->cpl != 0) {
4155             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4156         } else {
4157             gen_op_clts();
4158             /* abort block because static cpu state changed */
4159             gen_op_jmp_im(s->pc - s->cs_base);
4160             gen_eob(s);
4161         }
4162         break;
4163     default:
4164         goto illegal_op;
4165     }
4166     /* lock generation */
4167     if (s->prefix & PREFIX_LOCK)
4168         gen_op_unlock();
4169     return s->pc;
4170  illegal_op:
4171     if (s->prefix & PREFIX_LOCK)
4172         gen_op_unlock();
4173     /* XXX: ensure that no lock was generated */
4174     gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
4175     return s->pc;
4176 }
4177
4178 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
4179 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
4180
4181 /* flags read by an operation */
4182 static uint16_t opc_read_flags[NB_OPS] = { 
4183     [INDEX_op_aas] = CC_A,
4184     [INDEX_op_aaa] = CC_A,
4185     [INDEX_op_das] = CC_A | CC_C,
4186     [INDEX_op_daa] = CC_A | CC_C,
4187
4188     /* subtle: due to the incl/decl implementation, C is used */
4189     [INDEX_op_update_inc_cc] = CC_C, 
4190
4191     [INDEX_op_into] = CC_O,
4192
4193     [INDEX_op_jb_subb] = CC_C,
4194     [INDEX_op_jb_subw] = CC_C,
4195     [INDEX_op_jb_subl] = CC_C,
4196
4197     [INDEX_op_jz_subb] = CC_Z,
4198     [INDEX_op_jz_subw] = CC_Z,
4199     [INDEX_op_jz_subl] = CC_Z,
4200
4201     [INDEX_op_jbe_subb] = CC_Z | CC_C,
4202     [INDEX_op_jbe_subw] = CC_Z | CC_C,
4203     [INDEX_op_jbe_subl] = CC_Z | CC_C,
4204
4205     [INDEX_op_js_subb] = CC_S,
4206     [INDEX_op_js_subw] = CC_S,
4207     [INDEX_op_js_subl] = CC_S,
4208
4209     [INDEX_op_jl_subb] = CC_O | CC_S,
4210     [INDEX_op_jl_subw] = CC_O | CC_S,
4211     [INDEX_op_jl_subl] = CC_O | CC_S,
4212
4213     [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
4214     [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
4215     [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
4216
4217     [INDEX_op_loopnzw] = CC_Z,
4218     [INDEX_op_loopnzl] = CC_Z,
4219     [INDEX_op_loopzw] = CC_Z,
4220     [INDEX_op_loopzl] = CC_Z,
4221
4222     [INDEX_op_seto_T0_cc] = CC_O,
4223     [INDEX_op_setb_T0_cc] = CC_C,
4224     [INDEX_op_setz_T0_cc] = CC_Z,
4225     [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
4226     [INDEX_op_sets_T0_cc] = CC_S,
4227     [INDEX_op_setp_T0_cc] = CC_P,
4228     [INDEX_op_setl_T0_cc] = CC_O | CC_S,
4229     [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
4230
4231     [INDEX_op_setb_T0_subb] = CC_C,
4232     [INDEX_op_setb_T0_subw] = CC_C,
4233     [INDEX_op_setb_T0_subl] = CC_C,
4234
4235     [INDEX_op_setz_T0_subb] = CC_Z,
4236     [INDEX_op_setz_T0_subw] = CC_Z,
4237     [INDEX_op_setz_T0_subl] = CC_Z,
4238
4239     [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
4240     [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
4241     [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
4242
4243     [INDEX_op_sets_T0_subb] = CC_S,
4244     [INDEX_op_sets_T0_subw] = CC_S,
4245     [INDEX_op_sets_T0_subl] = CC_S,
4246
4247     [INDEX_op_setl_T0_subb] = CC_O | CC_S,
4248     [INDEX_op_setl_T0_subw] = CC_O | CC_S,
4249     [INDEX_op_setl_T0_subl] = CC_O | CC_S,
4250
4251     [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
4252     [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
4253     [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
4254
4255     [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
4256     [INDEX_op_cmc] = CC_C,
4257     [INDEX_op_salc] = CC_C,
4258
4259     /* needed for correct flag optimisation before string ops */
4260     [INDEX_op_jz_ecxw] = CC_OSZAPC,
4261     [INDEX_op_jz_ecxl] = CC_OSZAPC,
4262     [INDEX_op_jz_ecxw_im] = CC_OSZAPC,
4263     [INDEX_op_jz_ecxl_im] = CC_OSZAPC,
4264
4265 #define DEF_READF(SUFFIX)\
4266     [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4267     [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4268     [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
4269     [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4270     [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4271     [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
4272 \
4273     [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4274     [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4275     [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
4276     [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
4277     [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
4278     [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,
4279
4280
4281     DEF_READF( )
4282     DEF_READF(_raw)
4283 #ifndef CONFIG_USER_ONLY
4284     DEF_READF(_kernel)
4285     DEF_READF(_user)
4286 #endif
4287 };
4288
4289 /* flags written by an operation */
4290 static uint16_t opc_write_flags[NB_OPS] = { 
4291     [INDEX_op_update2_cc] = CC_OSZAPC,
4292     [INDEX_op_update1_cc] = CC_OSZAPC,
4293     [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
4294     [INDEX_op_update_neg_cc] = CC_OSZAPC,
4295     /* subtle: due to the incl/decl implementation, C is used */
4296     [INDEX_op_update_inc_cc] = CC_OSZAPC, 
4297     [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
4298
4299     [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
4300     [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
4301     [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
4302     [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
4303     [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
4304     [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
4305     [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
4306     [INDEX_op_imull_T0_T1] = CC_OSZAPC,
4307     
4308     /* bcd */
4309     [INDEX_op_aam] = CC_OSZAPC,
4310     [INDEX_op_aad] = CC_OSZAPC,
4311     [INDEX_op_aas] = CC_OSZAPC,
4312     [INDEX_op_aaa] = CC_OSZAPC,
4313     [INDEX_op_das] = CC_OSZAPC,
4314     [INDEX_op_daa] = CC_OSZAPC,
4315
4316     [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
4317     [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
4318     [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
4319     [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
4320     [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
4321     [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
4322     [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
4323     [INDEX_op_clc] = CC_C,
4324     [INDEX_op_stc] = CC_C,
4325     [INDEX_op_cmc] = CC_C,
4326
4327     [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
4328     [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
4329     [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
4330     [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
4331     [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
4332     [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
4333     [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
4334     [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
4335
4336     [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
4337     [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
4338     [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
4339     [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
4340
4341     [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4342     [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4343     [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4344
4345     [INDEX_op_cmpxchg8b] = CC_Z,
4346     [INDEX_op_lar] = CC_Z,
4347     [INDEX_op_lsl] = CC_Z,
4348     [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4349     [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4350
4351 #define DEF_WRITEF(SUFFIX)\
4352     [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4353     [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4354     [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4355     [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4356     [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4357     [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4358 \
4359     [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4360     [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4361     [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4362     [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4363     [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4364     [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4365 \
4366     [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4367     [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4368     [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4369     [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4370     [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4371     [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
4372 \
4373     [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4374     [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4375     [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4376 \
4377     [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4378     [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4379     [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4380 \
4381     [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4382     [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4383     [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
4384 \
4385     [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4386     [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4387     [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4388     [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4389 \
4390     [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4391     [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
4392     [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4393     [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
4394 \
4395     [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
4396     [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
4397     [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,
4398
4399
4400     DEF_WRITEF( )
4401     DEF_WRITEF(_raw)
4402 #ifndef CONFIG_USER_ONLY
4403     DEF_WRITEF(_kernel)
4404     DEF_WRITEF(_user)
4405 #endif
4406 };
4407
4408 /* simpler form of an operation if no flags need to be generated */
4409 static uint16_t opc_simpler[NB_OPS] = { 
4410     [INDEX_op_update2_cc] = INDEX_op_nop,
4411     [INDEX_op_update1_cc] = INDEX_op_nop,
4412     [INDEX_op_update_neg_cc] = INDEX_op_nop,
4413 #if 0
4414     /* broken: CC_OP logic must be rewritten */
4415     [INDEX_op_update_inc_cc] = INDEX_op_nop,
4416 #endif
4417
4418     [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4419     [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4420     [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4421
4422     [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4423     [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4424     [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4425
4426     [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4427     [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4428     [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4429
4430 #define DEF_SIMPLER(SUFFIX)\
4431     [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
4432     [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
4433     [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
4434 \
4435     [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
4436     [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
4437     [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,
4438
4439     DEF_SIMPLER( )
4440     DEF_SIMPLER(_raw)
4441 #ifndef CONFIG_USER_ONLY
4442     DEF_SIMPLER(_kernel)
4443     DEF_SIMPLER(_user)
4444 #endif
4445 };
4446
4447 void optimize_flags_init(void)
4448 {
4449     int i;
4450     /* put default values in arrays */
4451     for(i = 0; i < NB_OPS; i++) {
4452         if (opc_simpler[i] == 0)
4453             opc_simpler[i] = i;
4454     }
4455 }
4456
4457 /* CPU flags computation optimization: we move backward thru the
4458    generated code to see which flags are needed. The operation is
4459    modified if suitable */
4460 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4461 {
4462     uint16_t *opc_ptr;
4463     int live_flags, write_flags, op;
4464
4465     opc_ptr = opc_buf + opc_buf_len;
4466     /* live_flags contains the flags needed by the next instructions
4467        in the code. At the end of the bloc, we consider that all the
4468        flags are live. */
4469     live_flags = CC_OSZAPC;
4470     while (opc_ptr > opc_buf) {
4471         op = *--opc_ptr;
4472         /* if none of the flags written by the instruction is used,
4473            then we can try to find a simpler instruction */
4474         write_flags = opc_write_flags[op];
4475         if ((live_flags & write_flags) == 0) {
4476             *opc_ptr = opc_simpler[op];
4477         }
4478         /* compute the live flags before the instruction */
4479         live_flags &= ~write_flags;
4480         live_flags |= opc_read_flags[op];
4481     }
4482 }
4483
4484 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4485    basic block 'tb'. If search_pc is TRUE, also generate PC
4486    information for each intermediate instruction. */
4487 static inline int gen_intermediate_code_internal(CPUState *env,
4488                                                  TranslationBlock *tb, 
4489                                                  int search_pc)
4490 {
4491     DisasContext dc1, *dc = &dc1;
4492     uint8_t *pc_ptr;
4493     uint16_t *gen_opc_end;
4494     int flags, j, lj, cflags;
4495     uint8_t *pc_start;
4496     uint8_t *cs_base;
4497     
4498     /* generate intermediate code */
4499     pc_start = (uint8_t *)tb->pc;
4500     cs_base = (uint8_t *)tb->cs_base;
4501     flags = tb->flags;
4502     cflags = tb->cflags;
4503
4504     dc->pe = (flags >> HF_PE_SHIFT) & 1;
4505     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
4506     dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
4507     dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
4508     dc->f_st = 0;
4509     dc->vm86 = (flags >> VM_SHIFT) & 1;
4510     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
4511     dc->iopl = (flags >> IOPL_SHIFT) & 3;
4512     dc->tf = (flags >> TF_SHIFT) & 1;
4513     dc->singlestep_enabled = env->singlestep_enabled;
4514     dc->cc_op = CC_OP_DYNAMIC;
4515     dc->cs_base = cs_base;
4516     dc->tb = tb;
4517     dc->popl_esp_hack = 0;
4518     /* select memory access functions */
4519     dc->mem_index = 0;
4520     if (flags & HF_SOFTMMU_MASK) {
4521         if (dc->cpl == 3)
4522             dc->mem_index = 6;
4523         else
4524             dc->mem_index = 3;
4525     }
4526     dc->flags = flags;
4527     dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
4528                     (flags & HF_INHIBIT_IRQ_MASK)
4529 #ifndef CONFIG_SOFTMMU
4530                     || (flags & HF_SOFTMMU_MASK)
4531 #endif
4532                     );
4533 #if 0
4534     /* check addseg logic */
4535     if (!dc->addseg && (dc->vm86 || !dc->pe))
4536         printf("ERROR addseg\n");
4537 #endif
4538
4539     gen_opc_ptr = gen_opc_buf;
4540     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4541     gen_opparam_ptr = gen_opparam_buf;
4542
4543     dc->is_jmp = DISAS_NEXT;
4544     pc_ptr = pc_start;
4545     lj = -1;
4546
4547     for(;;) {
4548         if (env->nb_breakpoints > 0) {
4549             for(j = 0; j < env->nb_breakpoints; j++) {
4550                 if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4551                     gen_debug(dc, pc_ptr - dc->cs_base);
4552                     break;
4553                 }
4554             }
4555         }
4556         if (search_pc) {
4557             j = gen_opc_ptr - gen_opc_buf;
4558             if (lj < j) {
4559                 lj++;
4560                 while (lj < j)
4561                     gen_opc_instr_start[lj++] = 0;
4562             }
4563             gen_opc_pc[lj] = (uint32_t)pc_ptr;
4564             gen_opc_cc_op[lj] = dc->cc_op;
4565             gen_opc_instr_start[lj] = 1;
4566         }
4567         pc_ptr = disas_insn(dc, pc_ptr);
4568         /* stop translation if indicated */
4569         if (dc->is_jmp)
4570             break;
4571         /* if single step mode, we generate only one instruction and
4572            generate an exception */
4573         /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
4574            the flag and abort the translation to give the irqs a
4575            change to be happen */
4576         if (dc->tf || dc->singlestep_enabled || 
4577             (flags & HF_INHIBIT_IRQ_MASK) ||
4578             (cflags & CF_SINGLE_INSN)) {
4579             gen_op_jmp_im(pc_ptr - dc->cs_base);
4580             gen_eob(dc);
4581             break;
4582         }
4583         /* if too long translation, stop generation too */
4584         if (gen_opc_ptr >= gen_opc_end ||
4585             (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
4586             gen_op_jmp_im(pc_ptr - dc->cs_base);
4587             gen_eob(dc);
4588             break;
4589         }
4590     }
4591     *gen_opc_ptr = INDEX_op_end;
4592     /* we don't forget to fill the last values */
4593     if (search_pc) {
4594         j = gen_opc_ptr - gen_opc_buf;
4595         lj++;
4596         while (lj <= j)
4597             gen_opc_instr_start[lj++] = 0;
4598     }
4599         
4600 #ifdef DEBUG_DISAS
4601     if (loglevel & CPU_LOG_TB_IN_ASM) {
4602         fprintf(logfile, "----------------\n");
4603         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4604         disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4605         fprintf(logfile, "\n");
4606         if (loglevel & CPU_LOG_TB_OP) {
4607             fprintf(logfile, "OP:\n");
4608             dump_ops(gen_opc_buf, gen_opparam_buf);
4609             fprintf(logfile, "\n");
4610         }
4611     }
4612 #endif
4613
4614     /* optimize flag computations */
4615     optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4616
4617 #ifdef DEBUG_DISAS
4618     if (loglevel & CPU_LOG_TB_OP_OPT) {
4619         fprintf(logfile, "AFTER FLAGS OPT:\n");
4620         dump_ops(gen_opc_buf, gen_opparam_buf);
4621         fprintf(logfile, "\n");
4622     }
4623 #endif
4624     if (!search_pc)
4625         tb->size = pc_ptr - pc_start;
4626     return 0;
4627 }
4628
4629 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4630 {
4631     return gen_intermediate_code_internal(env, tb, 0);
4632 }
4633
4634 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4635 {
4636     return gen_intermediate_code_internal(env, tb, 1);
4637 }
4638