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