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 */
135 int tf
; /* TF cpu flag */
138 /* i386 arith/logic operations */
158 OP_SHL1
, /* undocumented */
163 #define DEF(s, n) INDEX_op_ ## s,
164 #include "opc-i386.h"
180 /* I386 int registers */
181 OR_EAX
, /* MUST be even numbered */
189 OR_TMP0
, /* temporary operand register */
191 OR_A0
, /* temporary register used when doing address evaluation */
192 OR_ZERO
, /* fixed zero register */
196 typedef void (GenOpFunc
)(void);
197 typedef void (GenOpFunc1
)(long);
198 typedef void (GenOpFunc2
)(long, long);
200 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
233 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
266 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
289 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
359 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
370 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
382 gen_op_addl_A0_EAX_s1
,
383 gen_op_addl_A0_ECX_s1
,
384 gen_op_addl_A0_EDX_s1
,
385 gen_op_addl_A0_EBX_s1
,
386 gen_op_addl_A0_ESP_s1
,
387 gen_op_addl_A0_EBP_s1
,
388 gen_op_addl_A0_ESI_s1
,
389 gen_op_addl_A0_EDI_s1
,
392 gen_op_addl_A0_EAX_s2
,
393 gen_op_addl_A0_ECX_s2
,
394 gen_op_addl_A0_EDX_s2
,
395 gen_op_addl_A0_EBX_s2
,
396 gen_op_addl_A0_ESP_s2
,
397 gen_op_addl_A0_EBP_s2
,
398 gen_op_addl_A0_ESI_s2
,
399 gen_op_addl_A0_EDI_s2
,
402 gen_op_addl_A0_EAX_s3
,
403 gen_op_addl_A0_ECX_s3
,
404 gen_op_addl_A0_EDX_s3
,
405 gen_op_addl_A0_EBX_s3
,
406 gen_op_addl_A0_ESP_s3
,
407 gen_op_addl_A0_EBP_s3
,
408 gen_op_addl_A0_ESI_s3
,
409 gen_op_addl_A0_EDI_s3
,
413 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
415 gen_op_cmovw_EAX_T1_T0
,
416 gen_op_cmovw_ECX_T1_T0
,
417 gen_op_cmovw_EDX_T1_T0
,
418 gen_op_cmovw_EBX_T1_T0
,
419 gen_op_cmovw_ESP_T1_T0
,
420 gen_op_cmovw_EBP_T1_T0
,
421 gen_op_cmovw_ESI_T1_T0
,
422 gen_op_cmovw_EDI_T1_T0
,
425 gen_op_cmovl_EAX_T1_T0
,
426 gen_op_cmovl_ECX_T1_T0
,
427 gen_op_cmovl_EDX_T1_T0
,
428 gen_op_cmovl_EBX_T1_T0
,
429 gen_op_cmovl_ESP_T1_T0
,
430 gen_op_cmovl_EBP_T1_T0
,
431 gen_op_cmovl_ESI_T1_T0
,
432 gen_op_cmovl_EDI_T1_T0
,
436 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
437 gen_op_addl_T0_T1_cc
,
441 gen_op_andl_T0_T1_cc
,
442 gen_op_subl_T0_T1_cc
,
443 gen_op_xorl_T0_T1_cc
,
444 gen_op_cmpl_T0_T1_cc
,
447 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
449 gen_op_adcb_T0_T1_cc
,
450 gen_op_sbbb_T0_T1_cc
,
453 gen_op_adcw_T0_T1_cc
,
454 gen_op_sbbw_T0_T1_cc
,
457 gen_op_adcl_T0_T1_cc
,
458 gen_op_sbbl_T0_T1_cc
,
462 static const int cc_op_arithb
[8] = {
473 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
474 gen_op_cmpxchgb_T0_T1_EAX_cc
,
475 gen_op_cmpxchgw_T0_T1_EAX_cc
,
476 gen_op_cmpxchgl_T0_T1_EAX_cc
,
479 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
481 gen_op_rolb_T0_T1_cc
,
482 gen_op_rorb_T0_T1_cc
,
483 gen_op_rclb_T0_T1_cc
,
484 gen_op_rcrb_T0_T1_cc
,
485 gen_op_shlb_T0_T1_cc
,
486 gen_op_shrb_T0_T1_cc
,
487 gen_op_shlb_T0_T1_cc
,
488 gen_op_sarb_T0_T1_cc
,
491 gen_op_rolw_T0_T1_cc
,
492 gen_op_rorw_T0_T1_cc
,
493 gen_op_rclw_T0_T1_cc
,
494 gen_op_rcrw_T0_T1_cc
,
495 gen_op_shlw_T0_T1_cc
,
496 gen_op_shrw_T0_T1_cc
,
497 gen_op_shlw_T0_T1_cc
,
498 gen_op_sarw_T0_T1_cc
,
501 gen_op_roll_T0_T1_cc
,
502 gen_op_rorl_T0_T1_cc
,
503 gen_op_rcll_T0_T1_cc
,
504 gen_op_rcrl_T0_T1_cc
,
505 gen_op_shll_T0_T1_cc
,
506 gen_op_shrl_T0_T1_cc
,
507 gen_op_shll_T0_T1_cc
,
508 gen_op_sarl_T0_T1_cc
,
512 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
514 gen_op_shldw_T0_T1_im_cc
,
515 gen_op_shrdw_T0_T1_im_cc
,
518 gen_op_shldl_T0_T1_im_cc
,
519 gen_op_shrdl_T0_T1_im_cc
,
523 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
525 gen_op_shldw_T0_T1_ECX_cc
,
526 gen_op_shrdw_T0_T1_ECX_cc
,
529 gen_op_shldl_T0_T1_ECX_cc
,
530 gen_op_shrdl_T0_T1_ECX_cc
,
534 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
537 gen_op_btsw_T0_T1_cc
,
538 gen_op_btrw_T0_T1_cc
,
539 gen_op_btcw_T0_T1_cc
,
543 gen_op_btsl_T0_T1_cc
,
544 gen_op_btrl_T0_T1_cc
,
545 gen_op_btcl_T0_T1_cc
,
549 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
560 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
565 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
570 /* sign does not matter */
571 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
577 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
583 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
589 /* the _a32 and _a16 string operations use A0 as the base register. */
591 #define STRINGOP(x) \
592 gen_op_ ## x ## b_fast, \
593 gen_op_ ## x ## w_fast, \
594 gen_op_ ## x ## l_fast, \
595 gen_op_ ## x ## b_a32, \
596 gen_op_ ## x ## w_a32, \
597 gen_op_ ## x ## l_a32, \
598 gen_op_ ## x ## b_a16, \
599 gen_op_ ## x ## w_a16, \
600 gen_op_ ## x ## l_a16,
602 static GenOpFunc
*gen_op_movs
[9 * 2] = {
607 static GenOpFunc
*gen_op_stos
[9 * 2] = {
612 static GenOpFunc
*gen_op_lods
[9 * 2] = {
617 static GenOpFunc
*gen_op_scas
[9 * 3] = {
623 static GenOpFunc
*gen_op_cmps
[9 * 3] = {
629 static GenOpFunc
*gen_op_ins
[9 * 2] = {
635 static GenOpFunc
*gen_op_outs
[9 * 2] = {
641 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
645 override
= s
->override
;
648 if (s
->addseg
&& override
< 0)
651 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
659 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
660 /* 16 address, always override */
666 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
683 static GenOpFunc
*gen_op_in
[3] = {
689 static GenOpFunc
*gen_op_out
[3] = {
706 static GenOpFunc2
*gen_jcc_slow
[8] = {
717 static GenOpFunc2
*gen_jcc_sub
[3][8] = {
749 static GenOpFunc2
*gen_op_loop
[2][4] = {
764 static GenOpFunc
*gen_setcc_slow
[8] = {
775 static GenOpFunc
*gen_setcc_sub
[3][8] = {
780 gen_op_setbe_T0_subb
,
784 gen_op_setle_T0_subb
,
790 gen_op_setbe_T0_subw
,
794 gen_op_setle_T0_subw
,
800 gen_op_setbe_T0_subl
,
804 gen_op_setle_T0_subl
,
808 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
814 gen_op_fsubr_ST0_FT0
,
816 gen_op_fdivr_ST0_FT0
,
819 /* NOTE the exception in "r" op ordering */
820 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
825 gen_op_fsubr_STN_ST0
,
827 gen_op_fdivr_STN_ST0
,
831 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
834 gen_op_mov_TN_reg
[ot
][0][d
]();
836 gen_op_mov_TN_reg
[ot
][1][s
]();
837 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
838 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
839 gen_op_set_cc_op(s1
->cc_op
);
840 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
841 s1
->cc_op
= CC_OP_DYNAMIC
;
843 gen_op_arith_T0_T1_cc
[op
]();
844 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
846 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
847 gen_op_mov_reg_T0
[ot
][d
]();
850 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
852 gen_op_movl_T1_im(c
);
853 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
856 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
859 gen_op_mov_TN_reg
[ot
][0][d
]();
860 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
861 gen_op_set_cc_op(s1
->cc_op
);
864 s1
->cc_op
= CC_OP_INCB
+ ot
;
867 s1
->cc_op
= CC_OP_DECB
+ ot
;
870 gen_op_mov_reg_T0
[ot
][d
]();
873 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
876 gen_op_mov_TN_reg
[ot
][0][d
]();
878 gen_op_mov_TN_reg
[ot
][1][s
]();
879 /* for zero counts, flags are not updated, so must do it dynamically */
880 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
881 gen_op_set_cc_op(s1
->cc_op
);
883 gen_op_shift_T0_T1_cc
[ot
][op
]();
886 gen_op_mov_reg_T0
[ot
][d
]();
887 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
890 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
892 /* currently not optimized */
893 gen_op_movl_T1_im(c
);
894 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
897 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
904 int mod
, rm
, code
, override
, must_add_seg
;
906 override
= s
->override
;
907 must_add_seg
= s
->addseg
;
910 mod
= (modrm
>> 6) & 3;
922 code
= ldub(s
->pc
++);
923 scale
= (code
>> 6) & 3;
924 index
= (code
>> 3) & 7;
939 disp
= (int8_t)ldub(s
->pc
++);
949 gen_op_movl_A0_reg
[base
]();
951 gen_op_addl_A0_im(disp
);
953 gen_op_movl_A0_im(disp
);
955 if (havesib
&& (index
!= 4 || scale
!= 0)) {
956 gen_op_addl_A0_reg_sN
[scale
][index
]();
960 if (base
== R_EBP
|| base
== R_ESP
)
965 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
973 gen_op_movl_A0_im(disp
);
974 rm
= 0; /* avoid SS override */
981 disp
= (int8_t)ldub(s
->pc
++);
991 gen_op_movl_A0_reg
[R_EBX
]();
992 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
995 gen_op_movl_A0_reg
[R_EBX
]();
996 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
999 gen_op_movl_A0_reg
[R_EBP
]();
1000 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
1003 gen_op_movl_A0_reg
[R_EBP
]();
1004 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
1007 gen_op_movl_A0_reg
[R_ESI
]();
1010 gen_op_movl_A0_reg
[R_EDI
]();
1013 gen_op_movl_A0_reg
[R_EBP
]();
1017 gen_op_movl_A0_reg
[R_EBX
]();
1021 gen_op_addl_A0_im(disp
);
1022 gen_op_andl_A0_ffff();
1026 if (rm
== 2 || rm
== 3 || rm
== 6)
1031 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
1041 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1043 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1045 int mod
, rm
, opreg
, disp
;
1047 mod
= (modrm
>> 6) & 3;
1052 gen_op_mov_TN_reg
[ot
][0][reg
]();
1053 gen_op_mov_reg_T0
[ot
][rm
]();
1055 gen_op_mov_TN_reg
[ot
][0][rm
]();
1057 gen_op_mov_reg_T0
[ot
][reg
]();
1060 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1063 gen_op_mov_TN_reg
[ot
][0][reg
]();
1064 gen_op_st_T0_A0
[ot
]();
1066 gen_op_ld_T0_A0
[ot
]();
1068 gen_op_mov_reg_T0
[ot
][reg
]();
1073 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1095 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1101 jcc_op
= (b
>> 1) & 7;
1103 /* we optimize the cmp/jcc case */
1107 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1112 /* some jumps are easy to compute */
1139 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1142 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1150 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1151 gen_op_set_cc_op(s
->cc_op
);
1152 func
= gen_jcc_slow
[jcc_op
];
1156 func(val
, next_eip
);
1158 func(next_eip
, val
);
1162 static void gen_setcc(DisasContext
*s
, int b
)
1168 jcc_op
= (b
>> 1) & 7;
1170 /* we optimize the cmp/jcc case */
1174 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1179 /* some jumps are easy to compute */
1197 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1200 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1208 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1209 gen_op_set_cc_op(s
->cc_op
);
1210 func
= gen_setcc_slow
[jcc_op
];
1219 /* move T0 to seg_reg and compute if the CPU state may change */
1220 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
)
1222 gen_op_movl_seg_T0(seg_reg
);
1223 if (!s
->addseg
&& seg_reg
< R_FS
)
1224 s
->is_jmp
= 2; /* abort translation because the register may
1225 have a non zero base */
1228 /* generate a push. It depends on ss32, addseg and dflag */
1229 static void gen_push_T0(DisasContext
*s
)
1239 gen_op_pushl_ss32_T0();
1241 gen_op_pushw_ss32_T0();
1245 gen_op_pushl_ss16_T0();
1247 gen_op_pushw_ss16_T0();
1251 /* two step pop is necessary for precise exceptions */
1252 static void gen_pop_T0(DisasContext
*s
)
1262 gen_op_popl_ss32_T0();
1264 gen_op_popw_ss32_T0();
1268 gen_op_popl_ss16_T0();
1270 gen_op_popw_ss16_T0();
1274 static void gen_pop_update(DisasContext
*s
)
1278 gen_op_addl_ESP_4();
1280 gen_op_addl_ESP_2();
1283 gen_op_addw_ESP_4();
1285 gen_op_addw_ESP_2();
1289 /* NOTE: wrap around in 16 bit not fully handled */
1290 static void gen_pusha(DisasContext
*s
)
1293 gen_op_movl_A0_ESP();
1294 gen_op_addl_A0_im(-16 << s
->dflag
);
1296 gen_op_andl_A0_ffff();
1297 gen_op_movl_T1_A0();
1299 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1300 for(i
= 0;i
< 8; i
++) {
1301 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1302 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1303 gen_op_addl_A0_im(2 << s
->dflag
);
1305 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1308 /* NOTE: wrap around in 16 bit not fully handled */
1309 static void gen_popa(DisasContext
*s
)
1312 gen_op_movl_A0_ESP();
1314 gen_op_andl_A0_ffff();
1315 gen_op_movl_T1_A0();
1316 gen_op_addl_T1_im(16 << s
->dflag
);
1318 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1319 for(i
= 0;i
< 8; i
++) {
1320 /* ESP is not reloaded */
1322 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1323 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1325 gen_op_addl_A0_im(2 << s
->dflag
);
1327 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1330 /* NOTE: wrap around in 16 bit not fully handled */
1331 /* XXX: check this */
1332 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1334 int ot
, level1
, addend
, opsize
;
1336 ot
= s
->dflag
+ OT_WORD
;
1339 opsize
= 2 << s
->dflag
;
1341 gen_op_movl_A0_ESP();
1342 gen_op_addl_A0_im(-opsize
);
1344 gen_op_andl_A0_ffff();
1345 gen_op_movl_T1_A0();
1347 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1349 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1350 gen_op_st_T0_A0
[ot
]();
1353 gen_op_addl_A0_im(-opsize
);
1354 gen_op_addl_T0_im(-opsize
);
1355 gen_op_st_T0_A0
[ot
]();
1357 gen_op_addl_A0_im(-opsize
);
1358 /* XXX: add st_T1_A0 ? */
1359 gen_op_movl_T0_T1();
1360 gen_op_st_T0_A0
[ot
]();
1362 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1363 addend
= -esp_addend
;
1365 addend
-= opsize
* (level1
+ 1);
1366 gen_op_addl_T1_im(addend
);
1367 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1370 static void gen_exception(DisasContext
*s
, int trapno
, unsigned int cur_eip
)
1372 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1373 gen_op_set_cc_op(s
->cc_op
);
1374 gen_op_jmp_im(cur_eip
);
1375 gen_op_raise_exception(trapno
);
1379 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1380 is set to true if the instruction sets the PC (last instruction of
1382 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1384 int b
, prefixes
, aflag
, dflag
;
1386 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1387 unsigned int next_eip
;
1397 /* check prefixes */
1400 prefixes
|= PREFIX_REPZ
;
1403 prefixes
|= PREFIX_REPNZ
;
1406 prefixes
|= PREFIX_LOCK
;
1427 prefixes
|= PREFIX_DATA
;
1430 prefixes
|= PREFIX_ADR
;
1433 prefixes
|= PREFIX_FWAIT
;
1437 if (prefixes
& PREFIX_DATA
)
1439 if (prefixes
& PREFIX_ADR
)
1442 s
->prefix
= prefixes
;
1446 /* lock generation */
1447 if (prefixes
& PREFIX_LOCK
)
1450 /* now check op code */
1454 /**************************/
1455 /* extended op code */
1456 b
= ldub(s
->pc
++) | 0x100;
1459 /**************************/
1477 ot
= dflag
? OT_LONG
: OT_WORD
;
1480 case 0: /* OP Ev, Gv */
1481 modrm
= ldub(s
->pc
++);
1482 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1483 mod
= (modrm
>> 6) & 3;
1486 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1487 gen_op_ld_T0_A0
[ot
]();
1490 opreg
= OR_EAX
+ rm
;
1492 gen_op(s
, op
, ot
, opreg
, reg
);
1493 if (mod
!= 3 && op
!= 7) {
1494 gen_op_st_T0_A0
[ot
]();
1497 case 1: /* OP Gv, Ev */
1498 modrm
= ldub(s
->pc
++);
1499 mod
= (modrm
>> 6) & 3;
1500 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1503 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1504 gen_op_ld_T1_A0
[ot
]();
1507 opreg
= OR_EAX
+ rm
;
1509 gen_op(s
, op
, ot
, reg
, opreg
);
1511 case 2: /* OP A, Iv */
1512 val
= insn_get(s
, ot
);
1513 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1519 case 0x80: /* GRP1 */
1528 ot
= dflag
? OT_LONG
: OT_WORD
;
1530 modrm
= ldub(s
->pc
++);
1531 mod
= (modrm
>> 6) & 3;
1533 op
= (modrm
>> 3) & 7;
1536 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1537 gen_op_ld_T0_A0
[ot
]();
1540 opreg
= rm
+ OR_EAX
;
1547 val
= insn_get(s
, ot
);
1550 val
= (int8_t)insn_get(s
, OT_BYTE
);
1554 gen_opi(s
, op
, ot
, opreg
, val
);
1555 if (op
!= 7 && mod
!= 3) {
1556 gen_op_st_T0_A0
[ot
]();
1561 /**************************/
1562 /* inc, dec, and other misc arith */
1563 case 0x40 ... 0x47: /* inc Gv */
1564 ot
= dflag
? OT_LONG
: OT_WORD
;
1565 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1567 case 0x48 ... 0x4f: /* dec Gv */
1568 ot
= dflag
? OT_LONG
: OT_WORD
;
1569 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1571 case 0xf6: /* GRP3 */
1576 ot
= dflag
? OT_LONG
: OT_WORD
;
1578 modrm
= ldub(s
->pc
++);
1579 mod
= (modrm
>> 6) & 3;
1581 op
= (modrm
>> 3) & 7;
1583 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1584 gen_op_ld_T0_A0
[ot
]();
1586 gen_op_mov_TN_reg
[ot
][0][rm
]();
1591 val
= insn_get(s
, ot
);
1592 gen_op_movl_T1_im(val
);
1593 gen_op_testl_T0_T1_cc();
1594 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1599 gen_op_st_T0_A0
[ot
]();
1601 gen_op_mov_reg_T0
[ot
][rm
]();
1605 gen_op_negl_T0_cc();
1607 gen_op_st_T0_A0
[ot
]();
1609 gen_op_mov_reg_T0
[ot
][rm
]();
1611 s
->cc_op
= CC_OP_SUBB
+ ot
;
1616 gen_op_mulb_AL_T0();
1619 gen_op_mulw_AX_T0();
1623 gen_op_mull_EAX_T0();
1626 s
->cc_op
= CC_OP_MUL
;
1631 gen_op_imulb_AL_T0();
1634 gen_op_imulw_AX_T0();
1638 gen_op_imull_EAX_T0();
1641 s
->cc_op
= CC_OP_MUL
;
1646 gen_op_divb_AL_T0();
1649 gen_op_divw_AX_T0();
1653 gen_op_divl_EAX_T0();
1660 gen_op_idivb_AL_T0();
1663 gen_op_idivw_AX_T0();
1667 gen_op_idivl_EAX_T0();
1676 case 0xfe: /* GRP4 */
1677 case 0xff: /* GRP5 */
1681 ot
= dflag
? OT_LONG
: OT_WORD
;
1683 modrm
= ldub(s
->pc
++);
1684 mod
= (modrm
>> 6) & 3;
1686 op
= (modrm
>> 3) & 7;
1687 if (op
>= 2 && b
== 0xfe) {
1691 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1692 if (op
!= 3 && op
!= 5)
1693 gen_op_ld_T0_A0
[ot
]();
1695 gen_op_mov_TN_reg
[ot
][0][rm
]();
1699 case 0: /* inc Ev */
1700 gen_inc(s
, ot
, OR_TMP0
, 1);
1702 gen_op_st_T0_A0
[ot
]();
1704 gen_op_mov_reg_T0
[ot
][rm
]();
1706 case 1: /* dec Ev */
1707 gen_inc(s
, ot
, OR_TMP0
, -1);
1709 gen_op_st_T0_A0
[ot
]();
1711 gen_op_mov_reg_T0
[ot
][rm
]();
1713 case 2: /* call Ev */
1714 /* XXX: optimize if memory (no and is necessary) */
1716 gen_op_andl_T0_ffff();
1718 next_eip
= s
->pc
- s
->cs_base
;
1719 gen_op_movl_T0_im(next_eip
);
1723 case 3: /* lcall Ev */
1724 /* push return segment + offset */
1725 gen_op_movl_T0_seg(R_CS
);
1727 next_eip
= s
->pc
- s
->cs_base
;
1728 gen_op_movl_T0_im(next_eip
);
1731 gen_op_ld_T1_A0
[ot
]();
1732 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1733 gen_op_lduw_T0_A0();
1734 gen_movl_seg_T0(s
, R_CS
);
1735 gen_op_movl_T0_T1();
1739 case 4: /* jmp Ev */
1741 gen_op_andl_T0_ffff();
1745 case 5: /* ljmp Ev */
1746 gen_op_ld_T1_A0
[ot
]();
1747 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1748 gen_op_lduw_T0_A0();
1749 gen_movl_seg_T0(s
, R_CS
);
1750 gen_op_movl_T0_T1();
1754 case 6: /* push Ev */
1762 case 0x84: /* test Ev, Gv */
1767 ot
= dflag
? OT_LONG
: OT_WORD
;
1769 modrm
= ldub(s
->pc
++);
1770 mod
= (modrm
>> 6) & 3;
1772 reg
= (modrm
>> 3) & 7;
1774 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1775 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1776 gen_op_testl_T0_T1_cc();
1777 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1780 case 0xa8: /* test eAX, Iv */
1785 ot
= dflag
? OT_LONG
: OT_WORD
;
1786 val
= insn_get(s
, ot
);
1788 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1789 gen_op_movl_T1_im(val
);
1790 gen_op_testl_T0_T1_cc();
1791 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1794 case 0x98: /* CWDE/CBW */
1796 gen_op_movswl_EAX_AX();
1798 gen_op_movsbw_AX_AL();
1800 case 0x99: /* CDQ/CWD */
1802 gen_op_movslq_EDX_EAX();
1804 gen_op_movswl_DX_AX();
1806 case 0x1af: /* imul Gv, Ev */
1807 case 0x69: /* imul Gv, Ev, I */
1809 ot
= dflag
? OT_LONG
: OT_WORD
;
1810 modrm
= ldub(s
->pc
++);
1811 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1812 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1814 val
= insn_get(s
, ot
);
1815 gen_op_movl_T1_im(val
);
1816 } else if (b
== 0x6b) {
1817 val
= insn_get(s
, OT_BYTE
);
1818 gen_op_movl_T1_im(val
);
1820 gen_op_mov_TN_reg
[ot
][1][reg
]();
1823 if (ot
== OT_LONG
) {
1824 gen_op_imull_T0_T1();
1826 gen_op_imulw_T0_T1();
1828 gen_op_mov_reg_T0
[ot
][reg
]();
1829 s
->cc_op
= CC_OP_MUL
;
1832 case 0x1c1: /* xadd Ev, Gv */
1836 ot
= dflag
? OT_LONG
: OT_WORD
;
1837 modrm
= ldub(s
->pc
++);
1838 reg
= (modrm
>> 3) & 7;
1839 mod
= (modrm
>> 6) & 3;
1842 gen_op_mov_TN_reg
[ot
][0][reg
]();
1843 gen_op_mov_TN_reg
[ot
][1][rm
]();
1844 gen_op_addl_T0_T1_cc();
1845 gen_op_mov_reg_T0
[ot
][rm
]();
1846 gen_op_mov_reg_T1
[ot
][reg
]();
1848 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1849 gen_op_mov_TN_reg
[ot
][0][reg
]();
1850 gen_op_ld_T1_A0
[ot
]();
1851 gen_op_addl_T0_T1_cc();
1852 gen_op_st_T0_A0
[ot
]();
1853 gen_op_mov_reg_T1
[ot
][reg
]();
1855 s
->cc_op
= CC_OP_ADDB
+ ot
;
1858 case 0x1b1: /* cmpxchg Ev, Gv */
1862 ot
= dflag
? OT_LONG
: OT_WORD
;
1863 modrm
= ldub(s
->pc
++);
1864 reg
= (modrm
>> 3) & 7;
1865 mod
= (modrm
>> 6) & 3;
1866 gen_op_mov_TN_reg
[ot
][1][reg
]();
1869 gen_op_mov_TN_reg
[ot
][0][rm
]();
1870 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1871 gen_op_mov_reg_T0
[ot
][rm
]();
1873 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1874 gen_op_ld_T0_A0
[ot
]();
1875 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1876 gen_op_st_T0_A0
[ot
]();
1878 s
->cc_op
= CC_OP_SUBB
+ ot
;
1880 case 0x1c7: /* cmpxchg8b */
1881 modrm
= ldub(s
->pc
++);
1882 mod
= (modrm
>> 6) & 3;
1885 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1886 gen_op_set_cc_op(s
->cc_op
);
1887 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1889 s
->cc_op
= CC_OP_EFLAGS
;
1892 /**************************/
1894 case 0x50 ... 0x57: /* push */
1895 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1898 case 0x58 ... 0x5f: /* pop */
1899 ot
= dflag
? OT_LONG
: OT_WORD
;
1901 gen_op_mov_reg_T0
[ot
][b
& 7]();
1904 case 0x60: /* pusha */
1907 case 0x61: /* popa */
1910 case 0x68: /* push Iv */
1912 ot
= dflag
? OT_LONG
: OT_WORD
;
1914 val
= insn_get(s
, ot
);
1916 val
= (int8_t)insn_get(s
, OT_BYTE
);
1917 gen_op_movl_T0_im(val
);
1920 case 0x8f: /* pop Ev */
1921 ot
= dflag
? OT_LONG
: OT_WORD
;
1922 modrm
= ldub(s
->pc
++);
1924 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1927 case 0xc8: /* enter */
1932 level
= ldub(s
->pc
++);
1933 gen_enter(s
, val
, level
);
1936 case 0xc9: /* leave */
1937 /* XXX: exception not precise (ESP is update before potential exception) */
1939 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1940 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1942 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1943 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1946 ot
= dflag
? OT_LONG
: OT_WORD
;
1947 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1950 case 0x06: /* push es */
1951 case 0x0e: /* push cs */
1952 case 0x16: /* push ss */
1953 case 0x1e: /* push ds */
1954 gen_op_movl_T0_seg(b
>> 3);
1957 case 0x1a0: /* push fs */
1958 case 0x1a8: /* push gs */
1959 gen_op_movl_T0_seg((b
>> 3) & 7);
1962 case 0x07: /* pop es */
1963 case 0x17: /* pop ss */
1964 case 0x1f: /* pop ds */
1966 gen_movl_seg_T0(s
, b
>> 3);
1969 case 0x1a1: /* pop fs */
1970 case 0x1a9: /* pop gs */
1972 gen_movl_seg_T0(s
, (b
>> 3) & 7);
1976 /**************************/
1979 case 0x89: /* mov Gv, Ev */
1983 ot
= dflag
? OT_LONG
: OT_WORD
;
1984 modrm
= ldub(s
->pc
++);
1985 reg
= (modrm
>> 3) & 7;
1987 /* generate a generic store */
1988 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
1991 case 0xc7: /* mov Ev, Iv */
1995 ot
= dflag
? OT_LONG
: OT_WORD
;
1996 modrm
= ldub(s
->pc
++);
1997 mod
= (modrm
>> 6) & 3;
1999 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2000 val
= insn_get(s
, ot
);
2001 gen_op_movl_T0_im(val
);
2003 gen_op_st_T0_A0
[ot
]();
2005 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
2008 case 0x8b: /* mov Ev, Gv */
2012 ot
= dflag
? OT_LONG
: OT_WORD
;
2013 modrm
= ldub(s
->pc
++);
2014 reg
= (modrm
>> 3) & 7;
2016 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2017 gen_op_mov_reg_T0
[ot
][reg
]();
2019 case 0x8e: /* mov seg, Gv */
2020 ot
= dflag
? OT_LONG
: OT_WORD
;
2021 modrm
= ldub(s
->pc
++);
2022 reg
= (modrm
>> 3) & 7;
2023 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2024 if (reg
>= 6 || reg
== R_CS
)
2026 gen_movl_seg_T0(s
, reg
);
2028 case 0x8c: /* mov Gv, seg */
2029 ot
= dflag
? OT_LONG
: OT_WORD
;
2030 modrm
= ldub(s
->pc
++);
2031 reg
= (modrm
>> 3) & 7;
2034 gen_op_movl_T0_seg(reg
);
2035 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2038 case 0x1b6: /* movzbS Gv, Eb */
2039 case 0x1b7: /* movzwS Gv, Eb */
2040 case 0x1be: /* movsbS Gv, Eb */
2041 case 0x1bf: /* movswS Gv, Eb */
2044 /* d_ot is the size of destination */
2045 d_ot
= dflag
+ OT_WORD
;
2046 /* ot is the size of source */
2047 ot
= (b
& 1) + OT_BYTE
;
2048 modrm
= ldub(s
->pc
++);
2049 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2050 mod
= (modrm
>> 6) & 3;
2054 gen_op_mov_TN_reg
[ot
][0][rm
]();
2055 switch(ot
| (b
& 8)) {
2057 gen_op_movzbl_T0_T0();
2060 gen_op_movsbl_T0_T0();
2063 gen_op_movzwl_T0_T0();
2067 gen_op_movswl_T0_T0();
2070 gen_op_mov_reg_T0
[d_ot
][reg
]();
2072 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2074 gen_op_lds_T0_A0
[ot
]();
2076 gen_op_ldu_T0_A0
[ot
]();
2078 gen_op_mov_reg_T0
[d_ot
][reg
]();
2083 case 0x8d: /* lea */
2084 ot
= dflag
? OT_LONG
: OT_WORD
;
2085 modrm
= ldub(s
->pc
++);
2086 reg
= (modrm
>> 3) & 7;
2087 /* we must ensure that no segment is added */
2091 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2093 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2096 case 0xa0: /* mov EAX, Ov */
2098 case 0xa2: /* mov Ov, EAX */
2103 ot
= dflag
? OT_LONG
: OT_WORD
;
2105 offset_addr
= insn_get(s
, OT_LONG
);
2107 offset_addr
= insn_get(s
, OT_WORD
);
2108 gen_op_movl_A0_im(offset_addr
);
2109 /* handle override */
2111 int override
, must_add_seg
;
2112 must_add_seg
= s
->addseg
;
2113 if (s
->override
>= 0) {
2114 override
= s
->override
;
2120 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2124 gen_op_ld_T0_A0
[ot
]();
2125 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2127 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2128 gen_op_st_T0_A0
[ot
]();
2131 case 0xd7: /* xlat */
2132 gen_op_movl_A0_reg
[R_EBX
]();
2133 gen_op_addl_A0_AL();
2135 gen_op_andl_A0_ffff();
2136 /* handle override */
2138 int override
, must_add_seg
;
2139 must_add_seg
= s
->addseg
;
2141 if (s
->override
>= 0) {
2142 override
= s
->override
;
2148 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2151 gen_op_ldub_T0_A0();
2152 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2154 case 0xb0 ... 0xb7: /* mov R, Ib */
2155 val
= insn_get(s
, OT_BYTE
);
2156 gen_op_movl_T0_im(val
);
2157 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2159 case 0xb8 ... 0xbf: /* mov R, Iv */
2160 ot
= dflag
? OT_LONG
: OT_WORD
;
2161 val
= insn_get(s
, ot
);
2162 reg
= OR_EAX
+ (b
& 7);
2163 gen_op_movl_T0_im(val
);
2164 gen_op_mov_reg_T0
[ot
][reg
]();
2167 case 0x91 ... 0x97: /* xchg R, EAX */
2168 ot
= dflag
? OT_LONG
: OT_WORD
;
2173 case 0x87: /* xchg Ev, Gv */
2177 ot
= dflag
? OT_LONG
: OT_WORD
;
2178 modrm
= ldub(s
->pc
++);
2179 reg
= (modrm
>> 3) & 7;
2180 mod
= (modrm
>> 6) & 3;
2184 gen_op_mov_TN_reg
[ot
][0][reg
]();
2185 gen_op_mov_TN_reg
[ot
][1][rm
]();
2186 gen_op_mov_reg_T0
[ot
][rm
]();
2187 gen_op_mov_reg_T1
[ot
][reg
]();
2189 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2190 gen_op_mov_TN_reg
[ot
][0][reg
]();
2191 /* for xchg, lock is implicit */
2192 if (!(prefixes
& PREFIX_LOCK
))
2194 gen_op_ld_T1_A0
[ot
]();
2195 gen_op_st_T0_A0
[ot
]();
2196 if (!(prefixes
& PREFIX_LOCK
))
2198 gen_op_mov_reg_T1
[ot
][reg
]();
2201 case 0xc4: /* les Gv */
2204 case 0xc5: /* lds Gv */
2207 case 0x1b2: /* lss Gv */
2210 case 0x1b4: /* lfs Gv */
2213 case 0x1b5: /* lgs Gv */
2216 ot
= dflag
? OT_LONG
: OT_WORD
;
2217 modrm
= ldub(s
->pc
++);
2218 reg
= (modrm
>> 3) & 7;
2219 mod
= (modrm
>> 6) & 3;
2222 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2223 gen_op_ld_T1_A0
[ot
]();
2224 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2225 /* load the segment first to handle exceptions properly */
2226 gen_op_lduw_T0_A0();
2227 gen_movl_seg_T0(s
, op
);
2228 /* then put the data */
2229 gen_op_mov_reg_T1
[ot
][reg
]();
2232 /************************/
2243 ot
= dflag
? OT_LONG
: OT_WORD
;
2245 modrm
= ldub(s
->pc
++);
2246 mod
= (modrm
>> 6) & 3;
2248 op
= (modrm
>> 3) & 7;
2251 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2252 gen_op_ld_T0_A0
[ot
]();
2255 opreg
= rm
+ OR_EAX
;
2260 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2263 shift
= ldub(s
->pc
++);
2265 gen_shifti(s
, op
, ot
, opreg
, shift
);
2269 gen_op_st_T0_A0
[ot
]();
2284 case 0x1a4: /* shld imm */
2288 case 0x1a5: /* shld cl */
2292 case 0x1ac: /* shrd imm */
2296 case 0x1ad: /* shrd cl */
2300 ot
= dflag
? OT_LONG
: OT_WORD
;
2301 modrm
= ldub(s
->pc
++);
2302 mod
= (modrm
>> 6) & 3;
2304 reg
= (modrm
>> 3) & 7;
2307 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2308 gen_op_ld_T0_A0
[ot
]();
2310 gen_op_mov_TN_reg
[ot
][0][rm
]();
2312 gen_op_mov_TN_reg
[ot
][1][reg
]();
2315 val
= ldub(s
->pc
++);
2318 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2319 if (op
== 0 && ot
!= OT_WORD
)
2320 s
->cc_op
= CC_OP_SHLB
+ ot
;
2322 s
->cc_op
= CC_OP_SARB
+ ot
;
2325 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2326 gen_op_set_cc_op(s
->cc_op
);
2327 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2328 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2331 gen_op_st_T0_A0
[ot
]();
2333 gen_op_mov_reg_T0
[ot
][rm
]();
2337 /************************/
2340 modrm
= ldub(s
->pc
++);
2341 mod
= (modrm
>> 6) & 3;
2343 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2347 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2349 case 0x00 ... 0x07: /* fxxxs */
2350 case 0x10 ... 0x17: /* fixxxl */
2351 case 0x20 ... 0x27: /* fxxxl */
2352 case 0x30 ... 0x37: /* fixxx */
2359 gen_op_flds_FT0_A0();
2362 gen_op_fildl_FT0_A0();
2365 gen_op_fldl_FT0_A0();
2369 gen_op_fild_FT0_A0();
2373 gen_op_fp_arith_ST0_FT0
[op1
]();
2375 /* fcomp needs pop */
2380 case 0x08: /* flds */
2381 case 0x0a: /* fsts */
2382 case 0x0b: /* fstps */
2383 case 0x18: /* fildl */
2384 case 0x1a: /* fistl */
2385 case 0x1b: /* fistpl */
2386 case 0x28: /* fldl */
2387 case 0x2a: /* fstl */
2388 case 0x2b: /* fstpl */
2389 case 0x38: /* filds */
2390 case 0x3a: /* fists */
2391 case 0x3b: /* fistps */
2398 gen_op_flds_ST0_A0();
2401 gen_op_fildl_ST0_A0();
2404 gen_op_fldl_ST0_A0();
2408 gen_op_fild_ST0_A0();
2415 gen_op_fsts_ST0_A0();
2418 gen_op_fistl_ST0_A0();
2421 gen_op_fstl_ST0_A0();
2425 gen_op_fist_ST0_A0();
2433 case 0x0d: /* fldcw mem */
2436 case 0x0f: /* fnstcw mem */
2439 case 0x1d: /* fldt mem */
2441 gen_op_fldt_ST0_A0();
2443 case 0x1f: /* fstpt mem */
2444 gen_op_fstt_ST0_A0();
2447 case 0x2f: /* fnstsw mem */
2450 case 0x3c: /* fbld */
2452 gen_op_fbld_ST0_A0();
2454 case 0x3e: /* fbstp */
2455 gen_op_fbst_ST0_A0();
2458 case 0x3d: /* fildll */
2460 gen_op_fildll_ST0_A0();
2462 case 0x3f: /* fistpll */
2463 gen_op_fistll_ST0_A0();
2470 /* register float ops */
2474 case 0x08: /* fld sti */
2476 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2478 case 0x09: /* fxchg sti */
2479 gen_op_fxchg_ST0_STN(opreg
);
2481 case 0x0a: /* grp d9/2 */
2489 case 0x0c: /* grp d9/4 */
2499 gen_op_fcom_ST0_FT0();
2508 case 0x0d: /* grp d9/5 */
2517 gen_op_fldl2t_ST0();
2521 gen_op_fldl2e_ST0();
2529 gen_op_fldlg2_ST0();
2533 gen_op_fldln2_ST0();
2544 case 0x0e: /* grp d9/6 */
2555 case 3: /* fpatan */
2558 case 4: /* fxtract */
2561 case 5: /* fprem1 */
2564 case 6: /* fdecstp */
2568 case 7: /* fincstp */
2573 case 0x0f: /* grp d9/7 */
2578 case 1: /* fyl2xp1 */
2584 case 3: /* fsincos */
2587 case 5: /* fscale */
2590 case 4: /* frndint */
2602 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2603 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2604 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2610 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2614 gen_op_fmov_FT0_STN(opreg
);
2615 gen_op_fp_arith_ST0_FT0
[op1
]();
2619 case 0x02: /* fcom */
2620 gen_op_fmov_FT0_STN(opreg
);
2621 gen_op_fcom_ST0_FT0();
2623 case 0x03: /* fcomp */
2624 gen_op_fmov_FT0_STN(opreg
);
2625 gen_op_fcom_ST0_FT0();
2628 case 0x15: /* da/5 */
2630 case 1: /* fucompp */
2631 gen_op_fmov_FT0_STN(1);
2632 gen_op_fucom_ST0_FT0();
2645 case 3: /* fninit */
2652 case 0x2a: /* fst sti */
2653 gen_op_fmov_STN_ST0(opreg
);
2655 case 0x2b: /* fstp sti */
2656 gen_op_fmov_STN_ST0(opreg
);
2659 case 0x2c: /* fucom st(i) */
2660 gen_op_fmov_FT0_STN(opreg
);
2661 gen_op_fucom_ST0_FT0();
2663 case 0x2d: /* fucomp st(i) */
2664 gen_op_fmov_FT0_STN(opreg
);
2665 gen_op_fucom_ST0_FT0();
2668 case 0x33: /* de/3 */
2670 case 1: /* fcompp */
2671 gen_op_fmov_FT0_STN(1);
2672 gen_op_fcom_ST0_FT0();
2680 case 0x3c: /* df/4 */
2683 gen_op_fnstsw_EAX();
2694 /************************/
2697 case 0xa4: /* movsS */
2702 ot
= dflag
? OT_LONG
: OT_WORD
;
2704 if (prefixes
& PREFIX_REPZ
) {
2705 gen_string_ds(s
, ot
, gen_op_movs
+ 9);
2707 gen_string_ds(s
, ot
, gen_op_movs
);
2711 case 0xaa: /* stosS */
2716 ot
= dflag
? OT_LONG
: OT_WORD
;
2718 if (prefixes
& PREFIX_REPZ
) {
2719 gen_string_es(s
, ot
, gen_op_stos
+ 9);
2721 gen_string_es(s
, ot
, gen_op_stos
);
2724 case 0xac: /* lodsS */
2729 ot
= dflag
? OT_LONG
: OT_WORD
;
2730 if (prefixes
& PREFIX_REPZ
) {
2731 gen_string_ds(s
, ot
, gen_op_lods
+ 9);
2733 gen_string_ds(s
, ot
, gen_op_lods
);
2736 case 0xae: /* scasS */
2741 ot
= dflag
? OT_LONG
: OT_WORD
;
2742 if (prefixes
& PREFIX_REPNZ
) {
2743 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2744 gen_op_set_cc_op(s
->cc_op
);
2745 gen_string_es(s
, ot
, gen_op_scas
+ 9 * 2);
2746 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2747 } else if (prefixes
& PREFIX_REPZ
) {
2748 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2749 gen_op_set_cc_op(s
->cc_op
);
2750 gen_string_es(s
, ot
, gen_op_scas
+ 9);
2751 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2753 gen_string_es(s
, ot
, gen_op_scas
);
2754 s
->cc_op
= CC_OP_SUBB
+ ot
;
2758 case 0xa6: /* cmpsS */
2763 ot
= dflag
? OT_LONG
: OT_WORD
;
2764 if (prefixes
& PREFIX_REPNZ
) {
2765 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2766 gen_op_set_cc_op(s
->cc_op
);
2767 gen_string_ds(s
, ot
, gen_op_cmps
+ 9 * 2);
2768 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2769 } else if (prefixes
& PREFIX_REPZ
) {
2770 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2771 gen_op_set_cc_op(s
->cc_op
);
2772 gen_string_ds(s
, ot
, gen_op_cmps
+ 9);
2773 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2775 gen_string_ds(s
, ot
, gen_op_cmps
);
2776 s
->cc_op
= CC_OP_SUBB
+ ot
;
2779 case 0x6c: /* insS */
2781 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2782 /* NOTE: even for (E)CX = 0 the exception is raised */
2783 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2788 ot
= dflag
? OT_LONG
: OT_WORD
;
2789 if (prefixes
& PREFIX_REPZ
) {
2790 gen_string_es(s
, ot
, gen_op_ins
+ 9);
2792 gen_string_es(s
, ot
, gen_op_ins
);
2796 case 0x6e: /* outsS */
2798 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2799 /* NOTE: even for (E)CX = 0 the exception is raised */
2800 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2805 ot
= dflag
? OT_LONG
: OT_WORD
;
2806 if (prefixes
& PREFIX_REPZ
) {
2807 gen_string_ds(s
, ot
, gen_op_outs
+ 9);
2809 gen_string_ds(s
, ot
, gen_op_outs
);
2814 /************************/
2818 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2819 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2824 ot
= dflag
? OT_LONG
: OT_WORD
;
2825 val
= ldub(s
->pc
++);
2826 gen_op_movl_T0_im(val
);
2828 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2833 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2834 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2839 ot
= dflag
? OT_LONG
: OT_WORD
;
2840 val
= ldub(s
->pc
++);
2841 gen_op_movl_T0_im(val
);
2842 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2848 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2849 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2854 ot
= dflag
? OT_LONG
: OT_WORD
;
2855 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2857 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2862 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2863 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2868 ot
= dflag
? OT_LONG
: OT_WORD
;
2869 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2870 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2875 /************************/
2877 case 0xc2: /* ret im */
2882 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2884 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2886 gen_op_andl_T0_ffff();
2890 case 0xc3: /* ret */
2894 gen_op_andl_T0_ffff();
2898 case 0xca: /* lret im */
2899 /* XXX: not restartable */
2905 gen_op_andl_T0_ffff();
2910 gen_movl_seg_T0(s
, R_CS
);
2912 /* add stack offset */
2914 gen_op_addl_ESP_im(val
);
2916 gen_op_addw_ESP_im(val
);
2919 case 0xcb: /* lret */
2920 /* XXX: not restartable */
2924 gen_op_andl_T0_ffff();
2929 gen_movl_seg_T0(s
, R_CS
);
2933 case 0xcf: /* iret */
2934 if (s
->vm86
&& s
->iopl
!= 3) {
2935 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2937 /* XXX: not restartable */
2941 gen_op_andl_T0_ffff();
2946 gen_movl_seg_T0(s
, R_CS
);
2951 gen_op_movl_eflags_T0();
2953 gen_op_movw_eflags_T0();
2956 s
->cc_op
= CC_OP_EFLAGS
;
2960 case 0xe8: /* call im */
2962 unsigned int next_eip
;
2963 ot
= dflag
? OT_LONG
: OT_WORD
;
2964 val
= insn_get(s
, ot
);
2965 next_eip
= s
->pc
- s
->cs_base
;
2969 gen_op_movl_T0_im(next_eip
);
2975 case 0x9a: /* lcall im */
2977 unsigned int selector
, offset
;
2979 ot
= dflag
? OT_LONG
: OT_WORD
;
2980 offset
= insn_get(s
, ot
);
2981 selector
= insn_get(s
, OT_WORD
);
2983 /* push return segment + offset */
2984 gen_op_movl_T0_seg(R_CS
);
2986 next_eip
= s
->pc
- s
->cs_base
;
2987 gen_op_movl_T0_im(next_eip
);
2990 /* change cs and pc */
2991 gen_op_movl_T0_im(selector
);
2992 gen_movl_seg_T0(s
, R_CS
);
2993 gen_op_jmp_im((unsigned long)offset
);
2997 case 0xe9: /* jmp */
2998 ot
= dflag
? OT_LONG
: OT_WORD
;
2999 val
= insn_get(s
, ot
);
3000 val
+= s
->pc
- s
->cs_base
;
3006 case 0xea: /* ljmp im */
3008 unsigned int selector
, offset
;
3010 ot
= dflag
? OT_LONG
: OT_WORD
;
3011 offset
= insn_get(s
, ot
);
3012 selector
= insn_get(s
, OT_WORD
);
3014 /* change cs and pc */
3015 gen_op_movl_T0_im(selector
);
3016 gen_movl_seg_T0(s
, R_CS
);
3017 gen_op_jmp_im((unsigned long)offset
);
3021 case 0xeb: /* jmp Jb */
3022 val
= (int8_t)insn_get(s
, OT_BYTE
);
3023 val
+= s
->pc
- s
->cs_base
;
3029 case 0x70 ... 0x7f: /* jcc Jb */
3030 val
= (int8_t)insn_get(s
, OT_BYTE
);
3032 case 0x180 ... 0x18f: /* jcc Jv */
3034 val
= insn_get(s
, OT_LONG
);
3036 val
= (int16_t)insn_get(s
, OT_WORD
);
3039 next_eip
= s
->pc
- s
->cs_base
;
3043 gen_jcc(s
, b
, val
, next_eip
);
3047 case 0x190 ... 0x19f: /* setcc Gv */
3048 modrm
= ldub(s
->pc
++);
3050 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
3052 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3053 ot
= dflag
? OT_LONG
: OT_WORD
;
3054 modrm
= ldub(s
->pc
++);
3055 reg
= (modrm
>> 3) & 7;
3056 mod
= (modrm
>> 6) & 3;
3059 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3060 gen_op_ld_T1_A0
[ot
]();
3063 gen_op_mov_TN_reg
[ot
][1][rm
]();
3065 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
3068 /************************/
3070 case 0x9c: /* pushf */
3071 if (s
->vm86
&& s
->iopl
!= 3) {
3072 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3074 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3075 gen_op_set_cc_op(s
->cc_op
);
3076 gen_op_movl_T0_eflags();
3080 case 0x9d: /* popf */
3081 if (s
->vm86
&& s
->iopl
!= 3) {
3082 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3086 gen_op_movl_eflags_T0();
3088 gen_op_movw_eflags_T0();
3091 s
->cc_op
= CC_OP_EFLAGS
;
3094 case 0x9e: /* sahf */
3095 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
3096 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3097 gen_op_set_cc_op(s
->cc_op
);
3098 gen_op_movb_eflags_T0();
3099 s
->cc_op
= CC_OP_EFLAGS
;
3101 case 0x9f: /* lahf */
3102 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3103 gen_op_set_cc_op(s
->cc_op
);
3104 gen_op_movl_T0_eflags();
3105 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
3107 case 0xf5: /* cmc */
3108 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3109 gen_op_set_cc_op(s
->cc_op
);
3111 s
->cc_op
= CC_OP_EFLAGS
;
3113 case 0xf8: /* clc */
3114 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3115 gen_op_set_cc_op(s
->cc_op
);
3117 s
->cc_op
= CC_OP_EFLAGS
;
3119 case 0xf9: /* stc */
3120 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3121 gen_op_set_cc_op(s
->cc_op
);
3123 s
->cc_op
= CC_OP_EFLAGS
;
3125 case 0xfc: /* cld */
3128 case 0xfd: /* std */
3132 /************************/
3133 /* bit operations */
3134 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3135 ot
= dflag
? OT_LONG
: OT_WORD
;
3136 modrm
= ldub(s
->pc
++);
3137 op
= (modrm
>> 3) & 7;
3138 mod
= (modrm
>> 6) & 3;
3141 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3142 gen_op_ld_T0_A0
[ot
]();
3144 gen_op_mov_TN_reg
[ot
][0][rm
]();
3147 val
= ldub(s
->pc
++);
3148 gen_op_movl_T1_im(val
);
3152 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3153 s
->cc_op
= CC_OP_SARB
+ ot
;
3156 gen_op_st_T0_A0
[ot
]();
3158 gen_op_mov_reg_T0
[ot
][rm
]();
3161 case 0x1a3: /* bt Gv, Ev */
3164 case 0x1ab: /* bts */
3167 case 0x1b3: /* btr */
3170 case 0x1bb: /* btc */
3173 ot
= dflag
? OT_LONG
: OT_WORD
;
3174 modrm
= ldub(s
->pc
++);
3175 reg
= (modrm
>> 3) & 7;
3176 mod
= (modrm
>> 6) & 3;
3178 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3180 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3181 /* specific case: we need to add a displacement */
3183 gen_op_add_bitw_A0_T1();
3185 gen_op_add_bitl_A0_T1();
3186 gen_op_ld_T0_A0
[ot
]();
3188 gen_op_mov_TN_reg
[ot
][0][rm
]();
3190 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3191 s
->cc_op
= CC_OP_SARB
+ ot
;
3194 gen_op_st_T0_A0
[ot
]();
3196 gen_op_mov_reg_T0
[ot
][rm
]();
3199 case 0x1bc: /* bsf */
3200 case 0x1bd: /* bsr */
3201 ot
= dflag
? OT_LONG
: OT_WORD
;
3202 modrm
= ldub(s
->pc
++);
3203 reg
= (modrm
>> 3) & 7;
3204 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3205 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3206 /* NOTE: we always write back the result. Intel doc says it is
3207 undefined if T0 == 0 */
3208 gen_op_mov_reg_T0
[ot
][reg
]();
3209 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3211 /************************/
3213 case 0x27: /* daa */
3214 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3215 gen_op_set_cc_op(s
->cc_op
);
3217 s
->cc_op
= CC_OP_EFLAGS
;
3219 case 0x2f: /* das */
3220 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3221 gen_op_set_cc_op(s
->cc_op
);
3223 s
->cc_op
= CC_OP_EFLAGS
;
3225 case 0x37: /* aaa */
3226 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3227 gen_op_set_cc_op(s
->cc_op
);
3229 s
->cc_op
= CC_OP_EFLAGS
;
3231 case 0x3f: /* aas */
3232 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3233 gen_op_set_cc_op(s
->cc_op
);
3235 s
->cc_op
= CC_OP_EFLAGS
;
3237 case 0xd4: /* aam */
3238 val
= ldub(s
->pc
++);
3240 s
->cc_op
= CC_OP_LOGICB
;
3242 case 0xd5: /* aad */
3243 val
= ldub(s
->pc
++);
3245 s
->cc_op
= CC_OP_LOGICB
;
3247 /************************/
3249 case 0x90: /* nop */
3251 case 0xcc: /* int3 */
3252 gen_exception(s
, EXCP03_INT3
, s
->pc
- s
->cs_base
);
3254 case 0xcd: /* int N */
3255 val
= ldub(s
->pc
++);
3256 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3257 gen_op_set_cc_op(s
->cc_op
);
3258 gen_op_int_im(val
, pc_start
- s
->cs_base
);
3261 case 0xce: /* into */
3262 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3263 gen_op_set_cc_op(s
->cc_op
);
3264 gen_op_into(s
->pc
- s
->cs_base
);
3266 case 0xfa: /* cli */
3268 if (s
->cpl
<= s
->iopl
) {
3271 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3277 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3281 case 0xfb: /* sti */
3283 if (s
->cpl
<= s
->iopl
) {
3286 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3292 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3296 case 0x62: /* bound */
3297 ot
= dflag
? OT_LONG
: OT_WORD
;
3298 modrm
= ldub(s
->pc
++);
3299 reg
= (modrm
>> 3) & 7;
3300 mod
= (modrm
>> 6) & 3;
3303 gen_op_mov_reg_T0
[ot
][reg
]();
3304 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3310 case 0x1c8 ... 0x1cf: /* bswap reg */
3312 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3314 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3316 case 0xd6: /* salc */
3317 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3318 gen_op_set_cc_op(s
->cc_op
);
3321 case 0xe0: /* loopnz */
3322 case 0xe1: /* loopz */
3323 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3324 gen_op_set_cc_op(s
->cc_op
);
3326 case 0xe2: /* loop */
3327 case 0xe3: /* jecxz */
3328 val
= (int8_t)insn_get(s
, OT_BYTE
);
3329 next_eip
= s
->pc
- s
->cs_base
;
3333 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3336 case 0x131: /* rdtsc */
3339 case 0x1a2: /* cpuid */
3342 case 0xf4: /* hlt */
3343 /* XXX: if cpl == 0, then should do something else */
3344 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3346 case 0x102: /* lar */
3347 case 0x103: /* lsl */
3350 ot
= dflag
? OT_LONG
: OT_WORD
;
3351 modrm
= ldub(s
->pc
++);
3352 reg
= (modrm
>> 3) & 7;
3353 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3354 gen_op_mov_TN_reg
[ot
][1][reg
]();
3355 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3356 gen_op_set_cc_op(s
->cc_op
);
3361 s
->cc_op
= CC_OP_EFLAGS
;
3362 gen_op_mov_reg_T1
[ot
][reg
]();
3367 /* lock generation */
3368 if (s
->prefix
& PREFIX_LOCK
)
3372 /* XXX: ensure that no lock was generated */
3376 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3377 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3379 /* flags read by an operation */
3380 static uint16_t opc_read_flags
[NB_OPS
] = {
3381 [INDEX_op_aas
] = CC_A
,
3382 [INDEX_op_aaa
] = CC_A
,
3383 [INDEX_op_das
] = CC_A
| CC_C
,
3384 [INDEX_op_daa
] = CC_A
| CC_C
,
3386 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3387 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3388 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3389 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3390 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3391 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3393 /* subtle: due to the incl/decl implementation, C is used */
3394 [INDEX_op_incl_T0_cc
] = CC_C
,
3395 [INDEX_op_decl_T0_cc
] = CC_C
,
3397 [INDEX_op_into
] = CC_O
,
3399 [INDEX_op_jo_cc
] = CC_O
,
3400 [INDEX_op_jb_cc
] = CC_C
,
3401 [INDEX_op_jz_cc
] = CC_Z
,
3402 [INDEX_op_jbe_cc
] = CC_Z
| CC_C
,
3403 [INDEX_op_js_cc
] = CC_S
,
3404 [INDEX_op_jp_cc
] = CC_P
,
3405 [INDEX_op_jl_cc
] = CC_O
| CC_S
,
3406 [INDEX_op_jle_cc
] = CC_O
| CC_S
| CC_Z
,
3408 [INDEX_op_jb_subb
] = CC_C
,
3409 [INDEX_op_jb_subw
] = CC_C
,
3410 [INDEX_op_jb_subl
] = CC_C
,
3412 [INDEX_op_jz_subb
] = CC_Z
,
3413 [INDEX_op_jz_subw
] = CC_Z
,
3414 [INDEX_op_jz_subl
] = CC_Z
,
3416 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3417 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3418 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3420 [INDEX_op_js_subb
] = CC_S
,
3421 [INDEX_op_js_subw
] = CC_S
,
3422 [INDEX_op_js_subl
] = CC_S
,
3424 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3425 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3426 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3428 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3429 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3430 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3432 [INDEX_op_loopnzw
] = CC_Z
,
3433 [INDEX_op_loopnzl
] = CC_Z
,
3434 [INDEX_op_loopzw
] = CC_Z
,
3435 [INDEX_op_loopzl
] = CC_Z
,
3437 [INDEX_op_seto_T0_cc
] = CC_O
,
3438 [INDEX_op_setb_T0_cc
] = CC_C
,
3439 [INDEX_op_setz_T0_cc
] = CC_Z
,
3440 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3441 [INDEX_op_sets_T0_cc
] = CC_S
,
3442 [INDEX_op_setp_T0_cc
] = CC_P
,
3443 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3444 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3446 [INDEX_op_setb_T0_subb
] = CC_C
,
3447 [INDEX_op_setb_T0_subw
] = CC_C
,
3448 [INDEX_op_setb_T0_subl
] = CC_C
,
3450 [INDEX_op_setz_T0_subb
] = CC_Z
,
3451 [INDEX_op_setz_T0_subw
] = CC_Z
,
3452 [INDEX_op_setz_T0_subl
] = CC_Z
,
3454 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3455 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3456 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3458 [INDEX_op_sets_T0_subb
] = CC_S
,
3459 [INDEX_op_sets_T0_subw
] = CC_S
,
3460 [INDEX_op_sets_T0_subl
] = CC_S
,
3462 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3463 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3464 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3466 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3467 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3468 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3470 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3471 [INDEX_op_cmc
] = CC_C
,
3472 [INDEX_op_salc
] = CC_C
,
3474 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3475 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3476 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3477 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3478 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3479 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3482 /* flags written by an operation */
3483 static uint16_t opc_write_flags
[NB_OPS
] = {
3484 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3485 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3486 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3487 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3488 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3489 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3490 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3491 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3492 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3493 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3494 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3495 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3496 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3497 /* subtle: due to the incl/decl implementation, C is used */
3498 [INDEX_op_incl_T0_cc
] = CC_OSZAPC
,
3499 [INDEX_op_decl_T0_cc
] = CC_OSZAPC
,
3500 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3502 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3503 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3504 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3505 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3506 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3507 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3508 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3509 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3512 [INDEX_op_aam
] = CC_OSZAPC
,
3513 [INDEX_op_aad
] = CC_OSZAPC
,
3514 [INDEX_op_aas
] = CC_OSZAPC
,
3515 [INDEX_op_aaa
] = CC_OSZAPC
,
3516 [INDEX_op_das
] = CC_OSZAPC
,
3517 [INDEX_op_daa
] = CC_OSZAPC
,
3519 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3520 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
3521 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3522 [INDEX_op_clc
] = CC_C
,
3523 [INDEX_op_stc
] = CC_C
,
3524 [INDEX_op_cmc
] = CC_C
,
3526 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3527 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3528 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3529 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3530 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3531 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3533 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3534 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3535 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3536 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3537 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3538 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3540 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3541 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3542 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3544 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3545 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3546 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3548 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3549 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3550 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3552 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3553 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3554 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3555 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3557 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3558 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3559 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3560 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3562 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3563 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3564 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3565 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3566 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3567 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3568 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3569 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3571 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3572 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3573 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3574 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3577 #define STRINGOP(x) \
3578 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3579 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3580 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3581 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3582 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3583 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3584 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3585 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3586 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3590 STRINGOP(repnz_scas
)
3593 STRINGOP(repnz_cmps
)
3595 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
3596 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3597 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3599 [INDEX_op_cmpxchg8b
] = CC_Z
,
3600 [INDEX_op_lar
] = CC_Z
,
3601 [INDEX_op_lsl
] = CC_Z
,
3604 /* simpler form of an operation if no flags need to be generated */
3605 static uint16_t opc_simpler
[NB_OPS
] = {
3606 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3607 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3608 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3609 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3610 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3611 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3612 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3613 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3615 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3616 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3617 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3619 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3620 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3621 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3623 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3624 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3625 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3627 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3628 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3629 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3631 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3632 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3633 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3636 static void optimize_flags_init(void)
3639 /* put default values in arrays */
3640 for(i
= 0; i
< NB_OPS
; i
++) {
3641 if (opc_simpler
[i
] == 0)
3646 /* CPU flags computation optimization: we move backward thru the
3647 generated code to see which flags are needed. The operation is
3648 modified if suitable */
3649 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3652 int live_flags
, write_flags
, op
;
3654 opc_ptr
= opc_buf
+ opc_buf_len
;
3655 /* live_flags contains the flags needed by the next instructions
3656 in the code. At the end of the bloc, we consider that all the
3658 live_flags
= CC_OSZAPC
;
3659 while (opc_ptr
> opc_buf
) {
3661 /* if none of the flags written by the instruction is used,
3662 then we can try to find a simpler instruction */
3663 write_flags
= opc_write_flags
[op
];
3664 if ((live_flags
& write_flags
) == 0) {
3665 *opc_ptr
= opc_simpler
[op
];
3667 /* compute the live flags before the instruction */
3668 live_flags
&= ~write_flags
;
3669 live_flags
|= opc_read_flags
[op
];
3675 static const char *op_str
[] = {
3676 #define DEF(s, n) #s,
3677 #include "opc-i386.h"
3681 static uint8_t op_nb_args
[] = {
3682 #define DEF(s, n) n,
3683 #include "opc-i386.h"
3687 static void dump_ops(const uint16_t *opc_buf
, const uint32_t *opparam_buf
)
3689 const uint16_t *opc_ptr
;
3690 const uint32_t *opparam_ptr
;
3694 opparam_ptr
= opparam_buf
;
3698 fprintf(logfile
, "0x%04x: %s",
3699 (int)(opc_ptr
- opc_buf
- 1), op_str
[c
]);
3700 for(i
= 0; i
< n
; i
++) {
3701 fprintf(logfile
, " 0x%x", opparam_ptr
[i
]);
3703 fprintf(logfile
, "\n");
3704 if (c
== INDEX_op_end
)
3712 /* XXX: make this buffer thread safe */
3713 /* XXX: make safe guess about sizes */
3714 #define MAX_OP_PER_INSTR 32
3715 #define OPC_BUF_SIZE 512
3716 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3718 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3720 static uint16_t gen_opc_buf
[OPC_BUF_SIZE
];
3721 static uint32_t gen_opparam_buf
[OPPARAM_BUF_SIZE
];
3723 /* return non zero if the very first instruction is invalid so that
3724 the virtual CPU can trigger an exception. */
3725 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
3726 int *gen_code_size_ptr
,
3727 uint8_t *pc_start
, uint8_t *cs_base
, int flags
)
3729 DisasContext dc1
, *dc
= &dc1
;
3731 uint16_t *gen_opc_end
;
3735 /* generate intermediate code */
3737 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3738 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3739 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3740 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3741 dc
->vm86
= (flags
>> GEN_FLAG_VM_SHIFT
) & 1;
3742 dc
->cpl
= (flags
>> GEN_FLAG_CPL_SHIFT
) & 3;
3743 dc
->iopl
= (flags
>> GEN_FLAG_IOPL_SHIFT
) & 3;
3744 dc
->tf
= (flags
>> GEN_FLAG_TF_SHIFT
) & 1;
3745 dc
->cc_op
= CC_OP_DYNAMIC
;
3746 dc
->cs_base
= cs_base
;
3748 gen_opc_ptr
= gen_opc_buf
;
3749 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3750 gen_opparam_ptr
= gen_opparam_buf
;
3755 ret
= disas_insn(dc
, pc_ptr
);
3757 /* we trigger an illegal instruction operation only if it
3758 is the first instruction. Otherwise, we simply stop
3759 generating the code just before it */
3760 if (pc_ptr
== pc_start
)
3765 pc_ptr
= (void *)ret
;
3766 /* if single step mode, we generate only one instruction and
3767 generate an exception */
3770 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
);
3771 /* we must store the eflags state if it is not already done */
3772 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3773 gen_op_set_cc_op(dc
->cc_op
);
3774 if (dc
->is_jmp
!= 1) {
3775 /* we add an additionnal jmp to update the simulated PC */
3776 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3779 gen_op_raise_exception(EXCP01_SSTP
);
3782 *gen_opc_ptr
= INDEX_op_end
;
3786 fprintf(logfile
, "----------------\n");
3787 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
3788 disas(logfile
, pc_start
, pc_ptr
- pc_start
,
3789 dc
->code32
? DISAS_I386_I386
: DISAS_I386_I8086
);
3790 fprintf(logfile
, "\n");
3792 fprintf(logfile
, "OP:\n");
3793 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3794 fprintf(logfile
, "\n");
3798 /* optimize flag computations */
3799 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3803 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3804 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3805 fprintf(logfile
, "\n");
3809 /* generate machine code */
3810 gen_code_size
= dyngen_code(gen_code_buf
, gen_opc_buf
, gen_opparam_buf
);
3811 flush_icache_range((unsigned long)gen_code_buf
, (unsigned long)(gen_code_buf
+ gen_code_size
));
3812 *gen_code_size_ptr
= gen_code_size
;
3816 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
3817 disas(logfile
, gen_code_buf
, *gen_code_size_ptr
, DISAS_TARGET
);
3818 fprintf(logfile
, "\n");
3825 CPUX86State
*cpu_x86_init(void)
3831 cpu_x86_tblocks_init();
3833 env
= malloc(sizeof(CPUX86State
));
3836 memset(env
, 0, sizeof(CPUX86State
));
3837 /* basic FPU init */
3838 for(i
= 0;i
< 8; i
++)
3841 /* flags setup : we activate the IRQs by default as in user mode */
3842 env
->eflags
= 0x2 | IF_MASK
;
3844 /* init various static tables */
3847 optimize_flags_init();
3853 void cpu_x86_close(CPUX86State
*env
)
3858 static const char *cc_op_str
[] = {
3891 void cpu_x86_dump_state(CPUX86State
*env
, FILE *f
, int flags
)
3894 char cc_op_name
[32];
3896 eflags
= env
->eflags
;
3897 fprintf(f
, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3898 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3899 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3900 env
->regs
[R_EAX
], env
->regs
[R_EBX
], env
->regs
[R_ECX
], env
->regs
[R_EDX
],
3901 env
->regs
[R_ESI
], env
->regs
[R_EDI
], env
->regs
[R_EBP
], env
->regs
[R_ESP
],
3903 eflags
& DF_MASK
? 'D' : '-',
3904 eflags
& CC_O
? 'O' : '-',
3905 eflags
& CC_S
? 'S' : '-',
3906 eflags
& CC_Z
? 'Z' : '-',
3907 eflags
& CC_A
? 'A' : '-',
3908 eflags
& CC_P
? 'P' : '-',
3909 eflags
& CC_C
? 'C' : '-');
3910 fprintf(f
, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3917 if (flags
& X86_DUMP_CCOP
) {
3918 if ((unsigned)env
->cc_op
< CC_OP_NB
)
3919 strcpy(cc_op_name
, cc_op_str
[env
->cc_op
]);
3921 snprintf(cc_op_name
, sizeof(cc_op_name
), "[%d]", env
->cc_op
);
3922 fprintf(f
, "CCS=%08x CCD=%08x CCO=%-8s\n",
3923 env
->cc_src
, env
->cc_dst
, cc_op_name
);
3925 if (flags
& X86_DUMP_FPU
) {
3926 fprintf(f
, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
3927 (double)env
->fpregs
[0],
3928 (double)env
->fpregs
[1],
3929 (double)env
->fpregs
[2],
3930 (double)env
->fpregs
[3]);
3931 fprintf(f
, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
3932 (double)env
->fpregs
[4],
3933 (double)env
->fpregs
[5],
3934 (double)env
->fpregs
[7],
3935 (double)env
->fpregs
[8]);