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