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