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
39 #define offsetof(type, field) ((size_t) &((type *)0)->field)
42 /* XXX: move that elsewhere */
43 static uint16_t *gen_opc_ptr
;
44 static uint32_t *gen_opparam_ptr
;
45 int __op_param1
, __op_param2
, __op_param3
;
48 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
54 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
61 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
63 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
67 p
= start
& ~(MIN_CACHE_LINE_SIZE
- 1);
68 stop
= (stop
+ MIN_CACHE_LINE_SIZE
- 1) & ~(MIN_CACHE_LINE_SIZE
- 1);
70 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
71 asm ("dcbst 0,%0;" : : "r"(p
) : "memory");
74 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
75 asm ("icbi 0,%0; sync;" : : "r"(p
) : "memory");
85 #define PREFIX_REPZ 0x01
86 #define PREFIX_REPNZ 0x02
87 #define PREFIX_LOCK 0x04
88 #define PREFIX_DATA 0x08
89 #define PREFIX_ADR 0x10
90 #define PREFIX_FWAIT 0x20
92 typedef struct DisasContext
{
93 /* current insn context */
94 int override
; /* -1 if no override */
97 uint8_t *pc
; /* pc = eip + cs_base */
98 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
99 static state change (stop translation) */
100 /* current block context */
101 uint8_t *cs_base
; /* base of CS segment */
102 int code32
; /* 32 bit code segment */
103 int ss32
; /* 32 bit stack segment */
104 int cc_op
; /* current CC operation */
105 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
106 int f_st
; /* currently unused */
107 int vm86
; /* vm86 mode */
110 /* i386 arith/logic operations */
130 OP_SHL1
, /* undocumented */
135 #define DEF(s, n) INDEX_op_ ## s,
136 #include "opc-i386.h"
152 /* I386 int registers */
153 OR_EAX
, /* MUST be even numbered */
161 OR_TMP0
, /* temporary operand register */
163 OR_A0
, /* temporary register used when doing address evaluation */
164 OR_ZERO
, /* fixed zero register */
168 typedef void (GenOpFunc
)(void);
169 typedef void (GenOpFunc1
)(long);
170 typedef void (GenOpFunc2
)(long, long);
172 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
205 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
238 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
261 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
331 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
342 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
354 gen_op_addl_A0_EAX_s1
,
355 gen_op_addl_A0_ECX_s1
,
356 gen_op_addl_A0_EDX_s1
,
357 gen_op_addl_A0_EBX_s1
,
358 gen_op_addl_A0_ESP_s1
,
359 gen_op_addl_A0_EBP_s1
,
360 gen_op_addl_A0_ESI_s1
,
361 gen_op_addl_A0_EDI_s1
,
364 gen_op_addl_A0_EAX_s2
,
365 gen_op_addl_A0_ECX_s2
,
366 gen_op_addl_A0_EDX_s2
,
367 gen_op_addl_A0_EBX_s2
,
368 gen_op_addl_A0_ESP_s2
,
369 gen_op_addl_A0_EBP_s2
,
370 gen_op_addl_A0_ESI_s2
,
371 gen_op_addl_A0_EDI_s2
,
374 gen_op_addl_A0_EAX_s3
,
375 gen_op_addl_A0_ECX_s3
,
376 gen_op_addl_A0_EDX_s3
,
377 gen_op_addl_A0_EBX_s3
,
378 gen_op_addl_A0_ESP_s3
,
379 gen_op_addl_A0_EBP_s3
,
380 gen_op_addl_A0_ESI_s3
,
381 gen_op_addl_A0_EDI_s3
,
385 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
387 gen_op_cmovw_EAX_T1_T0
,
388 gen_op_cmovw_ECX_T1_T0
,
389 gen_op_cmovw_EDX_T1_T0
,
390 gen_op_cmovw_EBX_T1_T0
,
391 gen_op_cmovw_ESP_T1_T0
,
392 gen_op_cmovw_EBP_T1_T0
,
393 gen_op_cmovw_ESI_T1_T0
,
394 gen_op_cmovw_EDI_T1_T0
,
397 gen_op_cmovl_EAX_T1_T0
,
398 gen_op_cmovl_ECX_T1_T0
,
399 gen_op_cmovl_EDX_T1_T0
,
400 gen_op_cmovl_EBX_T1_T0
,
401 gen_op_cmovl_ESP_T1_T0
,
402 gen_op_cmovl_EBP_T1_T0
,
403 gen_op_cmovl_ESI_T1_T0
,
404 gen_op_cmovl_EDI_T1_T0
,
408 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
409 gen_op_addl_T0_T1_cc
,
413 gen_op_andl_T0_T1_cc
,
414 gen_op_subl_T0_T1_cc
,
415 gen_op_xorl_T0_T1_cc
,
416 gen_op_cmpl_T0_T1_cc
,
419 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
421 gen_op_adcb_T0_T1_cc
,
422 gen_op_sbbb_T0_T1_cc
,
425 gen_op_adcw_T0_T1_cc
,
426 gen_op_sbbw_T0_T1_cc
,
429 gen_op_adcl_T0_T1_cc
,
430 gen_op_sbbl_T0_T1_cc
,
434 static const int cc_op_arithb
[8] = {
445 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
446 gen_op_cmpxchgb_T0_T1_EAX_cc
,
447 gen_op_cmpxchgw_T0_T1_EAX_cc
,
448 gen_op_cmpxchgl_T0_T1_EAX_cc
,
451 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
453 gen_op_rolb_T0_T1_cc
,
454 gen_op_rorb_T0_T1_cc
,
455 gen_op_rclb_T0_T1_cc
,
456 gen_op_rcrb_T0_T1_cc
,
457 gen_op_shlb_T0_T1_cc
,
458 gen_op_shrb_T0_T1_cc
,
459 gen_op_shlb_T0_T1_cc
,
460 gen_op_sarb_T0_T1_cc
,
463 gen_op_rolw_T0_T1_cc
,
464 gen_op_rorw_T0_T1_cc
,
465 gen_op_rclw_T0_T1_cc
,
466 gen_op_rcrw_T0_T1_cc
,
467 gen_op_shlw_T0_T1_cc
,
468 gen_op_shrw_T0_T1_cc
,
469 gen_op_shlw_T0_T1_cc
,
470 gen_op_sarw_T0_T1_cc
,
473 gen_op_roll_T0_T1_cc
,
474 gen_op_rorl_T0_T1_cc
,
475 gen_op_rcll_T0_T1_cc
,
476 gen_op_rcrl_T0_T1_cc
,
477 gen_op_shll_T0_T1_cc
,
478 gen_op_shrl_T0_T1_cc
,
479 gen_op_shll_T0_T1_cc
,
480 gen_op_sarl_T0_T1_cc
,
484 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
486 gen_op_shldw_T0_T1_im_cc
,
487 gen_op_shrdw_T0_T1_im_cc
,
490 gen_op_shldl_T0_T1_im_cc
,
491 gen_op_shrdl_T0_T1_im_cc
,
495 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
497 gen_op_shldw_T0_T1_ECX_cc
,
498 gen_op_shrdw_T0_T1_ECX_cc
,
501 gen_op_shldl_T0_T1_ECX_cc
,
502 gen_op_shrdl_T0_T1_ECX_cc
,
506 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
509 gen_op_btsw_T0_T1_cc
,
510 gen_op_btrw_T0_T1_cc
,
511 gen_op_btcw_T0_T1_cc
,
515 gen_op_btsl_T0_T1_cc
,
516 gen_op_btrl_T0_T1_cc
,
517 gen_op_btcl_T0_T1_cc
,
521 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
532 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
537 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
542 /* sign does not matter */
543 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
549 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
555 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
561 /* the _a32 and _a16 string operations use A0 as the base register. */
563 #define STRINGOP(x) \
564 gen_op_ ## x ## b_fast, \
565 gen_op_ ## x ## w_fast, \
566 gen_op_ ## x ## l_fast, \
567 gen_op_ ## x ## b_a32, \
568 gen_op_ ## x ## w_a32, \
569 gen_op_ ## x ## l_a32, \
570 gen_op_ ## x ## b_a16, \
571 gen_op_ ## x ## w_a16, \
572 gen_op_ ## x ## l_a16,
574 static GenOpFunc
*gen_op_movs
[9 * 2] = {
579 static GenOpFunc
*gen_op_stos
[9 * 2] = {
584 static GenOpFunc
*gen_op_lods
[9 * 2] = {
589 static GenOpFunc
*gen_op_scas
[9 * 3] = {
595 static GenOpFunc
*gen_op_cmps
[9 * 3] = {
601 static GenOpFunc
*gen_op_ins
[9 * 2] = {
607 static GenOpFunc
*gen_op_outs
[9 * 2] = {
613 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
617 override
= s
->override
;
620 if (s
->addseg
&& override
< 0)
623 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
631 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
632 /* 16 address, always override */
638 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
655 static GenOpFunc
*gen_op_in
[3] = {
661 static GenOpFunc
*gen_op_out
[3] = {
678 static GenOpFunc2
*gen_jcc_slow
[8] = {
689 static GenOpFunc2
*gen_jcc_sub
[3][8] = {
721 static GenOpFunc2
*gen_op_loop
[2][4] = {
736 static GenOpFunc
*gen_setcc_slow
[8] = {
747 static GenOpFunc
*gen_setcc_sub
[3][8] = {
752 gen_op_setbe_T0_subb
,
756 gen_op_setle_T0_subb
,
762 gen_op_setbe_T0_subw
,
766 gen_op_setle_T0_subw
,
772 gen_op_setbe_T0_subl
,
776 gen_op_setle_T0_subl
,
780 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
786 gen_op_fsubr_ST0_FT0
,
788 gen_op_fdivr_ST0_FT0
,
791 /* NOTE the exception in "r" op ordering */
792 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
797 gen_op_fsubr_STN_ST0
,
799 gen_op_fdivr_STN_ST0
,
803 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
806 gen_op_mov_TN_reg
[ot
][0][d
]();
808 gen_op_mov_TN_reg
[ot
][1][s
]();
809 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
810 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
811 gen_op_set_cc_op(s1
->cc_op
);
812 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
813 s1
->cc_op
= CC_OP_DYNAMIC
;
815 gen_op_arith_T0_T1_cc
[op
]();
816 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
818 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
819 gen_op_mov_reg_T0
[ot
][d
]();
822 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
824 gen_op_movl_T1_im(c
);
825 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
828 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
831 gen_op_mov_TN_reg
[ot
][0][d
]();
832 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
833 gen_op_set_cc_op(s1
->cc_op
);
836 s1
->cc_op
= CC_OP_INCB
+ ot
;
839 s1
->cc_op
= CC_OP_DECB
+ ot
;
842 gen_op_mov_reg_T0
[ot
][d
]();
845 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
848 gen_op_mov_TN_reg
[ot
][0][d
]();
850 gen_op_mov_TN_reg
[ot
][1][s
]();
851 /* for zero counts, flags are not updated, so must do it dynamically */
852 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
853 gen_op_set_cc_op(s1
->cc_op
);
855 gen_op_shift_T0_T1_cc
[ot
][op
]();
858 gen_op_mov_reg_T0
[ot
][d
]();
859 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
862 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
864 /* currently not optimized */
865 gen_op_movl_T1_im(c
);
866 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
869 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
876 int mod
, rm
, code
, override
, must_add_seg
;
878 override
= s
->override
;
879 must_add_seg
= s
->addseg
;
882 mod
= (modrm
>> 6) & 3;
894 code
= ldub(s
->pc
++);
895 scale
= (code
>> 6) & 3;
896 index
= (code
>> 3) & 7;
911 disp
= (int8_t)ldub(s
->pc
++);
921 gen_op_movl_A0_reg
[base
]();
923 gen_op_addl_A0_im(disp
);
925 gen_op_movl_A0_im(disp
);
927 if (havesib
&& (index
!= 4 || scale
!= 0)) {
928 gen_op_addl_A0_reg_sN
[scale
][index
]();
932 if (base
== R_EBP
|| base
== R_ESP
)
937 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
945 gen_op_movl_A0_im(disp
);
946 rm
= 0; /* avoid SS override */
953 disp
= (int8_t)ldub(s
->pc
++);
963 gen_op_movl_A0_reg
[R_EBX
]();
964 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
967 gen_op_movl_A0_reg
[R_EBX
]();
968 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
971 gen_op_movl_A0_reg
[R_EBP
]();
972 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
975 gen_op_movl_A0_reg
[R_EBP
]();
976 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
979 gen_op_movl_A0_reg
[R_ESI
]();
982 gen_op_movl_A0_reg
[R_EDI
]();
985 gen_op_movl_A0_reg
[R_EBP
]();
989 gen_op_movl_A0_reg
[R_EBX
]();
993 gen_op_addl_A0_im(disp
);
994 gen_op_andl_A0_ffff();
998 if (rm
== 2 || rm
== 3 || rm
== 6)
1003 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
1013 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1015 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1017 int mod
, rm
, opreg
, disp
;
1019 mod
= (modrm
>> 6) & 3;
1024 gen_op_mov_TN_reg
[ot
][0][reg
]();
1025 gen_op_mov_reg_T0
[ot
][rm
]();
1027 gen_op_mov_TN_reg
[ot
][0][rm
]();
1029 gen_op_mov_reg_T0
[ot
][reg
]();
1032 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1035 gen_op_mov_TN_reg
[ot
][0][reg
]();
1036 gen_op_st_T0_A0
[ot
]();
1038 gen_op_ld_T0_A0
[ot
]();
1040 gen_op_mov_reg_T0
[ot
][reg
]();
1045 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1067 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1073 jcc_op
= (b
>> 1) & 7;
1075 /* we optimize the cmp/jcc case */
1079 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1084 /* some jumps are easy to compute */
1111 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1114 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1122 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1123 gen_op_set_cc_op(s
->cc_op
);
1124 func
= gen_jcc_slow
[jcc_op
];
1128 func(val
, next_eip
);
1130 func(next_eip
, val
);
1134 static void gen_setcc(DisasContext
*s
, int b
)
1140 jcc_op
= (b
>> 1) & 7;
1142 /* we optimize the cmp/jcc case */
1146 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1151 /* some jumps are easy to compute */
1169 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1172 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1180 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1181 gen_op_set_cc_op(s
->cc_op
);
1182 func
= gen_setcc_slow
[jcc_op
];
1191 /* move T0 to seg_reg and compute if the CPU state may change */
1192 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
)
1194 gen_op_movl_seg_T0(seg_reg
);
1195 if (!s
->addseg
&& seg_reg
< R_FS
)
1196 s
->is_jmp
= 2; /* abort translation because the register may
1197 have a non zero base */
1200 /* generate a push. It depends on ss32, addseg and dflag */
1201 static void gen_push_T0(DisasContext
*s
)
1211 gen_op_pushl_ss32_T0();
1213 gen_op_pushw_ss32_T0();
1217 gen_op_pushl_ss16_T0();
1219 gen_op_pushw_ss16_T0();
1223 /* two step pop is necessary for precise exceptions */
1224 static void gen_pop_T0(DisasContext
*s
)
1234 gen_op_popl_ss32_T0();
1236 gen_op_popw_ss32_T0();
1240 gen_op_popl_ss16_T0();
1242 gen_op_popw_ss16_T0();
1246 static void gen_pop_update(DisasContext
*s
)
1250 gen_op_addl_ESP_4();
1252 gen_op_addl_ESP_2();
1255 gen_op_addw_ESP_4();
1257 gen_op_addw_ESP_2();
1261 /* NOTE: wrap around in 16 bit not fully handled */
1262 static void gen_pusha(DisasContext
*s
)
1265 gen_op_movl_A0_ESP();
1266 gen_op_addl_A0_im(-16 << s
->dflag
);
1268 gen_op_andl_A0_ffff();
1269 gen_op_movl_T1_A0();
1271 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1272 for(i
= 0;i
< 8; i
++) {
1273 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1274 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1275 gen_op_addl_A0_im(2 << s
->dflag
);
1277 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1280 /* NOTE: wrap around in 16 bit not fully handled */
1281 static void gen_popa(DisasContext
*s
)
1284 gen_op_movl_A0_ESP();
1286 gen_op_andl_A0_ffff();
1287 gen_op_movl_T1_A0();
1288 gen_op_addl_T1_im(16 << s
->dflag
);
1290 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1291 for(i
= 0;i
< 8; i
++) {
1292 /* ESP is not reloaded */
1294 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1295 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1297 gen_op_addl_A0_im(2 << s
->dflag
);
1299 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1302 /* NOTE: wrap around in 16 bit not fully handled */
1303 /* XXX: check this */
1304 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1306 int ot
, level1
, addend
, opsize
;
1308 ot
= s
->dflag
+ OT_WORD
;
1311 opsize
= 2 << s
->dflag
;
1313 gen_op_movl_A0_ESP();
1314 gen_op_addl_A0_im(-opsize
);
1316 gen_op_andl_A0_ffff();
1317 gen_op_movl_T1_A0();
1319 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1321 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1322 gen_op_st_T0_A0
[ot
]();
1325 gen_op_addl_A0_im(-opsize
);
1326 gen_op_addl_T0_im(-opsize
);
1327 gen_op_st_T0_A0
[ot
]();
1329 gen_op_addl_A0_im(-opsize
);
1330 /* XXX: add st_T1_A0 ? */
1331 gen_op_movl_T0_T1();
1332 gen_op_st_T0_A0
[ot
]();
1334 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1335 addend
= -esp_addend
;
1337 addend
-= opsize
* (level1
+ 1);
1338 gen_op_addl_T1_im(addend
);
1339 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1342 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1343 is set to true if the instruction sets the PC (last instruction of
1345 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1347 int b
, prefixes
, aflag
, dflag
;
1349 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1350 unsigned int next_eip
;
1360 /* check prefixes */
1363 prefixes
|= PREFIX_REPZ
;
1366 prefixes
|= PREFIX_REPNZ
;
1369 prefixes
|= PREFIX_LOCK
;
1390 prefixes
|= PREFIX_DATA
;
1393 prefixes
|= PREFIX_ADR
;
1396 prefixes
|= PREFIX_FWAIT
;
1400 if (prefixes
& PREFIX_DATA
)
1402 if (prefixes
& PREFIX_ADR
)
1405 s
->prefix
= prefixes
;
1409 /* lock generation */
1410 if (prefixes
& PREFIX_LOCK
)
1413 /* now check op code */
1417 /**************************/
1418 /* extended op code */
1419 b
= ldub(s
->pc
++) | 0x100;
1422 /**************************/
1440 ot
= dflag
? OT_LONG
: OT_WORD
;
1443 case 0: /* OP Ev, Gv */
1444 modrm
= ldub(s
->pc
++);
1445 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1446 mod
= (modrm
>> 6) & 3;
1449 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1450 gen_op_ld_T0_A0
[ot
]();
1453 opreg
= OR_EAX
+ rm
;
1455 gen_op(s
, op
, ot
, opreg
, reg
);
1456 if (mod
!= 3 && op
!= 7) {
1457 gen_op_st_T0_A0
[ot
]();
1460 case 1: /* OP Gv, Ev */
1461 modrm
= ldub(s
->pc
++);
1462 mod
= (modrm
>> 6) & 3;
1463 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1466 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1467 gen_op_ld_T1_A0
[ot
]();
1470 opreg
= OR_EAX
+ rm
;
1472 gen_op(s
, op
, ot
, reg
, opreg
);
1474 case 2: /* OP A, Iv */
1475 val
= insn_get(s
, ot
);
1476 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1482 case 0x80: /* GRP1 */
1491 ot
= dflag
? OT_LONG
: OT_WORD
;
1493 modrm
= ldub(s
->pc
++);
1494 mod
= (modrm
>> 6) & 3;
1496 op
= (modrm
>> 3) & 7;
1499 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1500 gen_op_ld_T0_A0
[ot
]();
1503 opreg
= rm
+ OR_EAX
;
1510 val
= insn_get(s
, ot
);
1513 val
= (int8_t)insn_get(s
, OT_BYTE
);
1517 gen_opi(s
, op
, ot
, opreg
, val
);
1518 if (op
!= 7 && mod
!= 3) {
1519 gen_op_st_T0_A0
[ot
]();
1524 /**************************/
1525 /* inc, dec, and other misc arith */
1526 case 0x40 ... 0x47: /* inc Gv */
1527 ot
= dflag
? OT_LONG
: OT_WORD
;
1528 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1530 case 0x48 ... 0x4f: /* dec Gv */
1531 ot
= dflag
? OT_LONG
: OT_WORD
;
1532 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1534 case 0xf6: /* GRP3 */
1539 ot
= dflag
? OT_LONG
: OT_WORD
;
1541 modrm
= ldub(s
->pc
++);
1542 mod
= (modrm
>> 6) & 3;
1544 op
= (modrm
>> 3) & 7;
1546 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1547 gen_op_ld_T0_A0
[ot
]();
1549 gen_op_mov_TN_reg
[ot
][0][rm
]();
1554 val
= insn_get(s
, ot
);
1555 gen_op_movl_T1_im(val
);
1556 gen_op_testl_T0_T1_cc();
1557 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1562 gen_op_st_T0_A0
[ot
]();
1564 gen_op_mov_reg_T0
[ot
][rm
]();
1568 gen_op_negl_T0_cc();
1570 gen_op_st_T0_A0
[ot
]();
1572 gen_op_mov_reg_T0
[ot
][rm
]();
1574 s
->cc_op
= CC_OP_SUBB
+ ot
;
1579 gen_op_mulb_AL_T0();
1582 gen_op_mulw_AX_T0();
1586 gen_op_mull_EAX_T0();
1589 s
->cc_op
= CC_OP_MUL
;
1594 gen_op_imulb_AL_T0();
1597 gen_op_imulw_AX_T0();
1601 gen_op_imull_EAX_T0();
1604 s
->cc_op
= CC_OP_MUL
;
1609 gen_op_divb_AL_T0();
1612 gen_op_divw_AX_T0();
1616 gen_op_divl_EAX_T0();
1623 gen_op_idivb_AL_T0();
1626 gen_op_idivw_AX_T0();
1630 gen_op_idivl_EAX_T0();
1639 case 0xfe: /* GRP4 */
1640 case 0xff: /* GRP5 */
1644 ot
= dflag
? OT_LONG
: OT_WORD
;
1646 modrm
= ldub(s
->pc
++);
1647 mod
= (modrm
>> 6) & 3;
1649 op
= (modrm
>> 3) & 7;
1650 if (op
>= 2 && b
== 0xfe) {
1654 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1655 if (op
!= 3 && op
!= 5)
1656 gen_op_ld_T0_A0
[ot
]();
1658 gen_op_mov_TN_reg
[ot
][0][rm
]();
1662 case 0: /* inc Ev */
1663 gen_inc(s
, ot
, OR_TMP0
, 1);
1665 gen_op_st_T0_A0
[ot
]();
1667 gen_op_mov_reg_T0
[ot
][rm
]();
1669 case 1: /* dec Ev */
1670 gen_inc(s
, ot
, OR_TMP0
, -1);
1672 gen_op_st_T0_A0
[ot
]();
1674 gen_op_mov_reg_T0
[ot
][rm
]();
1676 case 2: /* call Ev */
1677 /* XXX: optimize if memory (no and is necessary) */
1679 gen_op_andl_T0_ffff();
1681 next_eip
= s
->pc
- s
->cs_base
;
1682 gen_op_movl_T0_im(next_eip
);
1686 case 3: /* lcall Ev */
1687 /* push return segment + offset */
1688 gen_op_movl_T0_seg(R_CS
);
1690 next_eip
= s
->pc
- s
->cs_base
;
1691 gen_op_movl_T0_im(next_eip
);
1694 gen_op_ld_T1_A0
[ot
]();
1695 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1696 gen_op_lduw_T0_A0();
1697 gen_movl_seg_T0(s
, R_CS
);
1698 gen_op_movl_T0_T1();
1702 case 4: /* jmp Ev */
1704 gen_op_andl_T0_ffff();
1708 case 5: /* ljmp Ev */
1709 gen_op_ld_T1_A0
[ot
]();
1710 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1711 gen_op_lduw_T0_A0();
1712 gen_movl_seg_T0(s
, R_CS
);
1713 gen_op_movl_T0_T1();
1717 case 6: /* push Ev */
1725 case 0x84: /* test Ev, Gv */
1730 ot
= dflag
? OT_LONG
: OT_WORD
;
1732 modrm
= ldub(s
->pc
++);
1733 mod
= (modrm
>> 6) & 3;
1735 reg
= (modrm
>> 3) & 7;
1737 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1738 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1739 gen_op_testl_T0_T1_cc();
1740 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1743 case 0xa8: /* test eAX, Iv */
1748 ot
= dflag
? OT_LONG
: OT_WORD
;
1749 val
= insn_get(s
, ot
);
1751 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1752 gen_op_movl_T1_im(val
);
1753 gen_op_testl_T0_T1_cc();
1754 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1757 case 0x98: /* CWDE/CBW */
1759 gen_op_movswl_EAX_AX();
1761 gen_op_movsbw_AX_AL();
1763 case 0x99: /* CDQ/CWD */
1765 gen_op_movslq_EDX_EAX();
1767 gen_op_movswl_DX_AX();
1769 case 0x1af: /* imul Gv, Ev */
1770 case 0x69: /* imul Gv, Ev, I */
1772 ot
= dflag
? OT_LONG
: OT_WORD
;
1773 modrm
= ldub(s
->pc
++);
1774 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1775 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1777 val
= insn_get(s
, ot
);
1778 gen_op_movl_T1_im(val
);
1779 } else if (b
== 0x6b) {
1780 val
= insn_get(s
, OT_BYTE
);
1781 gen_op_movl_T1_im(val
);
1783 gen_op_mov_TN_reg
[ot
][1][reg
]();
1786 if (ot
== OT_LONG
) {
1787 gen_op_imull_T0_T1();
1789 gen_op_imulw_T0_T1();
1791 gen_op_mov_reg_T0
[ot
][reg
]();
1792 s
->cc_op
= CC_OP_MUL
;
1795 case 0x1c1: /* xadd Ev, Gv */
1799 ot
= dflag
? OT_LONG
: OT_WORD
;
1800 modrm
= ldub(s
->pc
++);
1801 reg
= (modrm
>> 3) & 7;
1802 mod
= (modrm
>> 6) & 3;
1805 gen_op_mov_TN_reg
[ot
][0][reg
]();
1806 gen_op_mov_TN_reg
[ot
][1][rm
]();
1807 gen_op_addl_T0_T1_cc();
1808 gen_op_mov_reg_T0
[ot
][rm
]();
1809 gen_op_mov_reg_T1
[ot
][reg
]();
1811 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1812 gen_op_mov_TN_reg
[ot
][0][reg
]();
1813 gen_op_ld_T1_A0
[ot
]();
1814 gen_op_addl_T0_T1_cc();
1815 gen_op_st_T0_A0
[ot
]();
1816 gen_op_mov_reg_T1
[ot
][reg
]();
1818 s
->cc_op
= CC_OP_ADDB
+ ot
;
1821 case 0x1b1: /* cmpxchg Ev, Gv */
1825 ot
= dflag
? OT_LONG
: OT_WORD
;
1826 modrm
= ldub(s
->pc
++);
1827 reg
= (modrm
>> 3) & 7;
1828 mod
= (modrm
>> 6) & 3;
1829 gen_op_mov_TN_reg
[ot
][1][reg
]();
1832 gen_op_mov_TN_reg
[ot
][0][rm
]();
1833 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1834 gen_op_mov_reg_T0
[ot
][rm
]();
1836 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1837 gen_op_ld_T0_A0
[ot
]();
1838 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1839 gen_op_st_T0_A0
[ot
]();
1841 s
->cc_op
= CC_OP_SUBB
+ ot
;
1843 case 0x1c7: /* cmpxchg8b */
1844 modrm
= ldub(s
->pc
++);
1845 mod
= (modrm
>> 6) & 3;
1848 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1849 gen_op_set_cc_op(s
->cc_op
);
1850 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1852 s
->cc_op
= CC_OP_EFLAGS
;
1855 /**************************/
1857 case 0x50 ... 0x57: /* push */
1858 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1861 case 0x58 ... 0x5f: /* pop */
1862 ot
= dflag
? OT_LONG
: OT_WORD
;
1864 gen_op_mov_reg_T0
[ot
][b
& 7]();
1867 case 0x60: /* pusha */
1870 case 0x61: /* popa */
1873 case 0x68: /* push Iv */
1875 ot
= dflag
? OT_LONG
: OT_WORD
;
1877 val
= insn_get(s
, ot
);
1879 val
= (int8_t)insn_get(s
, OT_BYTE
);
1880 gen_op_movl_T0_im(val
);
1883 case 0x8f: /* pop Ev */
1884 ot
= dflag
? OT_LONG
: OT_WORD
;
1885 modrm
= ldub(s
->pc
++);
1887 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1890 case 0xc8: /* enter */
1895 level
= ldub(s
->pc
++);
1896 gen_enter(s
, val
, level
);
1899 case 0xc9: /* leave */
1900 /* XXX: exception not precise (ESP is update before potential exception) */
1902 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1903 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1905 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1906 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1909 ot
= dflag
? OT_LONG
: OT_WORD
;
1910 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1913 case 0x06: /* push es */
1914 case 0x0e: /* push cs */
1915 case 0x16: /* push ss */
1916 case 0x1e: /* push ds */
1917 gen_op_movl_T0_seg(b
>> 3);
1920 case 0x1a0: /* push fs */
1921 case 0x1a8: /* push gs */
1922 gen_op_movl_T0_seg((b
>> 3) & 7);
1925 case 0x07: /* pop es */
1926 case 0x17: /* pop ss */
1927 case 0x1f: /* pop ds */
1929 gen_movl_seg_T0(s
, b
>> 3);
1932 case 0x1a1: /* pop fs */
1933 case 0x1a9: /* pop gs */
1935 gen_movl_seg_T0(s
, (b
>> 3) & 7);
1939 /**************************/
1942 case 0x89: /* mov Gv, Ev */
1946 ot
= dflag
? OT_LONG
: OT_WORD
;
1947 modrm
= ldub(s
->pc
++);
1948 reg
= (modrm
>> 3) & 7;
1950 /* generate a generic store */
1951 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
1954 case 0xc7: /* mov Ev, Iv */
1958 ot
= dflag
? OT_LONG
: OT_WORD
;
1959 modrm
= ldub(s
->pc
++);
1960 mod
= (modrm
>> 6) & 3;
1962 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1963 val
= insn_get(s
, ot
);
1964 gen_op_movl_T0_im(val
);
1966 gen_op_st_T0_A0
[ot
]();
1968 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
1971 case 0x8b: /* mov Ev, Gv */
1975 ot
= dflag
? OT_LONG
: OT_WORD
;
1976 modrm
= ldub(s
->pc
++);
1977 reg
= (modrm
>> 3) & 7;
1979 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1980 gen_op_mov_reg_T0
[ot
][reg
]();
1982 case 0x8e: /* mov seg, Gv */
1983 ot
= dflag
? OT_LONG
: OT_WORD
;
1984 modrm
= ldub(s
->pc
++);
1985 reg
= (modrm
>> 3) & 7;
1986 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1987 if (reg
>= 6 || reg
== R_CS
)
1989 gen_movl_seg_T0(s
, reg
);
1991 case 0x8c: /* mov Gv, seg */
1992 ot
= dflag
? OT_LONG
: OT_WORD
;
1993 modrm
= ldub(s
->pc
++);
1994 reg
= (modrm
>> 3) & 7;
1997 gen_op_movl_T0_seg(reg
);
1998 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2001 case 0x1b6: /* movzbS Gv, Eb */
2002 case 0x1b7: /* movzwS Gv, Eb */
2003 case 0x1be: /* movsbS Gv, Eb */
2004 case 0x1bf: /* movswS Gv, Eb */
2007 /* d_ot is the size of destination */
2008 d_ot
= dflag
+ OT_WORD
;
2009 /* ot is the size of source */
2010 ot
= (b
& 1) + OT_BYTE
;
2011 modrm
= ldub(s
->pc
++);
2012 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2013 mod
= (modrm
>> 6) & 3;
2017 gen_op_mov_TN_reg
[ot
][0][rm
]();
2018 switch(ot
| (b
& 8)) {
2020 gen_op_movzbl_T0_T0();
2023 gen_op_movsbl_T0_T0();
2026 gen_op_movzwl_T0_T0();
2030 gen_op_movswl_T0_T0();
2033 gen_op_mov_reg_T0
[d_ot
][reg
]();
2035 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2037 gen_op_lds_T0_A0
[ot
]();
2039 gen_op_ldu_T0_A0
[ot
]();
2041 gen_op_mov_reg_T0
[d_ot
][reg
]();
2046 case 0x8d: /* lea */
2047 ot
= dflag
? OT_LONG
: OT_WORD
;
2048 modrm
= ldub(s
->pc
++);
2049 reg
= (modrm
>> 3) & 7;
2050 /* we must ensure that no segment is added */
2054 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2056 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2059 case 0xa0: /* mov EAX, Ov */
2061 case 0xa2: /* mov Ov, EAX */
2066 ot
= dflag
? OT_LONG
: OT_WORD
;
2068 offset_addr
= insn_get(s
, OT_LONG
);
2070 offset_addr
= insn_get(s
, OT_WORD
);
2071 gen_op_movl_A0_im(offset_addr
);
2072 /* handle override */
2074 int override
, must_add_seg
;
2075 must_add_seg
= s
->addseg
;
2076 if (s
->override
>= 0) {
2077 override
= s
->override
;
2083 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2087 gen_op_ld_T0_A0
[ot
]();
2088 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2090 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2091 gen_op_st_T0_A0
[ot
]();
2094 case 0xd7: /* xlat */
2095 gen_op_movl_A0_reg
[R_EBX
]();
2096 gen_op_addl_A0_AL();
2098 gen_op_andl_A0_ffff();
2099 /* handle override */
2101 int override
, must_add_seg
;
2102 must_add_seg
= s
->addseg
;
2104 if (s
->override
>= 0) {
2105 override
= s
->override
;
2111 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2114 gen_op_ldub_T0_A0();
2115 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2117 case 0xb0 ... 0xb7: /* mov R, Ib */
2118 val
= insn_get(s
, OT_BYTE
);
2119 gen_op_movl_T0_im(val
);
2120 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2122 case 0xb8 ... 0xbf: /* mov R, Iv */
2123 ot
= dflag
? OT_LONG
: OT_WORD
;
2124 val
= insn_get(s
, ot
);
2125 reg
= OR_EAX
+ (b
& 7);
2126 gen_op_movl_T0_im(val
);
2127 gen_op_mov_reg_T0
[ot
][reg
]();
2130 case 0x91 ... 0x97: /* xchg R, EAX */
2131 ot
= dflag
? OT_LONG
: OT_WORD
;
2136 case 0x87: /* xchg Ev, Gv */
2140 ot
= dflag
? OT_LONG
: OT_WORD
;
2141 modrm
= ldub(s
->pc
++);
2142 reg
= (modrm
>> 3) & 7;
2143 mod
= (modrm
>> 6) & 3;
2147 gen_op_mov_TN_reg
[ot
][0][reg
]();
2148 gen_op_mov_TN_reg
[ot
][1][rm
]();
2149 gen_op_mov_reg_T0
[ot
][rm
]();
2150 gen_op_mov_reg_T1
[ot
][reg
]();
2152 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2153 gen_op_mov_TN_reg
[ot
][0][reg
]();
2154 /* for xchg, lock is implicit */
2155 if (!(prefixes
& PREFIX_LOCK
))
2157 gen_op_ld_T1_A0
[ot
]();
2158 gen_op_st_T0_A0
[ot
]();
2159 if (!(prefixes
& PREFIX_LOCK
))
2161 gen_op_mov_reg_T1
[ot
][reg
]();
2164 case 0xc4: /* les Gv */
2167 case 0xc5: /* lds Gv */
2170 case 0x1b2: /* lss Gv */
2173 case 0x1b4: /* lfs Gv */
2176 case 0x1b5: /* lgs Gv */
2179 ot
= dflag
? OT_LONG
: OT_WORD
;
2180 modrm
= ldub(s
->pc
++);
2181 reg
= (modrm
>> 3) & 7;
2182 mod
= (modrm
>> 6) & 3;
2185 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2186 gen_op_ld_T1_A0
[ot
]();
2187 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2188 /* load the segment first to handle exceptions properly */
2189 gen_op_lduw_T0_A0();
2190 gen_movl_seg_T0(s
, op
);
2191 /* then put the data */
2192 gen_op_mov_reg_T1
[ot
][reg
]();
2195 /************************/
2206 ot
= dflag
? OT_LONG
: OT_WORD
;
2208 modrm
= ldub(s
->pc
++);
2209 mod
= (modrm
>> 6) & 3;
2211 op
= (modrm
>> 3) & 7;
2214 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2215 gen_op_ld_T0_A0
[ot
]();
2218 opreg
= rm
+ OR_EAX
;
2223 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2226 shift
= ldub(s
->pc
++);
2228 gen_shifti(s
, op
, ot
, opreg
, shift
);
2232 gen_op_st_T0_A0
[ot
]();
2247 case 0x1a4: /* shld imm */
2251 case 0x1a5: /* shld cl */
2255 case 0x1ac: /* shrd imm */
2259 case 0x1ad: /* shrd cl */
2263 ot
= dflag
? OT_LONG
: OT_WORD
;
2264 modrm
= ldub(s
->pc
++);
2265 mod
= (modrm
>> 6) & 3;
2267 reg
= (modrm
>> 3) & 7;
2270 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2271 gen_op_ld_T0_A0
[ot
]();
2273 gen_op_mov_TN_reg
[ot
][0][rm
]();
2275 gen_op_mov_TN_reg
[ot
][1][reg
]();
2278 val
= ldub(s
->pc
++);
2281 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2282 if (op
== 0 && ot
!= OT_WORD
)
2283 s
->cc_op
= CC_OP_SHLB
+ ot
;
2285 s
->cc_op
= CC_OP_SARB
+ ot
;
2288 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2289 gen_op_set_cc_op(s
->cc_op
);
2290 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2291 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2294 gen_op_st_T0_A0
[ot
]();
2296 gen_op_mov_reg_T0
[ot
][rm
]();
2300 /************************/
2303 modrm
= ldub(s
->pc
++);
2304 mod
= (modrm
>> 6) & 3;
2306 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2310 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2312 case 0x00 ... 0x07: /* fxxxs */
2313 case 0x10 ... 0x17: /* fixxxl */
2314 case 0x20 ... 0x27: /* fxxxl */
2315 case 0x30 ... 0x37: /* fixxx */
2322 gen_op_flds_FT0_A0();
2325 gen_op_fildl_FT0_A0();
2328 gen_op_fldl_FT0_A0();
2332 gen_op_fild_FT0_A0();
2336 gen_op_fp_arith_ST0_FT0
[op1
]();
2338 /* fcomp needs pop */
2343 case 0x08: /* flds */
2344 case 0x0a: /* fsts */
2345 case 0x0b: /* fstps */
2346 case 0x18: /* fildl */
2347 case 0x1a: /* fistl */
2348 case 0x1b: /* fistpl */
2349 case 0x28: /* fldl */
2350 case 0x2a: /* fstl */
2351 case 0x2b: /* fstpl */
2352 case 0x38: /* filds */
2353 case 0x3a: /* fists */
2354 case 0x3b: /* fistps */
2361 gen_op_flds_ST0_A0();
2364 gen_op_fildl_ST0_A0();
2367 gen_op_fldl_ST0_A0();
2371 gen_op_fild_ST0_A0();
2378 gen_op_fsts_ST0_A0();
2381 gen_op_fistl_ST0_A0();
2384 gen_op_fstl_ST0_A0();
2388 gen_op_fist_ST0_A0();
2396 case 0x0d: /* fldcw mem */
2399 case 0x0f: /* fnstcw mem */
2402 case 0x1d: /* fldt mem */
2404 gen_op_fldt_ST0_A0();
2406 case 0x1f: /* fstpt mem */
2407 gen_op_fstt_ST0_A0();
2410 case 0x2f: /* fnstsw mem */
2413 case 0x3c: /* fbld */
2415 gen_op_fbld_ST0_A0();
2417 case 0x3e: /* fbstp */
2418 gen_op_fbst_ST0_A0();
2421 case 0x3d: /* fildll */
2423 gen_op_fildll_ST0_A0();
2425 case 0x3f: /* fistpll */
2426 gen_op_fistll_ST0_A0();
2433 /* register float ops */
2437 case 0x08: /* fld sti */
2439 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2441 case 0x09: /* fxchg sti */
2442 gen_op_fxchg_ST0_STN(opreg
);
2444 case 0x0a: /* grp d9/2 */
2452 case 0x0c: /* grp d9/4 */
2462 gen_op_fcom_ST0_FT0();
2471 case 0x0d: /* grp d9/5 */
2480 gen_op_fldl2t_ST0();
2484 gen_op_fldl2e_ST0();
2492 gen_op_fldlg2_ST0();
2496 gen_op_fldln2_ST0();
2507 case 0x0e: /* grp d9/6 */
2518 case 3: /* fpatan */
2521 case 4: /* fxtract */
2524 case 5: /* fprem1 */
2527 case 6: /* fdecstp */
2531 case 7: /* fincstp */
2536 case 0x0f: /* grp d9/7 */
2541 case 1: /* fyl2xp1 */
2547 case 3: /* fsincos */
2550 case 5: /* fscale */
2553 case 4: /* frndint */
2565 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2566 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2567 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2573 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2577 gen_op_fmov_FT0_STN(opreg
);
2578 gen_op_fp_arith_ST0_FT0
[op1
]();
2582 case 0x02: /* fcom */
2583 gen_op_fmov_FT0_STN(opreg
);
2584 gen_op_fcom_ST0_FT0();
2586 case 0x03: /* fcomp */
2587 gen_op_fmov_FT0_STN(opreg
);
2588 gen_op_fcom_ST0_FT0();
2591 case 0x15: /* da/5 */
2593 case 1: /* fucompp */
2594 gen_op_fmov_FT0_STN(1);
2595 gen_op_fucom_ST0_FT0();
2608 case 3: /* fninit */
2615 case 0x2a: /* fst sti */
2616 gen_op_fmov_STN_ST0(opreg
);
2618 case 0x2b: /* fstp sti */
2619 gen_op_fmov_STN_ST0(opreg
);
2622 case 0x2c: /* fucom st(i) */
2623 gen_op_fmov_FT0_STN(opreg
);
2624 gen_op_fucom_ST0_FT0();
2626 case 0x2d: /* fucomp st(i) */
2627 gen_op_fmov_FT0_STN(opreg
);
2628 gen_op_fucom_ST0_FT0();
2631 case 0x33: /* de/3 */
2633 case 1: /* fcompp */
2634 gen_op_fmov_FT0_STN(1);
2635 gen_op_fcom_ST0_FT0();
2643 case 0x3c: /* df/4 */
2646 gen_op_fnstsw_EAX();
2657 /************************/
2660 case 0xa4: /* movsS */
2665 ot
= dflag
? OT_LONG
: OT_WORD
;
2667 if (prefixes
& PREFIX_REPZ
) {
2668 gen_string_ds(s
, ot
, gen_op_movs
+ 9);
2670 gen_string_ds(s
, ot
, gen_op_movs
);
2674 case 0xaa: /* stosS */
2679 ot
= dflag
? OT_LONG
: OT_WORD
;
2681 if (prefixes
& PREFIX_REPZ
) {
2682 gen_string_es(s
, ot
, gen_op_stos
+ 9);
2684 gen_string_es(s
, ot
, gen_op_stos
);
2687 case 0xac: /* lodsS */
2692 ot
= dflag
? OT_LONG
: OT_WORD
;
2693 if (prefixes
& PREFIX_REPZ
) {
2694 gen_string_ds(s
, ot
, gen_op_lods
+ 9);
2696 gen_string_ds(s
, ot
, gen_op_lods
);
2699 case 0xae: /* scasS */
2704 ot
= dflag
? OT_LONG
: OT_WORD
;
2705 if (prefixes
& PREFIX_REPNZ
) {
2706 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2707 gen_op_set_cc_op(s
->cc_op
);
2708 gen_string_es(s
, ot
, gen_op_scas
+ 9 * 2);
2709 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2710 } else if (prefixes
& PREFIX_REPZ
) {
2711 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2712 gen_op_set_cc_op(s
->cc_op
);
2713 gen_string_es(s
, ot
, gen_op_scas
+ 9);
2714 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2716 gen_string_es(s
, ot
, gen_op_scas
);
2717 s
->cc_op
= CC_OP_SUBB
+ ot
;
2721 case 0xa6: /* cmpsS */
2726 ot
= dflag
? OT_LONG
: OT_WORD
;
2727 if (prefixes
& PREFIX_REPNZ
) {
2728 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2729 gen_op_set_cc_op(s
->cc_op
);
2730 gen_string_ds(s
, ot
, gen_op_cmps
+ 9 * 2);
2731 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2732 } else if (prefixes
& PREFIX_REPZ
) {
2733 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2734 gen_op_set_cc_op(s
->cc_op
);
2735 gen_string_ds(s
, ot
, gen_op_cmps
+ 9);
2736 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2738 gen_string_ds(s
, ot
, gen_op_cmps
);
2739 s
->cc_op
= CC_OP_SUBB
+ ot
;
2742 case 0x6c: /* insS */
2747 ot
= dflag
? OT_LONG
: OT_WORD
;
2748 if (prefixes
& PREFIX_REPZ
) {
2749 gen_string_es(s
, ot
, gen_op_ins
+ 9);
2751 gen_string_es(s
, ot
, gen_op_ins
);
2754 case 0x6e: /* outsS */
2759 ot
= dflag
? OT_LONG
: OT_WORD
;
2760 if (prefixes
& PREFIX_REPZ
) {
2761 gen_string_ds(s
, ot
, gen_op_outs
+ 9);
2763 gen_string_ds(s
, ot
, gen_op_outs
);
2767 /************************/
2774 ot
= dflag
? OT_LONG
: OT_WORD
;
2775 val
= ldub(s
->pc
++);
2776 gen_op_movl_T0_im(val
);
2778 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2785 ot
= dflag
? OT_LONG
: OT_WORD
;
2786 val
= ldub(s
->pc
++);
2787 gen_op_movl_T0_im(val
);
2788 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2796 ot
= dflag
? OT_LONG
: OT_WORD
;
2797 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2799 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2806 ot
= dflag
? OT_LONG
: OT_WORD
;
2807 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2808 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2812 /************************/
2814 case 0xc2: /* ret im */
2819 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2821 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2823 gen_op_andl_T0_ffff();
2827 case 0xc3: /* ret */
2831 gen_op_andl_T0_ffff();
2835 case 0xca: /* lret im */
2836 /* XXX: not restartable */
2842 gen_op_andl_T0_ffff();
2847 gen_movl_seg_T0(s
, R_CS
);
2849 /* add stack offset */
2851 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2853 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2856 case 0xcb: /* lret */
2857 /* XXX: not restartable */
2861 gen_op_andl_T0_ffff();
2866 gen_movl_seg_T0(s
, R_CS
);
2870 case 0xcf: /* iret */
2871 /* XXX: not restartable */
2875 gen_op_andl_T0_ffff();
2880 gen_movl_seg_T0(s
, R_CS
);
2886 gen_op_movl_eflags_T0_vm(pc_start
- s
->cs_base
);
2888 gen_op_movl_eflags_T0();
2891 gen_op_movw_eflags_T0_vm(pc_start
- s
->cs_base
);
2893 gen_op_movw_eflags_T0();
2896 s
->cc_op
= CC_OP_EFLAGS
;
2899 case 0xe8: /* call im */
2901 unsigned int next_eip
;
2902 ot
= dflag
? OT_LONG
: OT_WORD
;
2903 val
= insn_get(s
, ot
);
2904 next_eip
= s
->pc
- s
->cs_base
;
2908 gen_op_movl_T0_im(next_eip
);
2914 case 0x9a: /* lcall im */
2916 unsigned int selector
, offset
;
2918 ot
= dflag
? OT_LONG
: OT_WORD
;
2919 offset
= insn_get(s
, ot
);
2920 selector
= insn_get(s
, OT_WORD
);
2922 /* push return segment + offset */
2923 gen_op_movl_T0_seg(R_CS
);
2925 next_eip
= s
->pc
- s
->cs_base
;
2926 gen_op_movl_T0_im(next_eip
);
2929 /* change cs and pc */
2930 gen_op_movl_T0_im(selector
);
2931 gen_movl_seg_T0(s
, R_CS
);
2932 gen_op_jmp_im((unsigned long)offset
);
2936 case 0xe9: /* jmp */
2937 ot
= dflag
? OT_LONG
: OT_WORD
;
2938 val
= insn_get(s
, ot
);
2939 val
+= s
->pc
- s
->cs_base
;
2945 case 0xea: /* ljmp im */
2947 unsigned int selector
, offset
;
2949 ot
= dflag
? OT_LONG
: OT_WORD
;
2950 offset
= insn_get(s
, ot
);
2951 selector
= insn_get(s
, OT_WORD
);
2953 /* change cs and pc */
2954 gen_op_movl_T0_im(selector
);
2955 gen_movl_seg_T0(s
, R_CS
);
2956 gen_op_jmp_im((unsigned long)offset
);
2960 case 0xeb: /* jmp Jb */
2961 val
= (int8_t)insn_get(s
, OT_BYTE
);
2962 val
+= s
->pc
- s
->cs_base
;
2968 case 0x70 ... 0x7f: /* jcc Jb */
2969 val
= (int8_t)insn_get(s
, OT_BYTE
);
2971 case 0x180 ... 0x18f: /* jcc Jv */
2973 val
= insn_get(s
, OT_LONG
);
2975 val
= (int16_t)insn_get(s
, OT_WORD
);
2978 next_eip
= s
->pc
- s
->cs_base
;
2982 gen_jcc(s
, b
, val
, next_eip
);
2986 case 0x190 ... 0x19f: /* setcc Gv */
2987 modrm
= ldub(s
->pc
++);
2989 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
2991 case 0x140 ... 0x14f: /* cmov Gv, Ev */
2992 ot
= dflag
? OT_LONG
: OT_WORD
;
2993 modrm
= ldub(s
->pc
++);
2994 reg
= (modrm
>> 3) & 7;
2995 mod
= (modrm
>> 6) & 3;
2998 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2999 gen_op_ld_T1_A0
[ot
]();
3002 gen_op_mov_TN_reg
[ot
][1][rm
]();
3004 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
3007 /************************/
3009 case 0x9c: /* pushf */
3010 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3011 gen_op_set_cc_op(s
->cc_op
);
3013 gen_op_movl_T0_eflags_vm();
3015 gen_op_movl_T0_eflags();
3018 case 0x9d: /* popf */
3022 gen_op_movl_eflags_T0_vm(pc_start
- s
->cs_base
);
3024 gen_op_movl_eflags_T0();
3027 gen_op_movw_eflags_T0_vm(pc_start
- s
->cs_base
);
3029 gen_op_movw_eflags_T0();
3032 s
->cc_op
= CC_OP_EFLAGS
;
3034 case 0x9e: /* sahf */
3035 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
3036 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3037 gen_op_set_cc_op(s
->cc_op
);
3038 gen_op_movb_eflags_T0();
3039 s
->cc_op
= CC_OP_EFLAGS
;
3041 case 0x9f: /* lahf */
3042 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3043 gen_op_set_cc_op(s
->cc_op
);
3044 gen_op_movl_T0_eflags();
3045 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
3047 case 0xf5: /* cmc */
3048 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3049 gen_op_set_cc_op(s
->cc_op
);
3051 s
->cc_op
= CC_OP_EFLAGS
;
3053 case 0xf8: /* clc */
3054 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3055 gen_op_set_cc_op(s
->cc_op
);
3057 s
->cc_op
= CC_OP_EFLAGS
;
3059 case 0xf9: /* stc */
3060 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3061 gen_op_set_cc_op(s
->cc_op
);
3063 s
->cc_op
= CC_OP_EFLAGS
;
3065 case 0xfc: /* cld */
3068 case 0xfd: /* std */
3072 /************************/
3073 /* bit operations */
3074 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3075 ot
= dflag
? OT_LONG
: OT_WORD
;
3076 modrm
= ldub(s
->pc
++);
3077 op
= (modrm
>> 3) & 7;
3078 mod
= (modrm
>> 6) & 3;
3081 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3082 gen_op_ld_T0_A0
[ot
]();
3084 gen_op_mov_TN_reg
[ot
][0][rm
]();
3087 val
= ldub(s
->pc
++);
3088 gen_op_movl_T1_im(val
);
3092 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3093 s
->cc_op
= CC_OP_SARB
+ ot
;
3096 gen_op_st_T0_A0
[ot
]();
3098 gen_op_mov_reg_T0
[ot
][rm
]();
3101 case 0x1a3: /* bt Gv, Ev */
3104 case 0x1ab: /* bts */
3107 case 0x1b3: /* btr */
3110 case 0x1bb: /* btc */
3113 ot
= dflag
? OT_LONG
: OT_WORD
;
3114 modrm
= ldub(s
->pc
++);
3115 reg
= (modrm
>> 3) & 7;
3116 mod
= (modrm
>> 6) & 3;
3118 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3120 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3121 /* specific case: we need to add a displacement */
3123 gen_op_add_bitw_A0_T1();
3125 gen_op_add_bitl_A0_T1();
3126 gen_op_ld_T0_A0
[ot
]();
3128 gen_op_mov_TN_reg
[ot
][0][rm
]();
3130 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3131 s
->cc_op
= CC_OP_SARB
+ ot
;
3134 gen_op_st_T0_A0
[ot
]();
3136 gen_op_mov_reg_T0
[ot
][rm
]();
3139 case 0x1bc: /* bsf */
3140 case 0x1bd: /* bsr */
3141 ot
= dflag
? OT_LONG
: OT_WORD
;
3142 modrm
= ldub(s
->pc
++);
3143 reg
= (modrm
>> 3) & 7;
3144 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3145 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3146 /* NOTE: we always write back the result. Intel doc says it is
3147 undefined if T0 == 0 */
3148 gen_op_mov_reg_T0
[ot
][reg
]();
3149 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3151 /************************/
3153 case 0x27: /* daa */
3154 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3155 gen_op_set_cc_op(s
->cc_op
);
3157 s
->cc_op
= CC_OP_EFLAGS
;
3159 case 0x2f: /* das */
3160 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3161 gen_op_set_cc_op(s
->cc_op
);
3163 s
->cc_op
= CC_OP_EFLAGS
;
3165 case 0x37: /* aaa */
3166 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3167 gen_op_set_cc_op(s
->cc_op
);
3169 s
->cc_op
= CC_OP_EFLAGS
;
3171 case 0x3f: /* aas */
3172 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3173 gen_op_set_cc_op(s
->cc_op
);
3175 s
->cc_op
= CC_OP_EFLAGS
;
3177 case 0xd4: /* aam */
3178 val
= ldub(s
->pc
++);
3180 s
->cc_op
= CC_OP_LOGICB
;
3182 case 0xd5: /* aad */
3183 val
= ldub(s
->pc
++);
3185 s
->cc_op
= CC_OP_LOGICB
;
3187 /************************/
3189 case 0x90: /* nop */
3191 case 0xcc: /* int3 */
3192 gen_op_int3((long)pc_start
);
3195 case 0xcd: /* int N */
3196 val
= ldub(s
->pc
++);
3197 /* XXX: currently we ignore the interrupt number */
3198 gen_op_int_im(pc_start
- s
->cs_base
);
3201 case 0xce: /* into */
3202 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3203 gen_op_set_cc_op(s
->cc_op
);
3206 case 0xfa: /* cli */
3212 case 0xfb: /* sti */
3214 gen_op_sti_vm(pc_start
- s
->cs_base
);
3218 case 0x62: /* bound */
3219 ot
= dflag
? OT_LONG
: OT_WORD
;
3220 modrm
= ldub(s
->pc
++);
3221 reg
= (modrm
>> 3) & 7;
3222 mod
= (modrm
>> 6) & 3;
3225 gen_op_mov_reg_T0
[ot
][reg
]();
3226 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3232 case 0x1c8 ... 0x1cf: /* bswap reg */
3234 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3236 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3238 case 0xd6: /* salc */
3239 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3240 gen_op_set_cc_op(s
->cc_op
);
3243 case 0xe0: /* loopnz */
3244 case 0xe1: /* loopz */
3245 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3246 gen_op_set_cc_op(s
->cc_op
);
3248 case 0xe2: /* loop */
3249 case 0xe3: /* jecxz */
3250 val
= (int8_t)insn_get(s
, OT_BYTE
);
3251 next_eip
= s
->pc
- s
->cs_base
;
3255 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3258 case 0x131: /* rdtsc */
3261 case 0x1a2: /* cpuid */
3267 /* lock generation */
3268 if (s
->prefix
& PREFIX_LOCK
)
3272 /* XXX: ensure that no lock was generated */
3276 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3277 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3279 /* flags read by an operation */
3280 static uint16_t opc_read_flags
[NB_OPS
] = {
3281 [INDEX_op_aas
] = CC_A
,
3282 [INDEX_op_aaa
] = CC_A
,
3283 [INDEX_op_das
] = CC_A
| CC_C
,
3284 [INDEX_op_daa
] = CC_A
| CC_C
,
3286 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3287 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3288 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3289 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3290 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3291 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3293 [INDEX_op_into
] = CC_O
,
3295 [INDEX_op_jo_cc
] = CC_O
,
3296 [INDEX_op_jb_cc
] = CC_C
,
3297 [INDEX_op_jz_cc
] = CC_Z
,
3298 [INDEX_op_jbe_cc
] = CC_Z
| CC_C
,
3299 [INDEX_op_js_cc
] = CC_S
,
3300 [INDEX_op_jp_cc
] = CC_P
,
3301 [INDEX_op_jl_cc
] = CC_O
| CC_S
,
3302 [INDEX_op_jle_cc
] = CC_O
| CC_S
| CC_Z
,
3304 [INDEX_op_jb_subb
] = CC_C
,
3305 [INDEX_op_jb_subw
] = CC_C
,
3306 [INDEX_op_jb_subl
] = CC_C
,
3308 [INDEX_op_jz_subb
] = CC_Z
,
3309 [INDEX_op_jz_subw
] = CC_Z
,
3310 [INDEX_op_jz_subl
] = CC_Z
,
3312 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3313 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3314 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3316 [INDEX_op_js_subb
] = CC_S
,
3317 [INDEX_op_js_subw
] = CC_S
,
3318 [INDEX_op_js_subl
] = CC_S
,
3320 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3321 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3322 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3324 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3325 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3326 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3328 [INDEX_op_loopnzw
] = CC_Z
,
3329 [INDEX_op_loopnzl
] = CC_Z
,
3330 [INDEX_op_loopzw
] = CC_Z
,
3331 [INDEX_op_loopzl
] = CC_Z
,
3333 [INDEX_op_seto_T0_cc
] = CC_O
,
3334 [INDEX_op_setb_T0_cc
] = CC_C
,
3335 [INDEX_op_setz_T0_cc
] = CC_Z
,
3336 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3337 [INDEX_op_sets_T0_cc
] = CC_S
,
3338 [INDEX_op_setp_T0_cc
] = CC_P
,
3339 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3340 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3342 [INDEX_op_setb_T0_subb
] = CC_C
,
3343 [INDEX_op_setb_T0_subw
] = CC_C
,
3344 [INDEX_op_setb_T0_subl
] = CC_C
,
3346 [INDEX_op_setz_T0_subb
] = CC_Z
,
3347 [INDEX_op_setz_T0_subw
] = CC_Z
,
3348 [INDEX_op_setz_T0_subl
] = CC_Z
,
3350 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3351 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3352 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3354 [INDEX_op_sets_T0_subb
] = CC_S
,
3355 [INDEX_op_sets_T0_subw
] = CC_S
,
3356 [INDEX_op_sets_T0_subl
] = CC_S
,
3358 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3359 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3360 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3362 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3363 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3364 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3366 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3367 [INDEX_op_movl_T0_eflags_vm
] = CC_OSZAPC
,
3368 [INDEX_op_cmc
] = CC_C
,
3369 [INDEX_op_salc
] = CC_C
,
3371 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3372 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3373 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3374 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3375 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3376 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3379 /* flags written by an operation */
3380 static uint16_t opc_write_flags
[NB_OPS
] = {
3381 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3382 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3383 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3384 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3385 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3386 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3387 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3388 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3389 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3390 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3391 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3392 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3393 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3394 [INDEX_op_incl_T0_cc
] = CC_OSZAP
,
3395 [INDEX_op_decl_T0_cc
] = CC_OSZAP
,
3396 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3398 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3399 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3400 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3401 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3402 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3403 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3404 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3405 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3408 [INDEX_op_aam
] = CC_OSZAPC
,
3409 [INDEX_op_aad
] = CC_OSZAPC
,
3410 [INDEX_op_aas
] = CC_OSZAPC
,
3411 [INDEX_op_aaa
] = CC_OSZAPC
,
3412 [INDEX_op_das
] = CC_OSZAPC
,
3413 [INDEX_op_daa
] = CC_OSZAPC
,
3415 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3416 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
3417 [INDEX_op_movw_eflags_T0_vm
] = CC_OSZAPC
,
3418 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3419 [INDEX_op_movl_eflags_T0_vm
] = CC_OSZAPC
,
3420 [INDEX_op_clc
] = CC_C
,
3421 [INDEX_op_stc
] = CC_C
,
3422 [INDEX_op_cmc
] = CC_C
,
3424 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3425 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3426 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3427 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3428 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3429 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3431 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3432 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3433 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3434 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3435 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3436 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3438 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3439 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3440 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3442 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3443 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3444 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3446 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3447 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3448 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3450 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3451 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3452 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3453 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3455 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3456 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3457 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3458 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3460 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3461 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3462 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3463 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3464 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3465 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3466 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3467 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3469 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3470 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3471 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3472 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3475 #define STRINGOP(x) \
3476 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3477 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3478 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3479 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3480 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3481 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3482 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3483 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3484 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3488 STRINGOP(repnz_scas
)
3491 STRINGOP(repnz_cmps
)
3493 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
3494 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3495 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3497 [INDEX_op_cmpxchg8b
] = CC_Z
,
3500 /* simpler form of an operation if no flags need to be generated */
3501 static uint16_t opc_simpler
[NB_OPS
] = {
3502 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3503 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3504 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3505 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3506 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3507 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3508 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3509 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3511 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3512 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3513 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3515 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3516 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3517 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3519 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3520 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3521 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3523 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3524 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3525 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3527 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3528 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3529 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3532 static void optimize_flags_init(void)
3535 /* put default values in arrays */
3536 for(i
= 0; i
< NB_OPS
; i
++) {
3537 if (opc_simpler
[i
] == 0)
3542 /* CPU flags computation optimization: we move backward thru the
3543 generated code to see which flags are needed. The operation is
3544 modified if suitable */
3545 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3548 int live_flags
, write_flags
, op
;
3550 opc_ptr
= opc_buf
+ opc_buf_len
;
3551 /* live_flags contains the flags needed by the next instructions
3552 in the code. At the end of the bloc, we consider that all the
3554 live_flags
= CC_OSZAPC
;
3555 while (opc_ptr
> opc_buf
) {
3557 /* if none of the flags written by the instruction is used,
3558 then we can try to find a simpler instruction */
3559 write_flags
= opc_write_flags
[op
];
3560 if ((live_flags
& write_flags
) == 0) {
3561 *opc_ptr
= opc_simpler
[op
];
3563 /* compute the live flags before the instruction */
3564 live_flags
&= ~write_flags
;
3565 live_flags
|= opc_read_flags
[op
];
3571 static const char *op_str
[] = {
3572 #define DEF(s, n) #s,
3573 #include "opc-i386.h"
3577 static uint8_t op_nb_args
[] = {
3578 #define DEF(s, n) n,
3579 #include "opc-i386.h"
3583 static void dump_ops(const uint16_t *opc_buf
, const uint32_t *opparam_buf
)
3585 const uint16_t *opc_ptr
;
3586 const uint32_t *opparam_ptr
;
3590 opparam_ptr
= opparam_buf
;
3594 fprintf(logfile
, "0x%04x: %s", opc_ptr
- opc_buf
- 1, op_str
[c
]);
3595 for(i
= 0; i
< n
; i
++) {
3596 fprintf(logfile
, " 0x%x", opparam_ptr
[i
]);
3598 fprintf(logfile
, "\n");
3599 if (c
== INDEX_op_end
)
3607 /* XXX: make this buffer thread safe */
3608 /* XXX: make safe guess about sizes */
3609 #define MAX_OP_PER_INSTR 32
3610 #define OPC_BUF_SIZE 512
3611 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3613 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3615 static uint16_t gen_opc_buf
[OPC_BUF_SIZE
];
3616 static uint32_t gen_opparam_buf
[OPPARAM_BUF_SIZE
];
3618 /* return non zero if the very first instruction is invalid so that
3619 the virtual CPU can trigger an exception. */
3620 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
3621 int *gen_code_size_ptr
,
3622 uint8_t *pc_start
, uint8_t *cs_base
, int flags
)
3624 DisasContext dc1
, *dc
= &dc1
;
3626 uint16_t *gen_opc_end
;
3630 struct disassemble_info disasm_info
;
3633 /* generate intermediate code */
3635 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3636 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3637 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3638 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3639 dc
->vm86
= (flags
>> GEN_FLAG_VM_SHIFT
) & 1;
3640 dc
->cc_op
= CC_OP_DYNAMIC
;
3641 dc
->cs_base
= cs_base
;
3643 gen_opc_ptr
= gen_opc_buf
;
3644 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3645 gen_opparam_ptr
= gen_opparam_buf
;
3650 ret
= disas_insn(dc
, pc_ptr
);
3652 /* we trigger an illegal instruction operation only if it
3653 is the first instruction. Otherwise, we simply stop
3654 generating the code just before it */
3655 if (pc_ptr
== pc_start
)
3660 pc_ptr
= (void *)ret
;
3661 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
);
3662 /* we must store the eflags state if it is not already done */
3663 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3664 gen_op_set_cc_op(dc
->cc_op
);
3665 if (dc
->is_jmp
!= 1) {
3666 /* we add an additionnal jmp to update the simulated PC */
3667 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3669 *gen_opc_ptr
= INDEX_op_end
;
3671 /* optimize flag computations */
3677 INIT_DISASSEMBLE_INFO(disasm_info
, logfile
, fprintf
);
3679 disasm_info
.flavour
= bfd_get_flavour (abfd
);
3680 disasm_info
.arch
= bfd_get_arch (abfd
);
3681 disasm_info
.mach
= bfd_get_mach (abfd
);
3683 disasm_info
.endian
= BFD_ENDIAN_LITTLE
;
3685 disasm_info
.mach
= bfd_mach_i386_i386
;
3687 disasm_info
.mach
= bfd_mach_i386_i8086
;
3688 fprintf(logfile
, "----------------\n");
3689 fprintf(logfile
, "IN:\n");
3690 disasm_info
.buffer
= pc_start
;
3691 disasm_info
.buffer_vma
= (unsigned long)pc_start
;
3692 disasm_info
.buffer_length
= pc_ptr
- pc_start
;
3694 while (pc
< pc_ptr
) {
3695 fprintf(logfile
, "0x%08lx: ", (long)pc
);
3696 count
= print_insn_i386((unsigned long)pc
, &disasm_info
);
3697 fprintf(logfile
, "\n");
3700 fprintf(logfile
, "\n");
3702 fprintf(logfile
, "OP:\n");
3703 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3704 fprintf(logfile
, "\n");
3708 /* optimize flag computations */
3709 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3713 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3714 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3715 fprintf(logfile
, "\n");
3719 /* generate machine code */
3720 gen_code_size
= dyngen_code(gen_code_buf
, gen_opc_buf
, gen_opparam_buf
);
3721 flush_icache_range((unsigned long)gen_code_buf
, (unsigned long)(gen_code_buf
+ gen_code_size
));
3722 *gen_code_size_ptr
= gen_code_size
;
3729 INIT_DISASSEMBLE_INFO(disasm_info
, logfile
, fprintf
);
3731 disasm_info
.flavour
= bfd_get_flavour (abfd
);
3732 disasm_info
.arch
= bfd_get_arch (abfd
);
3733 disasm_info
.mach
= bfd_get_mach (abfd
);
3735 #ifdef WORDS_BIGENDIAN
3736 disasm_info
.endian
= BFD_ENDIAN_BIG
;
3738 disasm_info
.endian
= BFD_ENDIAN_LITTLE
;
3740 disasm_info
.mach
= bfd_mach_i386_i386
;
3743 disasm_info
.buffer
= pc
;
3744 disasm_info
.buffer_vma
= (unsigned long)pc
;
3745 disasm_info
.buffer_length
= *gen_code_size_ptr
;
3746 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
3747 while (pc
< gen_code_buf
+ *gen_code_size_ptr
) {
3748 fprintf(logfile
, "0x%08lx: ", (long)pc
);
3749 count
= print_insn_i386((unsigned long)pc
, &disasm_info
);
3750 fprintf(logfile
, "\n");
3753 fprintf(logfile
, "\n");
3760 CPUX86State
*cpu_x86_init(void)
3766 cpu_x86_tblocks_init();
3768 env
= malloc(sizeof(CPUX86State
));
3771 memset(env
, 0, sizeof(CPUX86State
));
3772 /* basic FPU init */
3773 for(i
= 0;i
< 8; i
++)
3776 /* flags setup : we activate the IRQs by default as in user mode */
3777 env
->eflags
= 0x2 | IF_MASK
;
3779 /* init various static tables */
3782 optimize_flags_init();
3787 void cpu_x86_close(CPUX86State
*env
)