4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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
36 #define offsetof(type, field) ((size_t) &((type *)0)->field)
39 /* XXX: move that elsewhere */
40 static uint16_t *gen_opc_ptr
;
41 static uint32_t *gen_opparam_ptr
;
42 int __op_param1
, __op_param2
, __op_param3
;
45 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
51 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
57 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
64 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
66 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
70 p
= start
& ~(MIN_CACHE_LINE_SIZE
- 1);
71 stop
= (stop
+ MIN_CACHE_LINE_SIZE
- 1) & ~(MIN_CACHE_LINE_SIZE
- 1);
73 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
74 asm ("dcbst 0,%0;" : : "r"(p
) : "memory");
77 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
78 asm ("icbi 0,%0; sync;" : : "r"(p
) : "memory");
86 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
94 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
98 p
= start
& ~(8UL - 1UL);
99 stop
= (stop
+ (8UL - 1UL)) & ~(8UL - 1UL);
101 for (; p
< stop
; p
+= 8)
102 __asm__
__volatile__("flush\t%0" : : "r" (p
));
107 extern FILE *logfile
;
110 #define PREFIX_REPZ 0x01
111 #define PREFIX_REPNZ 0x02
112 #define PREFIX_LOCK 0x04
113 #define PREFIX_DATA 0x08
114 #define PREFIX_ADR 0x10
115 #define PREFIX_FWAIT 0x20
117 typedef struct DisasContext
{
118 /* current insn context */
119 int override
; /* -1 if no override */
122 uint8_t *pc
; /* pc = eip + cs_base */
123 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
124 static state change (stop translation) */
125 /* current block context */
126 uint8_t *cs_base
; /* base of CS segment */
127 int code32
; /* 32 bit code segment */
128 int ss32
; /* 32 bit stack segment */
129 int cc_op
; /* current CC operation */
130 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
131 int f_st
; /* currently unused */
132 int vm86
; /* vm86 mode */
137 /* i386 arith/logic operations */
157 OP_SHL1
, /* undocumented */
162 #define DEF(s, n) INDEX_op_ ## s,
163 #include "opc-i386.h"
179 /* I386 int registers */
180 OR_EAX
, /* MUST be even numbered */
188 OR_TMP0
, /* temporary operand register */
190 OR_A0
, /* temporary register used when doing address evaluation */
191 OR_ZERO
, /* fixed zero register */
195 typedef void (GenOpFunc
)(void);
196 typedef void (GenOpFunc1
)(long);
197 typedef void (GenOpFunc2
)(long, long);
199 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
232 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
265 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
288 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
358 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
369 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
381 gen_op_addl_A0_EAX_s1
,
382 gen_op_addl_A0_ECX_s1
,
383 gen_op_addl_A0_EDX_s1
,
384 gen_op_addl_A0_EBX_s1
,
385 gen_op_addl_A0_ESP_s1
,
386 gen_op_addl_A0_EBP_s1
,
387 gen_op_addl_A0_ESI_s1
,
388 gen_op_addl_A0_EDI_s1
,
391 gen_op_addl_A0_EAX_s2
,
392 gen_op_addl_A0_ECX_s2
,
393 gen_op_addl_A0_EDX_s2
,
394 gen_op_addl_A0_EBX_s2
,
395 gen_op_addl_A0_ESP_s2
,
396 gen_op_addl_A0_EBP_s2
,
397 gen_op_addl_A0_ESI_s2
,
398 gen_op_addl_A0_EDI_s2
,
401 gen_op_addl_A0_EAX_s3
,
402 gen_op_addl_A0_ECX_s3
,
403 gen_op_addl_A0_EDX_s3
,
404 gen_op_addl_A0_EBX_s3
,
405 gen_op_addl_A0_ESP_s3
,
406 gen_op_addl_A0_EBP_s3
,
407 gen_op_addl_A0_ESI_s3
,
408 gen_op_addl_A0_EDI_s3
,
412 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
414 gen_op_cmovw_EAX_T1_T0
,
415 gen_op_cmovw_ECX_T1_T0
,
416 gen_op_cmovw_EDX_T1_T0
,
417 gen_op_cmovw_EBX_T1_T0
,
418 gen_op_cmovw_ESP_T1_T0
,
419 gen_op_cmovw_EBP_T1_T0
,
420 gen_op_cmovw_ESI_T1_T0
,
421 gen_op_cmovw_EDI_T1_T0
,
424 gen_op_cmovl_EAX_T1_T0
,
425 gen_op_cmovl_ECX_T1_T0
,
426 gen_op_cmovl_EDX_T1_T0
,
427 gen_op_cmovl_EBX_T1_T0
,
428 gen_op_cmovl_ESP_T1_T0
,
429 gen_op_cmovl_EBP_T1_T0
,
430 gen_op_cmovl_ESI_T1_T0
,
431 gen_op_cmovl_EDI_T1_T0
,
435 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
436 gen_op_addl_T0_T1_cc
,
440 gen_op_andl_T0_T1_cc
,
441 gen_op_subl_T0_T1_cc
,
442 gen_op_xorl_T0_T1_cc
,
443 gen_op_cmpl_T0_T1_cc
,
446 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
448 gen_op_adcb_T0_T1_cc
,
449 gen_op_sbbb_T0_T1_cc
,
452 gen_op_adcw_T0_T1_cc
,
453 gen_op_sbbw_T0_T1_cc
,
456 gen_op_adcl_T0_T1_cc
,
457 gen_op_sbbl_T0_T1_cc
,
461 static const int cc_op_arithb
[8] = {
472 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
473 gen_op_cmpxchgb_T0_T1_EAX_cc
,
474 gen_op_cmpxchgw_T0_T1_EAX_cc
,
475 gen_op_cmpxchgl_T0_T1_EAX_cc
,
478 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
480 gen_op_rolb_T0_T1_cc
,
481 gen_op_rorb_T0_T1_cc
,
482 gen_op_rclb_T0_T1_cc
,
483 gen_op_rcrb_T0_T1_cc
,
484 gen_op_shlb_T0_T1_cc
,
485 gen_op_shrb_T0_T1_cc
,
486 gen_op_shlb_T0_T1_cc
,
487 gen_op_sarb_T0_T1_cc
,
490 gen_op_rolw_T0_T1_cc
,
491 gen_op_rorw_T0_T1_cc
,
492 gen_op_rclw_T0_T1_cc
,
493 gen_op_rcrw_T0_T1_cc
,
494 gen_op_shlw_T0_T1_cc
,
495 gen_op_shrw_T0_T1_cc
,
496 gen_op_shlw_T0_T1_cc
,
497 gen_op_sarw_T0_T1_cc
,
500 gen_op_roll_T0_T1_cc
,
501 gen_op_rorl_T0_T1_cc
,
502 gen_op_rcll_T0_T1_cc
,
503 gen_op_rcrl_T0_T1_cc
,
504 gen_op_shll_T0_T1_cc
,
505 gen_op_shrl_T0_T1_cc
,
506 gen_op_shll_T0_T1_cc
,
507 gen_op_sarl_T0_T1_cc
,
511 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
513 gen_op_shldw_T0_T1_im_cc
,
514 gen_op_shrdw_T0_T1_im_cc
,
517 gen_op_shldl_T0_T1_im_cc
,
518 gen_op_shrdl_T0_T1_im_cc
,
522 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
524 gen_op_shldw_T0_T1_ECX_cc
,
525 gen_op_shrdw_T0_T1_ECX_cc
,
528 gen_op_shldl_T0_T1_ECX_cc
,
529 gen_op_shrdl_T0_T1_ECX_cc
,
533 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
536 gen_op_btsw_T0_T1_cc
,
537 gen_op_btrw_T0_T1_cc
,
538 gen_op_btcw_T0_T1_cc
,
542 gen_op_btsl_T0_T1_cc
,
543 gen_op_btrl_T0_T1_cc
,
544 gen_op_btcl_T0_T1_cc
,
548 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
559 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
564 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
569 /* sign does not matter */
570 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
576 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
582 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
588 /* the _a32 and _a16 string operations use A0 as the base register. */
590 #define STRINGOP(x) \
591 gen_op_ ## x ## b_fast, \
592 gen_op_ ## x ## w_fast, \
593 gen_op_ ## x ## l_fast, \
594 gen_op_ ## x ## b_a32, \
595 gen_op_ ## x ## w_a32, \
596 gen_op_ ## x ## l_a32, \
597 gen_op_ ## x ## b_a16, \
598 gen_op_ ## x ## w_a16, \
599 gen_op_ ## x ## l_a16,
601 static GenOpFunc
*gen_op_movs
[9 * 2] = {
606 static GenOpFunc
*gen_op_stos
[9 * 2] = {
611 static GenOpFunc
*gen_op_lods
[9 * 2] = {
616 static GenOpFunc
*gen_op_scas
[9 * 3] = {
622 static GenOpFunc
*gen_op_cmps
[9 * 3] = {
628 static GenOpFunc
*gen_op_ins
[9 * 2] = {
634 static GenOpFunc
*gen_op_outs
[9 * 2] = {
640 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
644 override
= s
->override
;
647 if (s
->addseg
&& override
< 0)
650 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
658 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
659 /* 16 address, always override */
665 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
682 static GenOpFunc
*gen_op_in
[3] = {
688 static GenOpFunc
*gen_op_out
[3] = {
705 static GenOpFunc2
*gen_jcc_slow
[8] = {
716 static GenOpFunc2
*gen_jcc_sub
[3][8] = {
748 static GenOpFunc2
*gen_op_loop
[2][4] = {
763 static GenOpFunc
*gen_setcc_slow
[8] = {
774 static GenOpFunc
*gen_setcc_sub
[3][8] = {
779 gen_op_setbe_T0_subb
,
783 gen_op_setle_T0_subb
,
789 gen_op_setbe_T0_subw
,
793 gen_op_setle_T0_subw
,
799 gen_op_setbe_T0_subl
,
803 gen_op_setle_T0_subl
,
807 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
813 gen_op_fsubr_ST0_FT0
,
815 gen_op_fdivr_ST0_FT0
,
818 /* NOTE the exception in "r" op ordering */
819 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
824 gen_op_fsubr_STN_ST0
,
826 gen_op_fdivr_STN_ST0
,
830 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
833 gen_op_mov_TN_reg
[ot
][0][d
]();
835 gen_op_mov_TN_reg
[ot
][1][s
]();
836 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
837 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
838 gen_op_set_cc_op(s1
->cc_op
);
839 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
840 s1
->cc_op
= CC_OP_DYNAMIC
;
842 gen_op_arith_T0_T1_cc
[op
]();
843 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
845 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
846 gen_op_mov_reg_T0
[ot
][d
]();
849 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
851 gen_op_movl_T1_im(c
);
852 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
855 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
858 gen_op_mov_TN_reg
[ot
][0][d
]();
859 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
860 gen_op_set_cc_op(s1
->cc_op
);
863 s1
->cc_op
= CC_OP_INCB
+ ot
;
866 s1
->cc_op
= CC_OP_DECB
+ ot
;
869 gen_op_mov_reg_T0
[ot
][d
]();
872 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
875 gen_op_mov_TN_reg
[ot
][0][d
]();
877 gen_op_mov_TN_reg
[ot
][1][s
]();
878 /* for zero counts, flags are not updated, so must do it dynamically */
879 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
880 gen_op_set_cc_op(s1
->cc_op
);
882 gen_op_shift_T0_T1_cc
[ot
][op
]();
885 gen_op_mov_reg_T0
[ot
][d
]();
886 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
889 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
891 /* currently not optimized */
892 gen_op_movl_T1_im(c
);
893 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
896 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
903 int mod
, rm
, code
, override
, must_add_seg
;
905 override
= s
->override
;
906 must_add_seg
= s
->addseg
;
909 mod
= (modrm
>> 6) & 3;
921 code
= ldub(s
->pc
++);
922 scale
= (code
>> 6) & 3;
923 index
= (code
>> 3) & 7;
938 disp
= (int8_t)ldub(s
->pc
++);
948 gen_op_movl_A0_reg
[base
]();
950 gen_op_addl_A0_im(disp
);
952 gen_op_movl_A0_im(disp
);
954 if (havesib
&& (index
!= 4 || scale
!= 0)) {
955 gen_op_addl_A0_reg_sN
[scale
][index
]();
959 if (base
== R_EBP
|| base
== R_ESP
)
964 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
972 gen_op_movl_A0_im(disp
);
973 rm
= 0; /* avoid SS override */
980 disp
= (int8_t)ldub(s
->pc
++);
990 gen_op_movl_A0_reg
[R_EBX
]();
991 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
994 gen_op_movl_A0_reg
[R_EBX
]();
995 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
998 gen_op_movl_A0_reg
[R_EBP
]();
999 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
1002 gen_op_movl_A0_reg
[R_EBP
]();
1003 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
1006 gen_op_movl_A0_reg
[R_ESI
]();
1009 gen_op_movl_A0_reg
[R_EDI
]();
1012 gen_op_movl_A0_reg
[R_EBP
]();
1016 gen_op_movl_A0_reg
[R_EBX
]();
1020 gen_op_addl_A0_im(disp
);
1021 gen_op_andl_A0_ffff();
1025 if (rm
== 2 || rm
== 3 || rm
== 6)
1030 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
1040 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1042 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1044 int mod
, rm
, opreg
, disp
;
1046 mod
= (modrm
>> 6) & 3;
1051 gen_op_mov_TN_reg
[ot
][0][reg
]();
1052 gen_op_mov_reg_T0
[ot
][rm
]();
1054 gen_op_mov_TN_reg
[ot
][0][rm
]();
1056 gen_op_mov_reg_T0
[ot
][reg
]();
1059 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1062 gen_op_mov_TN_reg
[ot
][0][reg
]();
1063 gen_op_st_T0_A0
[ot
]();
1065 gen_op_ld_T0_A0
[ot
]();
1067 gen_op_mov_reg_T0
[ot
][reg
]();
1072 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1094 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1100 jcc_op
= (b
>> 1) & 7;
1102 /* we optimize the cmp/jcc case */
1106 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1111 /* some jumps are easy to compute */
1138 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1141 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1149 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1150 gen_op_set_cc_op(s
->cc_op
);
1151 func
= gen_jcc_slow
[jcc_op
];
1155 func(val
, next_eip
);
1157 func(next_eip
, val
);
1161 static void gen_setcc(DisasContext
*s
, int b
)
1167 jcc_op
= (b
>> 1) & 7;
1169 /* we optimize the cmp/jcc case */
1173 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1178 /* some jumps are easy to compute */
1196 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1199 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1207 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1208 gen_op_set_cc_op(s
->cc_op
);
1209 func
= gen_setcc_slow
[jcc_op
];
1218 /* move T0 to seg_reg and compute if the CPU state may change */
1219 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
)
1221 gen_op_movl_seg_T0(seg_reg
);
1222 if (!s
->addseg
&& seg_reg
< R_FS
)
1223 s
->is_jmp
= 2; /* abort translation because the register may
1224 have a non zero base */
1227 /* generate a push. It depends on ss32, addseg and dflag */
1228 static void gen_push_T0(DisasContext
*s
)
1238 gen_op_pushl_ss32_T0();
1240 gen_op_pushw_ss32_T0();
1244 gen_op_pushl_ss16_T0();
1246 gen_op_pushw_ss16_T0();
1250 /* two step pop is necessary for precise exceptions */
1251 static void gen_pop_T0(DisasContext
*s
)
1261 gen_op_popl_ss32_T0();
1263 gen_op_popw_ss32_T0();
1267 gen_op_popl_ss16_T0();
1269 gen_op_popw_ss16_T0();
1273 static void gen_pop_update(DisasContext
*s
)
1277 gen_op_addl_ESP_4();
1279 gen_op_addl_ESP_2();
1282 gen_op_addw_ESP_4();
1284 gen_op_addw_ESP_2();
1288 /* NOTE: wrap around in 16 bit not fully handled */
1289 static void gen_pusha(DisasContext
*s
)
1292 gen_op_movl_A0_ESP();
1293 gen_op_addl_A0_im(-16 << s
->dflag
);
1295 gen_op_andl_A0_ffff();
1296 gen_op_movl_T1_A0();
1298 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1299 for(i
= 0;i
< 8; i
++) {
1300 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1301 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1302 gen_op_addl_A0_im(2 << s
->dflag
);
1304 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1307 /* NOTE: wrap around in 16 bit not fully handled */
1308 static void gen_popa(DisasContext
*s
)
1311 gen_op_movl_A0_ESP();
1313 gen_op_andl_A0_ffff();
1314 gen_op_movl_T1_A0();
1315 gen_op_addl_T1_im(16 << s
->dflag
);
1317 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1318 for(i
= 0;i
< 8; i
++) {
1319 /* ESP is not reloaded */
1321 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1322 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1324 gen_op_addl_A0_im(2 << s
->dflag
);
1326 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1329 /* NOTE: wrap around in 16 bit not fully handled */
1330 /* XXX: check this */
1331 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1333 int ot
, level1
, addend
, opsize
;
1335 ot
= s
->dflag
+ OT_WORD
;
1338 opsize
= 2 << s
->dflag
;
1340 gen_op_movl_A0_ESP();
1341 gen_op_addl_A0_im(-opsize
);
1343 gen_op_andl_A0_ffff();
1344 gen_op_movl_T1_A0();
1346 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1348 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1349 gen_op_st_T0_A0
[ot
]();
1352 gen_op_addl_A0_im(-opsize
);
1353 gen_op_addl_T0_im(-opsize
);
1354 gen_op_st_T0_A0
[ot
]();
1356 gen_op_addl_A0_im(-opsize
);
1357 /* XXX: add st_T1_A0 ? */
1358 gen_op_movl_T0_T1();
1359 gen_op_st_T0_A0
[ot
]();
1361 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1362 addend
= -esp_addend
;
1364 addend
-= opsize
* (level1
+ 1);
1365 gen_op_addl_T1_im(addend
);
1366 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1369 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1370 is set to true if the instruction sets the PC (last instruction of
1372 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1374 int b
, prefixes
, aflag
, dflag
;
1376 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1377 unsigned int next_eip
;
1387 /* check prefixes */
1390 prefixes
|= PREFIX_REPZ
;
1393 prefixes
|= PREFIX_REPNZ
;
1396 prefixes
|= PREFIX_LOCK
;
1417 prefixes
|= PREFIX_DATA
;
1420 prefixes
|= PREFIX_ADR
;
1423 prefixes
|= PREFIX_FWAIT
;
1427 if (prefixes
& PREFIX_DATA
)
1429 if (prefixes
& PREFIX_ADR
)
1432 s
->prefix
= prefixes
;
1436 /* lock generation */
1437 if (prefixes
& PREFIX_LOCK
)
1440 /* now check op code */
1444 /**************************/
1445 /* extended op code */
1446 b
= ldub(s
->pc
++) | 0x100;
1449 /**************************/
1467 ot
= dflag
? OT_LONG
: OT_WORD
;
1470 case 0: /* OP Ev, Gv */
1471 modrm
= ldub(s
->pc
++);
1472 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1473 mod
= (modrm
>> 6) & 3;
1476 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1477 gen_op_ld_T0_A0
[ot
]();
1480 opreg
= OR_EAX
+ rm
;
1482 gen_op(s
, op
, ot
, opreg
, reg
);
1483 if (mod
!= 3 && op
!= 7) {
1484 gen_op_st_T0_A0
[ot
]();
1487 case 1: /* OP Gv, Ev */
1488 modrm
= ldub(s
->pc
++);
1489 mod
= (modrm
>> 6) & 3;
1490 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1493 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1494 gen_op_ld_T1_A0
[ot
]();
1497 opreg
= OR_EAX
+ rm
;
1499 gen_op(s
, op
, ot
, reg
, opreg
);
1501 case 2: /* OP A, Iv */
1502 val
= insn_get(s
, ot
);
1503 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1509 case 0x80: /* GRP1 */
1518 ot
= dflag
? OT_LONG
: OT_WORD
;
1520 modrm
= ldub(s
->pc
++);
1521 mod
= (modrm
>> 6) & 3;
1523 op
= (modrm
>> 3) & 7;
1526 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1527 gen_op_ld_T0_A0
[ot
]();
1530 opreg
= rm
+ OR_EAX
;
1537 val
= insn_get(s
, ot
);
1540 val
= (int8_t)insn_get(s
, OT_BYTE
);
1544 gen_opi(s
, op
, ot
, opreg
, val
);
1545 if (op
!= 7 && mod
!= 3) {
1546 gen_op_st_T0_A0
[ot
]();
1551 /**************************/
1552 /* inc, dec, and other misc arith */
1553 case 0x40 ... 0x47: /* inc Gv */
1554 ot
= dflag
? OT_LONG
: OT_WORD
;
1555 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1557 case 0x48 ... 0x4f: /* dec Gv */
1558 ot
= dflag
? OT_LONG
: OT_WORD
;
1559 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1561 case 0xf6: /* GRP3 */
1566 ot
= dflag
? OT_LONG
: OT_WORD
;
1568 modrm
= ldub(s
->pc
++);
1569 mod
= (modrm
>> 6) & 3;
1571 op
= (modrm
>> 3) & 7;
1573 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1574 gen_op_ld_T0_A0
[ot
]();
1576 gen_op_mov_TN_reg
[ot
][0][rm
]();
1581 val
= insn_get(s
, ot
);
1582 gen_op_movl_T1_im(val
);
1583 gen_op_testl_T0_T1_cc();
1584 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1589 gen_op_st_T0_A0
[ot
]();
1591 gen_op_mov_reg_T0
[ot
][rm
]();
1595 gen_op_negl_T0_cc();
1597 gen_op_st_T0_A0
[ot
]();
1599 gen_op_mov_reg_T0
[ot
][rm
]();
1601 s
->cc_op
= CC_OP_SUBB
+ ot
;
1606 gen_op_mulb_AL_T0();
1609 gen_op_mulw_AX_T0();
1613 gen_op_mull_EAX_T0();
1616 s
->cc_op
= CC_OP_MUL
;
1621 gen_op_imulb_AL_T0();
1624 gen_op_imulw_AX_T0();
1628 gen_op_imull_EAX_T0();
1631 s
->cc_op
= CC_OP_MUL
;
1636 gen_op_divb_AL_T0();
1639 gen_op_divw_AX_T0();
1643 gen_op_divl_EAX_T0();
1650 gen_op_idivb_AL_T0();
1653 gen_op_idivw_AX_T0();
1657 gen_op_idivl_EAX_T0();
1666 case 0xfe: /* GRP4 */
1667 case 0xff: /* GRP5 */
1671 ot
= dflag
? OT_LONG
: OT_WORD
;
1673 modrm
= ldub(s
->pc
++);
1674 mod
= (modrm
>> 6) & 3;
1676 op
= (modrm
>> 3) & 7;
1677 if (op
>= 2 && b
== 0xfe) {
1681 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1682 if (op
!= 3 && op
!= 5)
1683 gen_op_ld_T0_A0
[ot
]();
1685 gen_op_mov_TN_reg
[ot
][0][rm
]();
1689 case 0: /* inc Ev */
1690 gen_inc(s
, ot
, OR_TMP0
, 1);
1692 gen_op_st_T0_A0
[ot
]();
1694 gen_op_mov_reg_T0
[ot
][rm
]();
1696 case 1: /* dec Ev */
1697 gen_inc(s
, ot
, OR_TMP0
, -1);
1699 gen_op_st_T0_A0
[ot
]();
1701 gen_op_mov_reg_T0
[ot
][rm
]();
1703 case 2: /* call Ev */
1704 /* XXX: optimize if memory (no and is necessary) */
1706 gen_op_andl_T0_ffff();
1708 next_eip
= s
->pc
- s
->cs_base
;
1709 gen_op_movl_T0_im(next_eip
);
1713 case 3: /* lcall Ev */
1714 /* push return segment + offset */
1715 gen_op_movl_T0_seg(R_CS
);
1717 next_eip
= s
->pc
- s
->cs_base
;
1718 gen_op_movl_T0_im(next_eip
);
1721 gen_op_ld_T1_A0
[ot
]();
1722 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1723 gen_op_lduw_T0_A0();
1724 gen_movl_seg_T0(s
, R_CS
);
1725 gen_op_movl_T0_T1();
1729 case 4: /* jmp Ev */
1731 gen_op_andl_T0_ffff();
1735 case 5: /* ljmp Ev */
1736 gen_op_ld_T1_A0
[ot
]();
1737 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1738 gen_op_lduw_T0_A0();
1739 gen_movl_seg_T0(s
, R_CS
);
1740 gen_op_movl_T0_T1();
1744 case 6: /* push Ev */
1752 case 0x84: /* test Ev, Gv */
1757 ot
= dflag
? OT_LONG
: OT_WORD
;
1759 modrm
= ldub(s
->pc
++);
1760 mod
= (modrm
>> 6) & 3;
1762 reg
= (modrm
>> 3) & 7;
1764 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1765 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1766 gen_op_testl_T0_T1_cc();
1767 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1770 case 0xa8: /* test eAX, Iv */
1775 ot
= dflag
? OT_LONG
: OT_WORD
;
1776 val
= insn_get(s
, ot
);
1778 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1779 gen_op_movl_T1_im(val
);
1780 gen_op_testl_T0_T1_cc();
1781 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1784 case 0x98: /* CWDE/CBW */
1786 gen_op_movswl_EAX_AX();
1788 gen_op_movsbw_AX_AL();
1790 case 0x99: /* CDQ/CWD */
1792 gen_op_movslq_EDX_EAX();
1794 gen_op_movswl_DX_AX();
1796 case 0x1af: /* imul Gv, Ev */
1797 case 0x69: /* imul Gv, Ev, I */
1799 ot
= dflag
? OT_LONG
: OT_WORD
;
1800 modrm
= ldub(s
->pc
++);
1801 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1802 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1804 val
= insn_get(s
, ot
);
1805 gen_op_movl_T1_im(val
);
1806 } else if (b
== 0x6b) {
1807 val
= insn_get(s
, OT_BYTE
);
1808 gen_op_movl_T1_im(val
);
1810 gen_op_mov_TN_reg
[ot
][1][reg
]();
1813 if (ot
== OT_LONG
) {
1814 gen_op_imull_T0_T1();
1816 gen_op_imulw_T0_T1();
1818 gen_op_mov_reg_T0
[ot
][reg
]();
1819 s
->cc_op
= CC_OP_MUL
;
1822 case 0x1c1: /* xadd Ev, Gv */
1826 ot
= dflag
? OT_LONG
: OT_WORD
;
1827 modrm
= ldub(s
->pc
++);
1828 reg
= (modrm
>> 3) & 7;
1829 mod
= (modrm
>> 6) & 3;
1832 gen_op_mov_TN_reg
[ot
][0][reg
]();
1833 gen_op_mov_TN_reg
[ot
][1][rm
]();
1834 gen_op_addl_T0_T1_cc();
1835 gen_op_mov_reg_T0
[ot
][rm
]();
1836 gen_op_mov_reg_T1
[ot
][reg
]();
1838 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1839 gen_op_mov_TN_reg
[ot
][0][reg
]();
1840 gen_op_ld_T1_A0
[ot
]();
1841 gen_op_addl_T0_T1_cc();
1842 gen_op_st_T0_A0
[ot
]();
1843 gen_op_mov_reg_T1
[ot
][reg
]();
1845 s
->cc_op
= CC_OP_ADDB
+ ot
;
1848 case 0x1b1: /* cmpxchg Ev, Gv */
1852 ot
= dflag
? OT_LONG
: OT_WORD
;
1853 modrm
= ldub(s
->pc
++);
1854 reg
= (modrm
>> 3) & 7;
1855 mod
= (modrm
>> 6) & 3;
1856 gen_op_mov_TN_reg
[ot
][1][reg
]();
1859 gen_op_mov_TN_reg
[ot
][0][rm
]();
1860 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1861 gen_op_mov_reg_T0
[ot
][rm
]();
1863 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1864 gen_op_ld_T0_A0
[ot
]();
1865 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1866 gen_op_st_T0_A0
[ot
]();
1868 s
->cc_op
= CC_OP_SUBB
+ ot
;
1870 case 0x1c7: /* cmpxchg8b */
1871 modrm
= ldub(s
->pc
++);
1872 mod
= (modrm
>> 6) & 3;
1875 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1876 gen_op_set_cc_op(s
->cc_op
);
1877 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1879 s
->cc_op
= CC_OP_EFLAGS
;
1882 /**************************/
1884 case 0x50 ... 0x57: /* push */
1885 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1888 case 0x58 ... 0x5f: /* pop */
1889 ot
= dflag
? OT_LONG
: OT_WORD
;
1891 gen_op_mov_reg_T0
[ot
][b
& 7]();
1894 case 0x60: /* pusha */
1897 case 0x61: /* popa */
1900 case 0x68: /* push Iv */
1902 ot
= dflag
? OT_LONG
: OT_WORD
;
1904 val
= insn_get(s
, ot
);
1906 val
= (int8_t)insn_get(s
, OT_BYTE
);
1907 gen_op_movl_T0_im(val
);
1910 case 0x8f: /* pop Ev */
1911 ot
= dflag
? OT_LONG
: OT_WORD
;
1912 modrm
= ldub(s
->pc
++);
1914 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1917 case 0xc8: /* enter */
1922 level
= ldub(s
->pc
++);
1923 gen_enter(s
, val
, level
);
1926 case 0xc9: /* leave */
1927 /* XXX: exception not precise (ESP is update before potential exception) */
1929 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1930 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1932 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1933 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1936 ot
= dflag
? OT_LONG
: OT_WORD
;
1937 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1940 case 0x06: /* push es */
1941 case 0x0e: /* push cs */
1942 case 0x16: /* push ss */
1943 case 0x1e: /* push ds */
1944 gen_op_movl_T0_seg(b
>> 3);
1947 case 0x1a0: /* push fs */
1948 case 0x1a8: /* push gs */
1949 gen_op_movl_T0_seg((b
>> 3) & 7);
1952 case 0x07: /* pop es */
1953 case 0x17: /* pop ss */
1954 case 0x1f: /* pop ds */
1956 gen_movl_seg_T0(s
, b
>> 3);
1959 case 0x1a1: /* pop fs */
1960 case 0x1a9: /* pop gs */
1962 gen_movl_seg_T0(s
, (b
>> 3) & 7);
1966 /**************************/
1969 case 0x89: /* mov Gv, Ev */
1973 ot
= dflag
? OT_LONG
: OT_WORD
;
1974 modrm
= ldub(s
->pc
++);
1975 reg
= (modrm
>> 3) & 7;
1977 /* generate a generic store */
1978 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
1981 case 0xc7: /* mov Ev, Iv */
1985 ot
= dflag
? OT_LONG
: OT_WORD
;
1986 modrm
= ldub(s
->pc
++);
1987 mod
= (modrm
>> 6) & 3;
1989 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1990 val
= insn_get(s
, ot
);
1991 gen_op_movl_T0_im(val
);
1993 gen_op_st_T0_A0
[ot
]();
1995 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
1998 case 0x8b: /* mov Ev, Gv */
2002 ot
= dflag
? OT_LONG
: OT_WORD
;
2003 modrm
= ldub(s
->pc
++);
2004 reg
= (modrm
>> 3) & 7;
2006 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2007 gen_op_mov_reg_T0
[ot
][reg
]();
2009 case 0x8e: /* mov seg, Gv */
2010 ot
= dflag
? OT_LONG
: OT_WORD
;
2011 modrm
= ldub(s
->pc
++);
2012 reg
= (modrm
>> 3) & 7;
2013 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2014 if (reg
>= 6 || reg
== R_CS
)
2016 gen_movl_seg_T0(s
, reg
);
2018 case 0x8c: /* mov Gv, seg */
2019 ot
= dflag
? OT_LONG
: OT_WORD
;
2020 modrm
= ldub(s
->pc
++);
2021 reg
= (modrm
>> 3) & 7;
2024 gen_op_movl_T0_seg(reg
);
2025 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2028 case 0x1b6: /* movzbS Gv, Eb */
2029 case 0x1b7: /* movzwS Gv, Eb */
2030 case 0x1be: /* movsbS Gv, Eb */
2031 case 0x1bf: /* movswS Gv, Eb */
2034 /* d_ot is the size of destination */
2035 d_ot
= dflag
+ OT_WORD
;
2036 /* ot is the size of source */
2037 ot
= (b
& 1) + OT_BYTE
;
2038 modrm
= ldub(s
->pc
++);
2039 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2040 mod
= (modrm
>> 6) & 3;
2044 gen_op_mov_TN_reg
[ot
][0][rm
]();
2045 switch(ot
| (b
& 8)) {
2047 gen_op_movzbl_T0_T0();
2050 gen_op_movsbl_T0_T0();
2053 gen_op_movzwl_T0_T0();
2057 gen_op_movswl_T0_T0();
2060 gen_op_mov_reg_T0
[d_ot
][reg
]();
2062 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2064 gen_op_lds_T0_A0
[ot
]();
2066 gen_op_ldu_T0_A0
[ot
]();
2068 gen_op_mov_reg_T0
[d_ot
][reg
]();
2073 case 0x8d: /* lea */
2074 ot
= dflag
? OT_LONG
: OT_WORD
;
2075 modrm
= ldub(s
->pc
++);
2076 reg
= (modrm
>> 3) & 7;
2077 /* we must ensure that no segment is added */
2081 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2083 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2086 case 0xa0: /* mov EAX, Ov */
2088 case 0xa2: /* mov Ov, EAX */
2093 ot
= dflag
? OT_LONG
: OT_WORD
;
2095 offset_addr
= insn_get(s
, OT_LONG
);
2097 offset_addr
= insn_get(s
, OT_WORD
);
2098 gen_op_movl_A0_im(offset_addr
);
2099 /* handle override */
2101 int override
, must_add_seg
;
2102 must_add_seg
= s
->addseg
;
2103 if (s
->override
>= 0) {
2104 override
= s
->override
;
2110 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2114 gen_op_ld_T0_A0
[ot
]();
2115 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2117 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2118 gen_op_st_T0_A0
[ot
]();
2121 case 0xd7: /* xlat */
2122 gen_op_movl_A0_reg
[R_EBX
]();
2123 gen_op_addl_A0_AL();
2125 gen_op_andl_A0_ffff();
2126 /* handle override */
2128 int override
, must_add_seg
;
2129 must_add_seg
= s
->addseg
;
2131 if (s
->override
>= 0) {
2132 override
= s
->override
;
2138 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2141 gen_op_ldub_T0_A0();
2142 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2144 case 0xb0 ... 0xb7: /* mov R, Ib */
2145 val
= insn_get(s
, OT_BYTE
);
2146 gen_op_movl_T0_im(val
);
2147 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2149 case 0xb8 ... 0xbf: /* mov R, Iv */
2150 ot
= dflag
? OT_LONG
: OT_WORD
;
2151 val
= insn_get(s
, ot
);
2152 reg
= OR_EAX
+ (b
& 7);
2153 gen_op_movl_T0_im(val
);
2154 gen_op_mov_reg_T0
[ot
][reg
]();
2157 case 0x91 ... 0x97: /* xchg R, EAX */
2158 ot
= dflag
? OT_LONG
: OT_WORD
;
2163 case 0x87: /* xchg Ev, Gv */
2167 ot
= dflag
? OT_LONG
: OT_WORD
;
2168 modrm
= ldub(s
->pc
++);
2169 reg
= (modrm
>> 3) & 7;
2170 mod
= (modrm
>> 6) & 3;
2174 gen_op_mov_TN_reg
[ot
][0][reg
]();
2175 gen_op_mov_TN_reg
[ot
][1][rm
]();
2176 gen_op_mov_reg_T0
[ot
][rm
]();
2177 gen_op_mov_reg_T1
[ot
][reg
]();
2179 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2180 gen_op_mov_TN_reg
[ot
][0][reg
]();
2181 /* for xchg, lock is implicit */
2182 if (!(prefixes
& PREFIX_LOCK
))
2184 gen_op_ld_T1_A0
[ot
]();
2185 gen_op_st_T0_A0
[ot
]();
2186 if (!(prefixes
& PREFIX_LOCK
))
2188 gen_op_mov_reg_T1
[ot
][reg
]();
2191 case 0xc4: /* les Gv */
2194 case 0xc5: /* lds Gv */
2197 case 0x1b2: /* lss Gv */
2200 case 0x1b4: /* lfs Gv */
2203 case 0x1b5: /* lgs Gv */
2206 ot
= dflag
? OT_LONG
: OT_WORD
;
2207 modrm
= ldub(s
->pc
++);
2208 reg
= (modrm
>> 3) & 7;
2209 mod
= (modrm
>> 6) & 3;
2212 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2213 gen_op_ld_T1_A0
[ot
]();
2214 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2215 /* load the segment first to handle exceptions properly */
2216 gen_op_lduw_T0_A0();
2217 gen_movl_seg_T0(s
, op
);
2218 /* then put the data */
2219 gen_op_mov_reg_T1
[ot
][reg
]();
2222 /************************/
2233 ot
= dflag
? OT_LONG
: OT_WORD
;
2235 modrm
= ldub(s
->pc
++);
2236 mod
= (modrm
>> 6) & 3;
2238 op
= (modrm
>> 3) & 7;
2241 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2242 gen_op_ld_T0_A0
[ot
]();
2245 opreg
= rm
+ OR_EAX
;
2250 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2253 shift
= ldub(s
->pc
++);
2255 gen_shifti(s
, op
, ot
, opreg
, shift
);
2259 gen_op_st_T0_A0
[ot
]();
2274 case 0x1a4: /* shld imm */
2278 case 0x1a5: /* shld cl */
2282 case 0x1ac: /* shrd imm */
2286 case 0x1ad: /* shrd cl */
2290 ot
= dflag
? OT_LONG
: OT_WORD
;
2291 modrm
= ldub(s
->pc
++);
2292 mod
= (modrm
>> 6) & 3;
2294 reg
= (modrm
>> 3) & 7;
2297 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2298 gen_op_ld_T0_A0
[ot
]();
2300 gen_op_mov_TN_reg
[ot
][0][rm
]();
2302 gen_op_mov_TN_reg
[ot
][1][reg
]();
2305 val
= ldub(s
->pc
++);
2308 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2309 if (op
== 0 && ot
!= OT_WORD
)
2310 s
->cc_op
= CC_OP_SHLB
+ ot
;
2312 s
->cc_op
= CC_OP_SARB
+ ot
;
2315 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2316 gen_op_set_cc_op(s
->cc_op
);
2317 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2318 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2321 gen_op_st_T0_A0
[ot
]();
2323 gen_op_mov_reg_T0
[ot
][rm
]();
2327 /************************/
2330 modrm
= ldub(s
->pc
++);
2331 mod
= (modrm
>> 6) & 3;
2333 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2337 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2339 case 0x00 ... 0x07: /* fxxxs */
2340 case 0x10 ... 0x17: /* fixxxl */
2341 case 0x20 ... 0x27: /* fxxxl */
2342 case 0x30 ... 0x37: /* fixxx */
2349 gen_op_flds_FT0_A0();
2352 gen_op_fildl_FT0_A0();
2355 gen_op_fldl_FT0_A0();
2359 gen_op_fild_FT0_A0();
2363 gen_op_fp_arith_ST0_FT0
[op1
]();
2365 /* fcomp needs pop */
2370 case 0x08: /* flds */
2371 case 0x0a: /* fsts */
2372 case 0x0b: /* fstps */
2373 case 0x18: /* fildl */
2374 case 0x1a: /* fistl */
2375 case 0x1b: /* fistpl */
2376 case 0x28: /* fldl */
2377 case 0x2a: /* fstl */
2378 case 0x2b: /* fstpl */
2379 case 0x38: /* filds */
2380 case 0x3a: /* fists */
2381 case 0x3b: /* fistps */
2388 gen_op_flds_ST0_A0();
2391 gen_op_fildl_ST0_A0();
2394 gen_op_fldl_ST0_A0();
2398 gen_op_fild_ST0_A0();
2405 gen_op_fsts_ST0_A0();
2408 gen_op_fistl_ST0_A0();
2411 gen_op_fstl_ST0_A0();
2415 gen_op_fist_ST0_A0();
2423 case 0x0d: /* fldcw mem */
2426 case 0x0f: /* fnstcw mem */
2429 case 0x1d: /* fldt mem */
2431 gen_op_fldt_ST0_A0();
2433 case 0x1f: /* fstpt mem */
2434 gen_op_fstt_ST0_A0();
2437 case 0x2f: /* fnstsw mem */
2440 case 0x3c: /* fbld */
2442 gen_op_fbld_ST0_A0();
2444 case 0x3e: /* fbstp */
2445 gen_op_fbst_ST0_A0();
2448 case 0x3d: /* fildll */
2450 gen_op_fildll_ST0_A0();
2452 case 0x3f: /* fistpll */
2453 gen_op_fistll_ST0_A0();
2460 /* register float ops */
2464 case 0x08: /* fld sti */
2466 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2468 case 0x09: /* fxchg sti */
2469 gen_op_fxchg_ST0_STN(opreg
);
2471 case 0x0a: /* grp d9/2 */
2479 case 0x0c: /* grp d9/4 */
2489 gen_op_fcom_ST0_FT0();
2498 case 0x0d: /* grp d9/5 */
2507 gen_op_fldl2t_ST0();
2511 gen_op_fldl2e_ST0();
2519 gen_op_fldlg2_ST0();
2523 gen_op_fldln2_ST0();
2534 case 0x0e: /* grp d9/6 */
2545 case 3: /* fpatan */
2548 case 4: /* fxtract */
2551 case 5: /* fprem1 */
2554 case 6: /* fdecstp */
2558 case 7: /* fincstp */
2563 case 0x0f: /* grp d9/7 */
2568 case 1: /* fyl2xp1 */
2574 case 3: /* fsincos */
2577 case 5: /* fscale */
2580 case 4: /* frndint */
2592 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2593 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2594 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2600 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2604 gen_op_fmov_FT0_STN(opreg
);
2605 gen_op_fp_arith_ST0_FT0
[op1
]();
2609 case 0x02: /* fcom */
2610 gen_op_fmov_FT0_STN(opreg
);
2611 gen_op_fcom_ST0_FT0();
2613 case 0x03: /* fcomp */
2614 gen_op_fmov_FT0_STN(opreg
);
2615 gen_op_fcom_ST0_FT0();
2618 case 0x15: /* da/5 */
2620 case 1: /* fucompp */
2621 gen_op_fmov_FT0_STN(1);
2622 gen_op_fucom_ST0_FT0();
2635 case 3: /* fninit */
2642 case 0x2a: /* fst sti */
2643 gen_op_fmov_STN_ST0(opreg
);
2645 case 0x2b: /* fstp sti */
2646 gen_op_fmov_STN_ST0(opreg
);
2649 case 0x2c: /* fucom st(i) */
2650 gen_op_fmov_FT0_STN(opreg
);
2651 gen_op_fucom_ST0_FT0();
2653 case 0x2d: /* fucomp st(i) */
2654 gen_op_fmov_FT0_STN(opreg
);
2655 gen_op_fucom_ST0_FT0();
2658 case 0x33: /* de/3 */
2660 case 1: /* fcompp */
2661 gen_op_fmov_FT0_STN(1);
2662 gen_op_fcom_ST0_FT0();
2670 case 0x3c: /* df/4 */
2673 gen_op_fnstsw_EAX();
2684 /************************/
2687 case 0xa4: /* movsS */
2692 ot
= dflag
? OT_LONG
: OT_WORD
;
2694 if (prefixes
& PREFIX_REPZ
) {
2695 gen_string_ds(s
, ot
, gen_op_movs
+ 9);
2697 gen_string_ds(s
, ot
, gen_op_movs
);
2701 case 0xaa: /* stosS */
2706 ot
= dflag
? OT_LONG
: OT_WORD
;
2708 if (prefixes
& PREFIX_REPZ
) {
2709 gen_string_es(s
, ot
, gen_op_stos
+ 9);
2711 gen_string_es(s
, ot
, gen_op_stos
);
2714 case 0xac: /* lodsS */
2719 ot
= dflag
? OT_LONG
: OT_WORD
;
2720 if (prefixes
& PREFIX_REPZ
) {
2721 gen_string_ds(s
, ot
, gen_op_lods
+ 9);
2723 gen_string_ds(s
, ot
, gen_op_lods
);
2726 case 0xae: /* scasS */
2731 ot
= dflag
? OT_LONG
: OT_WORD
;
2732 if (prefixes
& PREFIX_REPNZ
) {
2733 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2734 gen_op_set_cc_op(s
->cc_op
);
2735 gen_string_es(s
, ot
, gen_op_scas
+ 9 * 2);
2736 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2737 } else if (prefixes
& PREFIX_REPZ
) {
2738 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2739 gen_op_set_cc_op(s
->cc_op
);
2740 gen_string_es(s
, ot
, gen_op_scas
+ 9);
2741 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2743 gen_string_es(s
, ot
, gen_op_scas
);
2744 s
->cc_op
= CC_OP_SUBB
+ ot
;
2748 case 0xa6: /* cmpsS */
2753 ot
= dflag
? OT_LONG
: OT_WORD
;
2754 if (prefixes
& PREFIX_REPNZ
) {
2755 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2756 gen_op_set_cc_op(s
->cc_op
);
2757 gen_string_ds(s
, ot
, gen_op_cmps
+ 9 * 2);
2758 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2759 } else if (prefixes
& PREFIX_REPZ
) {
2760 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2761 gen_op_set_cc_op(s
->cc_op
);
2762 gen_string_ds(s
, ot
, gen_op_cmps
+ 9);
2763 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2765 gen_string_ds(s
, ot
, gen_op_cmps
);
2766 s
->cc_op
= CC_OP_SUBB
+ ot
;
2769 case 0x6c: /* insS */
2771 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2772 /* NOTE: even for (E)CX = 0 the exception is raised */
2773 gen_op_gpf(pc_start
- s
->cs_base
);
2778 ot
= dflag
? OT_LONG
: OT_WORD
;
2779 if (prefixes
& PREFIX_REPZ
) {
2780 gen_string_es(s
, ot
, gen_op_ins
+ 9);
2782 gen_string_es(s
, ot
, gen_op_ins
);
2786 case 0x6e: /* outsS */
2788 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2789 /* NOTE: even for (E)CX = 0 the exception is raised */
2790 gen_op_gpf(pc_start
- s
->cs_base
);
2795 ot
= dflag
? OT_LONG
: OT_WORD
;
2796 if (prefixes
& PREFIX_REPZ
) {
2797 gen_string_ds(s
, ot
, gen_op_outs
+ 9);
2799 gen_string_ds(s
, ot
, gen_op_outs
);
2804 /************************/
2808 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2809 gen_op_gpf(pc_start
- s
->cs_base
);
2814 ot
= dflag
? OT_LONG
: OT_WORD
;
2815 val
= ldub(s
->pc
++);
2816 gen_op_movl_T0_im(val
);
2818 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2823 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2824 gen_op_gpf(pc_start
- s
->cs_base
);
2829 ot
= dflag
? OT_LONG
: OT_WORD
;
2830 val
= ldub(s
->pc
++);
2831 gen_op_movl_T0_im(val
);
2832 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2838 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2839 gen_op_gpf(pc_start
- s
->cs_base
);
2844 ot
= dflag
? OT_LONG
: OT_WORD
;
2845 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2847 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2852 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2853 gen_op_gpf(pc_start
- s
->cs_base
);
2858 ot
= dflag
? OT_LONG
: OT_WORD
;
2859 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2860 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2865 /************************/
2867 case 0xc2: /* ret im */
2872 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2874 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2876 gen_op_andl_T0_ffff();
2880 case 0xc3: /* ret */
2884 gen_op_andl_T0_ffff();
2888 case 0xca: /* lret im */
2889 /* XXX: not restartable */
2895 gen_op_andl_T0_ffff();
2900 gen_movl_seg_T0(s
, R_CS
);
2902 /* add stack offset */
2904 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2906 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2909 case 0xcb: /* lret */
2910 /* XXX: not restartable */
2914 gen_op_andl_T0_ffff();
2919 gen_movl_seg_T0(s
, R_CS
);
2923 case 0xcf: /* iret */
2924 /* XXX: not restartable */
2928 gen_op_andl_T0_ffff();
2933 gen_movl_seg_T0(s
, R_CS
);
2939 gen_op_movl_eflags_T0_vm(pc_start
- s
->cs_base
);
2941 gen_op_movl_eflags_T0();
2944 gen_op_movw_eflags_T0_vm(pc_start
- s
->cs_base
);
2946 gen_op_movw_eflags_T0();
2949 s
->cc_op
= CC_OP_EFLAGS
;
2952 case 0xe8: /* call im */
2954 unsigned int next_eip
;
2955 ot
= dflag
? OT_LONG
: OT_WORD
;
2956 val
= insn_get(s
, ot
);
2957 next_eip
= s
->pc
- s
->cs_base
;
2961 gen_op_movl_T0_im(next_eip
);
2967 case 0x9a: /* lcall im */
2969 unsigned int selector
, offset
;
2971 ot
= dflag
? OT_LONG
: OT_WORD
;
2972 offset
= insn_get(s
, ot
);
2973 selector
= insn_get(s
, OT_WORD
);
2975 /* push return segment + offset */
2976 gen_op_movl_T0_seg(R_CS
);
2978 next_eip
= s
->pc
- s
->cs_base
;
2979 gen_op_movl_T0_im(next_eip
);
2982 /* change cs and pc */
2983 gen_op_movl_T0_im(selector
);
2984 gen_movl_seg_T0(s
, R_CS
);
2985 gen_op_jmp_im((unsigned long)offset
);
2989 case 0xe9: /* jmp */
2990 ot
= dflag
? OT_LONG
: OT_WORD
;
2991 val
= insn_get(s
, ot
);
2992 val
+= s
->pc
- s
->cs_base
;
2998 case 0xea: /* ljmp im */
3000 unsigned int selector
, offset
;
3002 ot
= dflag
? OT_LONG
: OT_WORD
;
3003 offset
= insn_get(s
, ot
);
3004 selector
= insn_get(s
, OT_WORD
);
3006 /* change cs and pc */
3007 gen_op_movl_T0_im(selector
);
3008 gen_movl_seg_T0(s
, R_CS
);
3009 gen_op_jmp_im((unsigned long)offset
);
3013 case 0xeb: /* jmp Jb */
3014 val
= (int8_t)insn_get(s
, OT_BYTE
);
3015 val
+= s
->pc
- s
->cs_base
;
3021 case 0x70 ... 0x7f: /* jcc Jb */
3022 val
= (int8_t)insn_get(s
, OT_BYTE
);
3024 case 0x180 ... 0x18f: /* jcc Jv */
3026 val
= insn_get(s
, OT_LONG
);
3028 val
= (int16_t)insn_get(s
, OT_WORD
);
3031 next_eip
= s
->pc
- s
->cs_base
;
3035 gen_jcc(s
, b
, val
, next_eip
);
3039 case 0x190 ... 0x19f: /* setcc Gv */
3040 modrm
= ldub(s
->pc
++);
3042 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
3044 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3045 ot
= dflag
? OT_LONG
: OT_WORD
;
3046 modrm
= ldub(s
->pc
++);
3047 reg
= (modrm
>> 3) & 7;
3048 mod
= (modrm
>> 6) & 3;
3051 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3052 gen_op_ld_T1_A0
[ot
]();
3055 gen_op_mov_TN_reg
[ot
][1][rm
]();
3057 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
3060 /************************/
3062 case 0x9c: /* pushf */
3063 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3064 gen_op_set_cc_op(s
->cc_op
);
3066 gen_op_movl_T0_eflags_vm();
3068 gen_op_movl_T0_eflags();
3071 case 0x9d: /* popf */
3075 gen_op_movl_eflags_T0_vm(pc_start
- s
->cs_base
);
3077 gen_op_movl_eflags_T0();
3080 gen_op_movw_eflags_T0_vm(pc_start
- s
->cs_base
);
3082 gen_op_movw_eflags_T0();
3085 s
->cc_op
= CC_OP_EFLAGS
;
3087 case 0x9e: /* sahf */
3088 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
3089 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3090 gen_op_set_cc_op(s
->cc_op
);
3091 gen_op_movb_eflags_T0();
3092 s
->cc_op
= CC_OP_EFLAGS
;
3094 case 0x9f: /* lahf */
3095 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3096 gen_op_set_cc_op(s
->cc_op
);
3097 gen_op_movl_T0_eflags();
3098 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
3100 case 0xf5: /* cmc */
3101 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3102 gen_op_set_cc_op(s
->cc_op
);
3104 s
->cc_op
= CC_OP_EFLAGS
;
3106 case 0xf8: /* clc */
3107 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3108 gen_op_set_cc_op(s
->cc_op
);
3110 s
->cc_op
= CC_OP_EFLAGS
;
3112 case 0xf9: /* stc */
3113 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3114 gen_op_set_cc_op(s
->cc_op
);
3116 s
->cc_op
= CC_OP_EFLAGS
;
3118 case 0xfc: /* cld */
3121 case 0xfd: /* std */
3125 /************************/
3126 /* bit operations */
3127 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3128 ot
= dflag
? OT_LONG
: OT_WORD
;
3129 modrm
= ldub(s
->pc
++);
3130 op
= (modrm
>> 3) & 7;
3131 mod
= (modrm
>> 6) & 3;
3134 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3135 gen_op_ld_T0_A0
[ot
]();
3137 gen_op_mov_TN_reg
[ot
][0][rm
]();
3140 val
= ldub(s
->pc
++);
3141 gen_op_movl_T1_im(val
);
3145 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3146 s
->cc_op
= CC_OP_SARB
+ ot
;
3149 gen_op_st_T0_A0
[ot
]();
3151 gen_op_mov_reg_T0
[ot
][rm
]();
3154 case 0x1a3: /* bt Gv, Ev */
3157 case 0x1ab: /* bts */
3160 case 0x1b3: /* btr */
3163 case 0x1bb: /* btc */
3166 ot
= dflag
? OT_LONG
: OT_WORD
;
3167 modrm
= ldub(s
->pc
++);
3168 reg
= (modrm
>> 3) & 7;
3169 mod
= (modrm
>> 6) & 3;
3171 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3173 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3174 /* specific case: we need to add a displacement */
3176 gen_op_add_bitw_A0_T1();
3178 gen_op_add_bitl_A0_T1();
3179 gen_op_ld_T0_A0
[ot
]();
3181 gen_op_mov_TN_reg
[ot
][0][rm
]();
3183 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3184 s
->cc_op
= CC_OP_SARB
+ ot
;
3187 gen_op_st_T0_A0
[ot
]();
3189 gen_op_mov_reg_T0
[ot
][rm
]();
3192 case 0x1bc: /* bsf */
3193 case 0x1bd: /* bsr */
3194 ot
= dflag
? OT_LONG
: OT_WORD
;
3195 modrm
= ldub(s
->pc
++);
3196 reg
= (modrm
>> 3) & 7;
3197 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3198 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3199 /* NOTE: we always write back the result. Intel doc says it is
3200 undefined if T0 == 0 */
3201 gen_op_mov_reg_T0
[ot
][reg
]();
3202 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3204 /************************/
3206 case 0x27: /* daa */
3207 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3208 gen_op_set_cc_op(s
->cc_op
);
3210 s
->cc_op
= CC_OP_EFLAGS
;
3212 case 0x2f: /* das */
3213 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3214 gen_op_set_cc_op(s
->cc_op
);
3216 s
->cc_op
= CC_OP_EFLAGS
;
3218 case 0x37: /* aaa */
3219 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3220 gen_op_set_cc_op(s
->cc_op
);
3222 s
->cc_op
= CC_OP_EFLAGS
;
3224 case 0x3f: /* aas */
3225 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3226 gen_op_set_cc_op(s
->cc_op
);
3228 s
->cc_op
= CC_OP_EFLAGS
;
3230 case 0xd4: /* aam */
3231 val
= ldub(s
->pc
++);
3233 s
->cc_op
= CC_OP_LOGICB
;
3235 case 0xd5: /* aad */
3236 val
= ldub(s
->pc
++);
3238 s
->cc_op
= CC_OP_LOGICB
;
3240 /************************/
3242 case 0x90: /* nop */
3244 case 0xcc: /* int3 */
3245 gen_op_int3((long)pc_start
);
3248 case 0xcd: /* int N */
3249 val
= ldub(s
->pc
++);
3250 gen_op_int_im(val
, pc_start
- s
->cs_base
);
3253 case 0xce: /* into */
3254 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3255 gen_op_set_cc_op(s
->cc_op
);
3258 case 0xfa: /* cli */
3260 if (s
->cpl
<= s
->iopl
)
3263 gen_op_gpf(pc_start
- s
->cs_base
);
3271 case 0xfb: /* sti */
3273 if (s
->cpl
<= s
->iopl
)
3276 gen_op_gpf(pc_start
- s
->cs_base
);
3281 gen_op_sti_vm(pc_start
- s
->cs_base
);
3284 case 0x62: /* bound */
3285 ot
= dflag
? OT_LONG
: OT_WORD
;
3286 modrm
= ldub(s
->pc
++);
3287 reg
= (modrm
>> 3) & 7;
3288 mod
= (modrm
>> 6) & 3;
3291 gen_op_mov_reg_T0
[ot
][reg
]();
3292 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3298 case 0x1c8 ... 0x1cf: /* bswap reg */
3300 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3302 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3304 case 0xd6: /* salc */
3305 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3306 gen_op_set_cc_op(s
->cc_op
);
3309 case 0xe0: /* loopnz */
3310 case 0xe1: /* loopz */
3311 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3312 gen_op_set_cc_op(s
->cc_op
);
3314 case 0xe2: /* loop */
3315 case 0xe3: /* jecxz */
3316 val
= (int8_t)insn_get(s
, OT_BYTE
);
3317 next_eip
= s
->pc
- s
->cs_base
;
3321 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3324 case 0x131: /* rdtsc */
3327 case 0x1a2: /* cpuid */
3330 case 0xf4: /* hlt */
3334 gen_op_gpf(pc_start
- s
->cs_base
);
3340 /* lock generation */
3341 if (s
->prefix
& PREFIX_LOCK
)
3345 /* XXX: ensure that no lock was generated */
3349 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3350 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3352 /* flags read by an operation */
3353 static uint16_t opc_read_flags
[NB_OPS
] = {
3354 [INDEX_op_aas
] = CC_A
,
3355 [INDEX_op_aaa
] = CC_A
,
3356 [INDEX_op_das
] = CC_A
| CC_C
,
3357 [INDEX_op_daa
] = CC_A
| CC_C
,
3359 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3360 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3361 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3362 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3363 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3364 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3366 /* subtle: due to the incl/decl implementation, C is used */
3367 [INDEX_op_incl_T0_cc
] = CC_C
,
3368 [INDEX_op_decl_T0_cc
] = CC_C
,
3370 [INDEX_op_into
] = CC_O
,
3372 [INDEX_op_jo_cc
] = CC_O
,
3373 [INDEX_op_jb_cc
] = CC_C
,
3374 [INDEX_op_jz_cc
] = CC_Z
,
3375 [INDEX_op_jbe_cc
] = CC_Z
| CC_C
,
3376 [INDEX_op_js_cc
] = CC_S
,
3377 [INDEX_op_jp_cc
] = CC_P
,
3378 [INDEX_op_jl_cc
] = CC_O
| CC_S
,
3379 [INDEX_op_jle_cc
] = CC_O
| CC_S
| CC_Z
,
3381 [INDEX_op_jb_subb
] = CC_C
,
3382 [INDEX_op_jb_subw
] = CC_C
,
3383 [INDEX_op_jb_subl
] = CC_C
,
3385 [INDEX_op_jz_subb
] = CC_Z
,
3386 [INDEX_op_jz_subw
] = CC_Z
,
3387 [INDEX_op_jz_subl
] = CC_Z
,
3389 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3390 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3391 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3393 [INDEX_op_js_subb
] = CC_S
,
3394 [INDEX_op_js_subw
] = CC_S
,
3395 [INDEX_op_js_subl
] = CC_S
,
3397 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3398 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3399 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3401 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3402 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3403 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3405 [INDEX_op_loopnzw
] = CC_Z
,
3406 [INDEX_op_loopnzl
] = CC_Z
,
3407 [INDEX_op_loopzw
] = CC_Z
,
3408 [INDEX_op_loopzl
] = CC_Z
,
3410 [INDEX_op_seto_T0_cc
] = CC_O
,
3411 [INDEX_op_setb_T0_cc
] = CC_C
,
3412 [INDEX_op_setz_T0_cc
] = CC_Z
,
3413 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3414 [INDEX_op_sets_T0_cc
] = CC_S
,
3415 [INDEX_op_setp_T0_cc
] = CC_P
,
3416 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3417 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3419 [INDEX_op_setb_T0_subb
] = CC_C
,
3420 [INDEX_op_setb_T0_subw
] = CC_C
,
3421 [INDEX_op_setb_T0_subl
] = CC_C
,
3423 [INDEX_op_setz_T0_subb
] = CC_Z
,
3424 [INDEX_op_setz_T0_subw
] = CC_Z
,
3425 [INDEX_op_setz_T0_subl
] = CC_Z
,
3427 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3428 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3429 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3431 [INDEX_op_sets_T0_subb
] = CC_S
,
3432 [INDEX_op_sets_T0_subw
] = CC_S
,
3433 [INDEX_op_sets_T0_subl
] = CC_S
,
3435 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3436 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3437 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3439 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3440 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3441 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3443 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3444 [INDEX_op_movl_T0_eflags_vm
] = CC_OSZAPC
,
3445 [INDEX_op_cmc
] = CC_C
,
3446 [INDEX_op_salc
] = CC_C
,
3448 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3449 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3450 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3451 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3452 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3453 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3456 /* flags written by an operation */
3457 static uint16_t opc_write_flags
[NB_OPS
] = {
3458 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3459 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3460 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3461 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3462 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3463 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3464 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3465 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3466 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3467 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3468 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3469 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3470 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3471 /* subtle: due to the incl/decl implementation, C is used */
3472 [INDEX_op_incl_T0_cc
] = CC_OSZAPC
,
3473 [INDEX_op_decl_T0_cc
] = CC_OSZAPC
,
3474 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3476 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3477 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3478 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3479 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3480 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3481 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3482 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3483 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3486 [INDEX_op_aam
] = CC_OSZAPC
,
3487 [INDEX_op_aad
] = CC_OSZAPC
,
3488 [INDEX_op_aas
] = CC_OSZAPC
,
3489 [INDEX_op_aaa
] = CC_OSZAPC
,
3490 [INDEX_op_das
] = CC_OSZAPC
,
3491 [INDEX_op_daa
] = CC_OSZAPC
,
3493 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3494 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
3495 [INDEX_op_movw_eflags_T0_vm
] = CC_OSZAPC
,
3496 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3497 [INDEX_op_movl_eflags_T0_vm
] = CC_OSZAPC
,
3498 [INDEX_op_clc
] = CC_C
,
3499 [INDEX_op_stc
] = CC_C
,
3500 [INDEX_op_cmc
] = CC_C
,
3502 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3503 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3504 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3505 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3506 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3507 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3509 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3510 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3511 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3512 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3513 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3514 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3516 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3517 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3518 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3520 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3521 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3522 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3524 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3525 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3526 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3528 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3529 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3530 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3531 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3533 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3534 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3535 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3536 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3538 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3539 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3540 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3541 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3542 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3543 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3544 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3545 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3547 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3548 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3549 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3550 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3553 #define STRINGOP(x) \
3554 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3555 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3556 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3557 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3558 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3559 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3560 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3561 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3562 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3566 STRINGOP(repnz_scas
)
3569 STRINGOP(repnz_cmps
)
3571 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
3572 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3573 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3575 [INDEX_op_cmpxchg8b
] = CC_Z
,
3578 /* simpler form of an operation if no flags need to be generated */
3579 static uint16_t opc_simpler
[NB_OPS
] = {
3580 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3581 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3582 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3583 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3584 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3585 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3586 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3587 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3589 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3590 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3591 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3593 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3594 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3595 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3597 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3598 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3599 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3601 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3602 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3603 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3605 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3606 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3607 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3610 static void optimize_flags_init(void)
3613 /* put default values in arrays */
3614 for(i
= 0; i
< NB_OPS
; i
++) {
3615 if (opc_simpler
[i
] == 0)
3620 /* CPU flags computation optimization: we move backward thru the
3621 generated code to see which flags are needed. The operation is
3622 modified if suitable */
3623 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3626 int live_flags
, write_flags
, op
;
3628 opc_ptr
= opc_buf
+ opc_buf_len
;
3629 /* live_flags contains the flags needed by the next instructions
3630 in the code. At the end of the bloc, we consider that all the
3632 live_flags
= CC_OSZAPC
;
3633 while (opc_ptr
> opc_buf
) {
3635 /* if none of the flags written by the instruction is used,
3636 then we can try to find a simpler instruction */
3637 write_flags
= opc_write_flags
[op
];
3638 if ((live_flags
& write_flags
) == 0) {
3639 *opc_ptr
= opc_simpler
[op
];
3641 /* compute the live flags before the instruction */
3642 live_flags
&= ~write_flags
;
3643 live_flags
|= opc_read_flags
[op
];
3649 static const char *op_str
[] = {
3650 #define DEF(s, n) #s,
3651 #include "opc-i386.h"
3655 static uint8_t op_nb_args
[] = {
3656 #define DEF(s, n) n,
3657 #include "opc-i386.h"
3661 static void dump_ops(const uint16_t *opc_buf
, const uint32_t *opparam_buf
)
3663 const uint16_t *opc_ptr
;
3664 const uint32_t *opparam_ptr
;
3668 opparam_ptr
= opparam_buf
;
3672 fprintf(logfile
, "0x%04x: %s", opc_ptr
- opc_buf
- 1, op_str
[c
]);
3673 for(i
= 0; i
< n
; i
++) {
3674 fprintf(logfile
, " 0x%x", opparam_ptr
[i
]);
3676 fprintf(logfile
, "\n");
3677 if (c
== INDEX_op_end
)
3685 /* XXX: make this buffer thread safe */
3686 /* XXX: make safe guess about sizes */
3687 #define MAX_OP_PER_INSTR 32
3688 #define OPC_BUF_SIZE 512
3689 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3691 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3693 static uint16_t gen_opc_buf
[OPC_BUF_SIZE
];
3694 static uint32_t gen_opparam_buf
[OPPARAM_BUF_SIZE
];
3696 /* return non zero if the very first instruction is invalid so that
3697 the virtual CPU can trigger an exception. */
3698 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
3699 int *gen_code_size_ptr
,
3700 uint8_t *pc_start
, uint8_t *cs_base
, int flags
)
3702 DisasContext dc1
, *dc
= &dc1
;
3704 uint16_t *gen_opc_end
;
3708 /* generate intermediate code */
3710 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3711 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3712 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3713 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3714 dc
->vm86
= (flags
>> GEN_FLAG_VM_SHIFT
) & 1;
3715 dc
->cpl
= (flags
>> GEN_FLAG_CPL_SHIFT
) & 3;
3716 dc
->iopl
= (flags
>> GEN_FLAG_IOPL_SHIFT
) & 3;
3717 dc
->cc_op
= CC_OP_DYNAMIC
;
3718 dc
->cs_base
= cs_base
;
3720 gen_opc_ptr
= gen_opc_buf
;
3721 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3722 gen_opparam_ptr
= gen_opparam_buf
;
3727 ret
= disas_insn(dc
, pc_ptr
);
3729 /* we trigger an illegal instruction operation only if it
3730 is the first instruction. Otherwise, we simply stop
3731 generating the code just before it */
3732 if (pc_ptr
== pc_start
)
3737 pc_ptr
= (void *)ret
;
3738 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
);
3739 /* we must store the eflags state if it is not already done */
3740 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3741 gen_op_set_cc_op(dc
->cc_op
);
3742 if (dc
->is_jmp
!= 1) {
3743 /* we add an additionnal jmp to update the simulated PC */
3744 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3746 *gen_opc_ptr
= INDEX_op_end
;
3750 fprintf(logfile
, "----------------\n");
3751 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
3752 disas(logfile
, pc_start
, pc_ptr
- pc_start
,
3753 dc
->code32
? DISAS_I386_I386
: DISAS_I386_I8086
);
3754 fprintf(logfile
, "\n");
3756 fprintf(logfile
, "OP:\n");
3757 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3758 fprintf(logfile
, "\n");
3762 /* optimize flag computations */
3763 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3767 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3768 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3769 fprintf(logfile
, "\n");
3773 /* generate machine code */
3774 gen_code_size
= dyngen_code(gen_code_buf
, gen_opc_buf
, gen_opparam_buf
);
3775 flush_icache_range((unsigned long)gen_code_buf
, (unsigned long)(gen_code_buf
+ gen_code_size
));
3776 *gen_code_size_ptr
= gen_code_size
;
3780 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
3781 disas(logfile
, gen_code_buf
, *gen_code_size_ptr
, DISAS_TARGET
);
3782 fprintf(logfile
, "\n");
3789 CPUX86State
*cpu_x86_init(void)
3795 cpu_x86_tblocks_init();
3797 env
= malloc(sizeof(CPUX86State
));
3800 memset(env
, 0, sizeof(CPUX86State
));
3801 /* basic FPU init */
3802 for(i
= 0;i
< 8; i
++)
3805 /* flags setup : we activate the IRQs by default as in user mode */
3806 env
->eflags
= 0x2 | IF_MASK
;
3808 /* init various static tables */
3811 optimize_flags_init();
3816 void cpu_x86_close(CPUX86State
*env
)