4 * Copyright (c) 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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
)
55 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
57 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
61 p
= start
& ~(MIN_CACHE_LINE_SIZE
- 1);
62 stop
= (stop
+ MIN_CACHE_LINE_SIZE
- 1) & ~(MIN_CACHE_LINE_SIZE
- 1);
64 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
65 asm ("dcbst 0,%0;" : : "r"(p
) : "memory");
68 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
69 asm ("icbi 0,%0; sync;" : : "r"(p
) : "memory");
80 #define PREFIX_REPNZ 2
83 #define PREFIX_SS 0x10
84 #define PREFIX_DS 0x20
85 #define PREFIX_ES 0x40
86 #define PREFIX_FS 0x80
87 #define PREFIX_GS 0x100
88 #define PREFIX_DATA 0x200
89 #define PREFIX_ADR 0x400
90 #define PREFIX_FWAIT 0x800
92 typedef struct DisasContext
{
93 /* current insn context */
96 uint8_t *pc
; /* pc = eip + cs_base */
97 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
98 static state change (stop translation) */
99 /* current block context */
100 uint8_t *cs_base
; /* base of CS segment */
101 int code32
; /* 32 bit code segment */
102 int ss32
; /* 32 bit stack segment */
103 int cc_op
; /* current CC operation */
104 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
105 int f_st
; /* currently unused */
108 /* i386 arith/logic operations */
128 OP_SHL1
, /* undocumented */
133 #define DEF(s) INDEX_op_ ## s,
134 #include "opc-i386.h"
150 /* I386 int registers */
151 OR_EAX
, /* MUST be even numbered */
159 OR_TMP0
, /* temporary operand register */
161 OR_A0
, /* temporary register used when doing address evaluation */
162 OR_ZERO
, /* fixed zero register */
166 typedef void (GenOpFunc
)(void);
167 typedef void (GenOpFunc1
)(long);
168 typedef void (GenOpFunc2
)(long, long);
170 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
203 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
236 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
259 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
329 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
340 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
352 gen_op_addl_A0_EAX_s1
,
353 gen_op_addl_A0_ECX_s1
,
354 gen_op_addl_A0_EDX_s1
,
355 gen_op_addl_A0_EBX_s1
,
356 gen_op_addl_A0_ESP_s1
,
357 gen_op_addl_A0_EBP_s1
,
358 gen_op_addl_A0_ESI_s1
,
359 gen_op_addl_A0_EDI_s1
,
362 gen_op_addl_A0_EAX_s2
,
363 gen_op_addl_A0_ECX_s2
,
364 gen_op_addl_A0_EDX_s2
,
365 gen_op_addl_A0_EBX_s2
,
366 gen_op_addl_A0_ESP_s2
,
367 gen_op_addl_A0_EBP_s2
,
368 gen_op_addl_A0_ESI_s2
,
369 gen_op_addl_A0_EDI_s2
,
372 gen_op_addl_A0_EAX_s3
,
373 gen_op_addl_A0_ECX_s3
,
374 gen_op_addl_A0_EDX_s3
,
375 gen_op_addl_A0_EBX_s3
,
376 gen_op_addl_A0_ESP_s3
,
377 gen_op_addl_A0_EBP_s3
,
378 gen_op_addl_A0_ESI_s3
,
379 gen_op_addl_A0_EDI_s3
,
383 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
385 gen_op_cmovw_EAX_T1_T0
,
386 gen_op_cmovw_ECX_T1_T0
,
387 gen_op_cmovw_EDX_T1_T0
,
388 gen_op_cmovw_EBX_T1_T0
,
389 gen_op_cmovw_ESP_T1_T0
,
390 gen_op_cmovw_EBP_T1_T0
,
391 gen_op_cmovw_ESI_T1_T0
,
392 gen_op_cmovw_EDI_T1_T0
,
395 gen_op_cmovl_EAX_T1_T0
,
396 gen_op_cmovl_ECX_T1_T0
,
397 gen_op_cmovl_EDX_T1_T0
,
398 gen_op_cmovl_EBX_T1_T0
,
399 gen_op_cmovl_ESP_T1_T0
,
400 gen_op_cmovl_EBP_T1_T0
,
401 gen_op_cmovl_ESI_T1_T0
,
402 gen_op_cmovl_EDI_T1_T0
,
406 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
407 gen_op_addl_T0_T1_cc
,
411 gen_op_andl_T0_T1_cc
,
412 gen_op_subl_T0_T1_cc
,
413 gen_op_xorl_T0_T1_cc
,
414 gen_op_cmpl_T0_T1_cc
,
417 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
419 gen_op_adcb_T0_T1_cc
,
420 gen_op_sbbb_T0_T1_cc
,
423 gen_op_adcw_T0_T1_cc
,
424 gen_op_sbbw_T0_T1_cc
,
427 gen_op_adcl_T0_T1_cc
,
428 gen_op_sbbl_T0_T1_cc
,
432 static const int cc_op_arithb
[8] = {
443 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
444 gen_op_cmpxchgb_T0_T1_EAX_cc
,
445 gen_op_cmpxchgw_T0_T1_EAX_cc
,
446 gen_op_cmpxchgl_T0_T1_EAX_cc
,
449 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
451 gen_op_rolb_T0_T1_cc
,
452 gen_op_rorb_T0_T1_cc
,
453 gen_op_rclb_T0_T1_cc
,
454 gen_op_rcrb_T0_T1_cc
,
455 gen_op_shlb_T0_T1_cc
,
456 gen_op_shrb_T0_T1_cc
,
457 gen_op_shlb_T0_T1_cc
,
458 gen_op_sarb_T0_T1_cc
,
461 gen_op_rolw_T0_T1_cc
,
462 gen_op_rorw_T0_T1_cc
,
463 gen_op_rclw_T0_T1_cc
,
464 gen_op_rcrw_T0_T1_cc
,
465 gen_op_shlw_T0_T1_cc
,
466 gen_op_shrw_T0_T1_cc
,
467 gen_op_shlw_T0_T1_cc
,
468 gen_op_sarw_T0_T1_cc
,
471 gen_op_roll_T0_T1_cc
,
472 gen_op_rorl_T0_T1_cc
,
473 gen_op_rcll_T0_T1_cc
,
474 gen_op_rcrl_T0_T1_cc
,
475 gen_op_shll_T0_T1_cc
,
476 gen_op_shrl_T0_T1_cc
,
477 gen_op_shll_T0_T1_cc
,
478 gen_op_sarl_T0_T1_cc
,
482 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
484 gen_op_shldw_T0_T1_im_cc
,
485 gen_op_shrdw_T0_T1_im_cc
,
488 gen_op_shldl_T0_T1_im_cc
,
489 gen_op_shrdl_T0_T1_im_cc
,
493 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
495 gen_op_shldw_T0_T1_ECX_cc
,
496 gen_op_shrdw_T0_T1_ECX_cc
,
499 gen_op_shldl_T0_T1_ECX_cc
,
500 gen_op_shrdl_T0_T1_ECX_cc
,
504 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
507 gen_op_btsw_T0_T1_cc
,
508 gen_op_btrw_T0_T1_cc
,
509 gen_op_btcw_T0_T1_cc
,
513 gen_op_btsl_T0_T1_cc
,
514 gen_op_btrl_T0_T1_cc
,
515 gen_op_btcl_T0_T1_cc
,
519 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
530 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
535 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
540 /* sign does not matter */
541 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
547 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
553 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
559 static GenOpFunc
*gen_op_movs
[6] = {
568 static GenOpFunc
*gen_op_stos
[6] = {
577 static GenOpFunc
*gen_op_lods
[6] = {
586 static GenOpFunc
*gen_op_scas
[9] = {
598 static GenOpFunc
*gen_op_cmps
[9] = {
610 static GenOpFunc
*gen_op_ins
[6] = {
620 static GenOpFunc
*gen_op_outs
[6] = {
629 static GenOpFunc
*gen_op_in
[3] = {
635 static GenOpFunc
*gen_op_out
[3] = {
652 static GenOpFunc2
*gen_jcc_slow
[8] = {
663 static GenOpFunc2
*gen_jcc_sub
[3][8] = {
695 static GenOpFunc2
*gen_op_loop
[2][4] = {
710 static GenOpFunc
*gen_setcc_slow
[8] = {
721 static GenOpFunc
*gen_setcc_sub
[3][8] = {
726 gen_op_setbe_T0_subb
,
730 gen_op_setle_T0_subb
,
736 gen_op_setbe_T0_subw
,
740 gen_op_setle_T0_subw
,
746 gen_op_setbe_T0_subl
,
750 gen_op_setle_T0_subl
,
754 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
760 gen_op_fsubr_ST0_FT0
,
762 gen_op_fdivr_ST0_FT0
,
765 /* NOTE the exception in "r" op ordering */
766 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
771 gen_op_fsubr_STN_ST0
,
773 gen_op_fdivr_STN_ST0
,
777 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
780 gen_op_mov_TN_reg
[ot
][0][d
]();
782 gen_op_mov_TN_reg
[ot
][1][s
]();
783 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
784 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
785 gen_op_set_cc_op(s1
->cc_op
);
786 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
787 s1
->cc_op
= CC_OP_DYNAMIC
;
789 gen_op_arith_T0_T1_cc
[op
]();
790 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
792 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
793 gen_op_mov_reg_T0
[ot
][d
]();
796 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
798 gen_op_movl_T1_im(c
);
799 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
802 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
805 gen_op_mov_TN_reg
[ot
][0][d
]();
806 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
807 gen_op_set_cc_op(s1
->cc_op
);
810 s1
->cc_op
= CC_OP_INCB
+ ot
;
813 s1
->cc_op
= CC_OP_DECB
+ ot
;
816 gen_op_mov_reg_T0
[ot
][d
]();
819 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
822 gen_op_mov_TN_reg
[ot
][0][d
]();
824 gen_op_mov_TN_reg
[ot
][1][s
]();
825 /* for zero counts, flags are not updated, so must do it dynamically */
826 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
827 gen_op_set_cc_op(s1
->cc_op
);
829 gen_op_shift_T0_T1_cc
[ot
][op
]();
832 gen_op_mov_reg_T0
[ot
][d
]();
833 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
836 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
838 /* currently not optimized */
839 gen_op_movl_T1_im(c
);
840 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
843 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
850 int mod
, rm
, code
, override
, must_add_seg
;
852 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
854 must_add_seg
= s
->addseg
;
855 if (s
->prefix
& (PREFIX_CS
| PREFIX_SS
| PREFIX_DS
|
856 PREFIX_ES
| PREFIX_FS
| PREFIX_GS
)) {
857 if (s
->prefix
& PREFIX_ES
)
859 else if (s
->prefix
& PREFIX_CS
)
861 else if (s
->prefix
& PREFIX_SS
)
863 else if (s
->prefix
& PREFIX_DS
)
865 else if (s
->prefix
& PREFIX_FS
)
872 mod
= (modrm
>> 6) & 3;
884 code
= ldub(s
->pc
++);
885 scale
= (code
>> 6) & 3;
886 index
= (code
>> 3) & 7;
901 disp
= (int8_t)ldub(s
->pc
++);
911 gen_op_movl_A0_reg
[base
]();
913 gen_op_addl_A0_im(disp
);
915 gen_op_movl_A0_im(disp
);
917 if (havesib
&& (index
!= 4 || scale
!= 0)) {
918 gen_op_addl_A0_reg_sN
[scale
][index
]();
922 if (base
== R_EBP
|| base
== R_ESP
)
927 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
935 gen_op_movl_A0_im(disp
);
936 rm
= 0; /* avoid SS override */
943 disp
= (int8_t)ldub(s
->pc
++);
953 gen_op_movl_A0_reg
[R_EBX
]();
954 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
957 gen_op_movl_A0_reg
[R_EBX
]();
958 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
961 gen_op_movl_A0_reg
[R_EBP
]();
962 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
965 gen_op_movl_A0_reg
[R_EBP
]();
966 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
969 gen_op_movl_A0_reg
[R_ESI
]();
972 gen_op_movl_A0_reg
[R_EDI
]();
975 gen_op_movl_A0_reg
[R_EBP
]();
979 gen_op_movl_A0_reg
[R_EBX
]();
983 gen_op_addl_A0_im(disp
);
984 gen_op_andl_A0_ffff();
988 if (rm
== 2 || rm
== 3 || rm
== 6)
993 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
1003 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1005 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1007 int mod
, rm
, opreg
, disp
;
1009 mod
= (modrm
>> 6) & 3;
1014 gen_op_mov_TN_reg
[ot
][0][reg
]();
1015 gen_op_mov_reg_T0
[ot
][rm
]();
1017 gen_op_mov_TN_reg
[ot
][0][rm
]();
1019 gen_op_mov_reg_T0
[ot
][reg
]();
1022 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1025 gen_op_mov_TN_reg
[ot
][0][reg
]();
1026 gen_op_st_T0_A0
[ot
]();
1028 gen_op_ld_T0_A0
[ot
]();
1030 gen_op_mov_reg_T0
[ot
][reg
]();
1035 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1057 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1063 jcc_op
= (b
>> 1) & 7;
1065 /* we optimize the cmp/jcc case */
1069 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1074 /* some jumps are easy to compute */
1101 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1104 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1112 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1113 gen_op_set_cc_op(s
->cc_op
);
1114 func
= gen_jcc_slow
[jcc_op
];
1118 func(val
, next_eip
);
1120 func(next_eip
, val
);
1124 static void gen_setcc(DisasContext
*s
, int b
)
1130 jcc_op
= (b
>> 1) & 7;
1132 /* we optimize the cmp/jcc case */
1136 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1141 /* some jumps are easy to compute */
1159 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1162 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1170 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1171 gen_op_set_cc_op(s
->cc_op
);
1172 func
= gen_setcc_slow
[jcc_op
];
1181 /* move T0 to seg_reg and compute if the CPU state may change */
1182 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
)
1184 gen_op_movl_seg_T0(seg_reg
);
1185 if (!s
->addseg
&& seg_reg
< R_FS
)
1186 s
->is_jmp
= 2; /* abort translation because the register may
1187 have a non zero base */
1190 /* generate a push. It depends on ss32, addseg and dflag */
1191 static void gen_push_T0(DisasContext
*s
)
1201 gen_op_pushl_ss32_T0();
1203 gen_op_pushw_ss32_T0();
1207 gen_op_pushl_ss16_T0();
1209 gen_op_pushw_ss16_T0();
1213 /* two step pop is necessary for precise exceptions */
1214 static void gen_pop_T0(DisasContext
*s
)
1224 gen_op_popl_ss32_T0();
1226 gen_op_popw_ss32_T0();
1230 gen_op_popl_ss16_T0();
1232 gen_op_popw_ss16_T0();
1236 static void gen_pop_update(DisasContext
*s
)
1240 gen_op_addl_ESP_4();
1242 gen_op_addl_ESP_2();
1245 gen_op_addw_ESP_4();
1247 gen_op_addw_ESP_2();
1251 /* NOTE: wrap around in 16 bit not fully handled */
1252 static void gen_pusha(DisasContext
*s
)
1255 gen_op_movl_A0_ESP();
1256 gen_op_addl_A0_im(-16 << s
->dflag
);
1258 gen_op_andl_A0_ffff();
1259 gen_op_movl_T1_A0();
1261 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1262 for(i
= 0;i
< 8; i
++) {
1263 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1264 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1265 gen_op_addl_A0_im(2 << s
->dflag
);
1267 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1270 /* NOTE: wrap around in 16 bit not fully handled */
1271 static void gen_popa(DisasContext
*s
)
1274 gen_op_movl_A0_ESP();
1276 gen_op_andl_A0_ffff();
1277 gen_op_movl_T1_A0();
1278 gen_op_addl_T1_im(16 << s
->dflag
);
1280 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1281 for(i
= 0;i
< 8; i
++) {
1282 /* ESP is not reloaded */
1284 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1285 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1287 gen_op_addl_A0_im(2 << s
->dflag
);
1289 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1292 /* NOTE: wrap around in 16 bit not fully handled */
1293 /* XXX: check this */
1294 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1296 int ot
, level1
, addend
, opsize
;
1298 ot
= s
->dflag
+ OT_WORD
;
1301 opsize
= 2 << s
->dflag
;
1303 gen_op_movl_A0_ESP();
1304 gen_op_addl_A0_im(-opsize
);
1306 gen_op_andl_A0_ffff();
1307 gen_op_movl_T1_A0();
1309 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1311 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1312 gen_op_st_T0_A0
[ot
]();
1315 gen_op_addl_A0_im(-opsize
);
1316 gen_op_addl_T0_im(-opsize
);
1317 gen_op_st_T0_A0
[ot
]();
1319 gen_op_addl_A0_im(-opsize
);
1320 /* XXX: add st_T1_A0 ? */
1321 gen_op_movl_T0_T1();
1322 gen_op_st_T0_A0
[ot
]();
1324 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1325 addend
= -esp_addend
;
1327 addend
-= opsize
* (level1
+ 1);
1328 gen_op_addl_T1_im(addend
);
1329 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1332 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1333 is set to true if the instruction sets the PC (last instruction of
1335 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1337 int b
, prefixes
, aflag
, dflag
;
1339 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1340 unsigned int next_eip
;
1346 // cur_pc = s->pc; /* for insn generation */
1350 /* check prefixes */
1353 prefixes
|= PREFIX_REPZ
;
1356 prefixes
|= PREFIX_REPNZ
;
1359 prefixes
|= PREFIX_LOCK
;
1362 prefixes
|= PREFIX_CS
;
1365 prefixes
|= PREFIX_SS
;
1368 prefixes
|= PREFIX_DS
;
1371 prefixes
|= PREFIX_ES
;
1374 prefixes
|= PREFIX_FS
;
1377 prefixes
|= PREFIX_GS
;
1380 prefixes
|= PREFIX_DATA
;
1383 prefixes
|= PREFIX_ADR
;
1386 prefixes
|= PREFIX_FWAIT
;
1390 if (prefixes
& PREFIX_DATA
)
1392 if (prefixes
& PREFIX_ADR
)
1395 s
->prefix
= prefixes
;
1399 /* lock generation */
1400 if (prefixes
& PREFIX_LOCK
)
1403 /* now check op code */
1407 /**************************/
1408 /* extended op code */
1409 b
= ldub(s
->pc
++) | 0x100;
1412 /**************************/
1430 ot
= dflag
? OT_LONG
: OT_WORD
;
1433 case 0: /* OP Ev, Gv */
1434 modrm
= ldub(s
->pc
++);
1435 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1436 mod
= (modrm
>> 6) & 3;
1439 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1440 gen_op_ld_T0_A0
[ot
]();
1443 opreg
= OR_EAX
+ rm
;
1445 gen_op(s
, op
, ot
, opreg
, reg
);
1446 if (mod
!= 3 && op
!= 7) {
1447 gen_op_st_T0_A0
[ot
]();
1450 case 1: /* OP Gv, Ev */
1451 modrm
= ldub(s
->pc
++);
1452 mod
= (modrm
>> 6) & 3;
1453 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1456 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1457 gen_op_ld_T1_A0
[ot
]();
1460 opreg
= OR_EAX
+ rm
;
1462 gen_op(s
, op
, ot
, reg
, opreg
);
1464 case 2: /* OP A, Iv */
1465 val
= insn_get(s
, ot
);
1466 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1472 case 0x80: /* GRP1 */
1481 ot
= dflag
? OT_LONG
: OT_WORD
;
1483 modrm
= ldub(s
->pc
++);
1484 mod
= (modrm
>> 6) & 3;
1486 op
= (modrm
>> 3) & 7;
1489 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1490 gen_op_ld_T0_A0
[ot
]();
1493 opreg
= rm
+ OR_EAX
;
1500 val
= insn_get(s
, ot
);
1503 val
= (int8_t)insn_get(s
, OT_BYTE
);
1507 gen_opi(s
, op
, ot
, opreg
, val
);
1508 if (op
!= 7 && mod
!= 3) {
1509 gen_op_st_T0_A0
[ot
]();
1514 /**************************/
1515 /* inc, dec, and other misc arith */
1516 case 0x40 ... 0x47: /* inc Gv */
1517 ot
= dflag
? OT_LONG
: OT_WORD
;
1518 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1520 case 0x48 ... 0x4f: /* dec Gv */
1521 ot
= dflag
? OT_LONG
: OT_WORD
;
1522 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1524 case 0xf6: /* GRP3 */
1529 ot
= dflag
? OT_LONG
: OT_WORD
;
1531 modrm
= ldub(s
->pc
++);
1532 mod
= (modrm
>> 6) & 3;
1534 op
= (modrm
>> 3) & 7;
1536 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1537 gen_op_ld_T0_A0
[ot
]();
1539 gen_op_mov_TN_reg
[ot
][0][rm
]();
1544 val
= insn_get(s
, ot
);
1545 gen_op_movl_T1_im(val
);
1546 gen_op_testl_T0_T1_cc();
1547 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1552 gen_op_st_T0_A0
[ot
]();
1554 gen_op_mov_reg_T0
[ot
][rm
]();
1558 gen_op_negl_T0_cc();
1560 gen_op_st_T0_A0
[ot
]();
1562 gen_op_mov_reg_T0
[ot
][rm
]();
1564 s
->cc_op
= CC_OP_SUBB
+ ot
;
1569 gen_op_mulb_AL_T0();
1572 gen_op_mulw_AX_T0();
1576 gen_op_mull_EAX_T0();
1579 s
->cc_op
= CC_OP_MUL
;
1584 gen_op_imulb_AL_T0();
1587 gen_op_imulw_AX_T0();
1591 gen_op_imull_EAX_T0();
1594 s
->cc_op
= CC_OP_MUL
;
1599 gen_op_divb_AL_T0();
1602 gen_op_divw_AX_T0();
1606 gen_op_divl_EAX_T0();
1613 gen_op_idivb_AL_T0();
1616 gen_op_idivw_AX_T0();
1620 gen_op_idivl_EAX_T0();
1629 case 0xfe: /* GRP4 */
1630 case 0xff: /* GRP5 */
1634 ot
= dflag
? OT_LONG
: OT_WORD
;
1636 modrm
= ldub(s
->pc
++);
1637 mod
= (modrm
>> 6) & 3;
1639 op
= (modrm
>> 3) & 7;
1640 if (op
>= 2 && b
== 0xfe) {
1644 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1645 if (op
!= 3 && op
!= 5)
1646 gen_op_ld_T0_A0
[ot
]();
1648 gen_op_mov_TN_reg
[ot
][0][rm
]();
1652 case 0: /* inc Ev */
1653 gen_inc(s
, ot
, OR_TMP0
, 1);
1655 gen_op_st_T0_A0
[ot
]();
1657 gen_op_mov_reg_T0
[ot
][rm
]();
1659 case 1: /* dec Ev */
1660 gen_inc(s
, ot
, OR_TMP0
, -1);
1662 gen_op_st_T0_A0
[ot
]();
1664 gen_op_mov_reg_T0
[ot
][rm
]();
1666 case 2: /* call Ev */
1667 /* XXX: optimize if memory (no and is necessary) */
1669 gen_op_andl_T0_ffff();
1671 next_eip
= s
->pc
- s
->cs_base
;
1672 gen_op_movl_T0_im(next_eip
);
1676 case 3: /* lcall Ev */
1677 /* push return segment + offset */
1678 gen_op_movl_T0_seg(R_CS
);
1680 next_eip
= s
->pc
- s
->cs_base
;
1681 gen_op_movl_T0_im(next_eip
);
1684 gen_op_ld_T1_A0
[ot
]();
1685 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1686 gen_op_lduw_T0_A0();
1687 gen_movl_seg_T0(s
, R_CS
);
1688 gen_op_movl_T0_T1();
1692 case 4: /* jmp Ev */
1694 gen_op_andl_T0_ffff();
1698 case 5: /* ljmp Ev */
1699 gen_op_ld_T1_A0
[ot
]();
1700 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1701 gen_op_lduw_T0_A0();
1702 gen_movl_seg_T0(s
, R_CS
);
1703 gen_op_movl_T0_T1();
1707 case 6: /* push Ev */
1715 case 0x84: /* test Ev, Gv */
1720 ot
= dflag
? OT_LONG
: OT_WORD
;
1722 modrm
= ldub(s
->pc
++);
1723 mod
= (modrm
>> 6) & 3;
1725 reg
= (modrm
>> 3) & 7;
1727 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1728 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1729 gen_op_testl_T0_T1_cc();
1730 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1733 case 0xa8: /* test eAX, Iv */
1738 ot
= dflag
? OT_LONG
: OT_WORD
;
1739 val
= insn_get(s
, ot
);
1741 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1742 gen_op_movl_T1_im(val
);
1743 gen_op_testl_T0_T1_cc();
1744 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1747 case 0x98: /* CWDE/CBW */
1749 gen_op_movswl_EAX_AX();
1751 gen_op_movsbw_AX_AL();
1753 case 0x99: /* CDQ/CWD */
1755 gen_op_movslq_EDX_EAX();
1757 gen_op_movswl_DX_AX();
1759 case 0x1af: /* imul Gv, Ev */
1760 case 0x69: /* imul Gv, Ev, I */
1762 ot
= dflag
? OT_LONG
: OT_WORD
;
1763 modrm
= ldub(s
->pc
++);
1764 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1765 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1767 val
= insn_get(s
, ot
);
1768 gen_op_movl_T1_im(val
);
1769 } else if (b
== 0x6b) {
1770 val
= insn_get(s
, OT_BYTE
);
1771 gen_op_movl_T1_im(val
);
1773 gen_op_mov_TN_reg
[ot
][1][reg
]();
1776 if (ot
== OT_LONG
) {
1777 gen_op_imull_T0_T1();
1779 gen_op_imulw_T0_T1();
1781 gen_op_mov_reg_T0
[ot
][reg
]();
1782 s
->cc_op
= CC_OP_MUL
;
1785 case 0x1c1: /* xadd Ev, Gv */
1789 ot
= dflag
? OT_LONG
: OT_WORD
;
1790 modrm
= ldub(s
->pc
++);
1791 reg
= (modrm
>> 3) & 7;
1792 mod
= (modrm
>> 6) & 3;
1795 gen_op_mov_TN_reg
[ot
][0][reg
]();
1796 gen_op_mov_TN_reg
[ot
][1][rm
]();
1797 gen_op_addl_T0_T1_cc();
1798 gen_op_mov_reg_T0
[ot
][rm
]();
1799 gen_op_mov_reg_T1
[ot
][reg
]();
1801 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1802 gen_op_mov_TN_reg
[ot
][0][reg
]();
1803 gen_op_ld_T1_A0
[ot
]();
1804 gen_op_addl_T0_T1_cc();
1805 gen_op_st_T0_A0
[ot
]();
1806 gen_op_mov_reg_T1
[ot
][reg
]();
1808 s
->cc_op
= CC_OP_ADDB
+ ot
;
1811 case 0x1b1: /* cmpxchg Ev, Gv */
1815 ot
= dflag
? OT_LONG
: OT_WORD
;
1816 modrm
= ldub(s
->pc
++);
1817 reg
= (modrm
>> 3) & 7;
1818 mod
= (modrm
>> 6) & 3;
1819 gen_op_mov_TN_reg
[ot
][1][reg
]();
1822 gen_op_mov_TN_reg
[ot
][0][rm
]();
1823 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1824 gen_op_mov_reg_T0
[ot
][rm
]();
1826 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1827 gen_op_ld_T0_A0
[ot
]();
1828 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1829 gen_op_st_T0_A0
[ot
]();
1831 s
->cc_op
= CC_OP_SUBB
+ ot
;
1834 /**************************/
1836 case 0x50 ... 0x57: /* push */
1837 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1840 case 0x58 ... 0x5f: /* pop */
1841 ot
= dflag
? OT_LONG
: OT_WORD
;
1843 gen_op_mov_reg_T0
[ot
][b
& 7]();
1846 case 0x60: /* pusha */
1849 case 0x61: /* popa */
1852 case 0x68: /* push Iv */
1854 ot
= dflag
? OT_LONG
: OT_WORD
;
1856 val
= insn_get(s
, ot
);
1858 val
= (int8_t)insn_get(s
, OT_BYTE
);
1859 gen_op_movl_T0_im(val
);
1862 case 0x8f: /* pop Ev */
1863 ot
= dflag
? OT_LONG
: OT_WORD
;
1864 modrm
= ldub(s
->pc
++);
1866 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1869 case 0xc8: /* enter */
1874 level
= ldub(s
->pc
++);
1875 gen_enter(s
, val
, level
);
1878 case 0xc9: /* leave */
1879 /* XXX: exception not precise (ESP is update before potential exception) */
1881 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1882 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1884 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1885 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1888 ot
= dflag
? OT_LONG
: OT_WORD
;
1889 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1892 case 0x06: /* push es */
1893 case 0x0e: /* push cs */
1894 case 0x16: /* push ss */
1895 case 0x1e: /* push ds */
1896 gen_op_movl_T0_seg(b
>> 3);
1899 case 0x1a0: /* push fs */
1900 case 0x1a8: /* push gs */
1901 gen_op_movl_T0_seg(((b
>> 3) & 7) + R_FS
);
1904 case 0x07: /* pop es */
1905 case 0x17: /* pop ss */
1906 case 0x1f: /* pop ds */
1908 gen_movl_seg_T0(s
, b
>> 3);
1911 case 0x1a1: /* pop fs */
1912 case 0x1a9: /* pop gs */
1914 gen_movl_seg_T0(s
, ((b
>> 3) & 7) + R_FS
);
1918 /**************************/
1921 case 0x89: /* mov Gv, Ev */
1925 ot
= dflag
? OT_LONG
: OT_WORD
;
1926 modrm
= ldub(s
->pc
++);
1927 reg
= (modrm
>> 3) & 7;
1929 /* generate a generic store */
1930 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
1933 case 0xc7: /* mov Ev, Iv */
1937 ot
= dflag
? OT_LONG
: OT_WORD
;
1938 modrm
= ldub(s
->pc
++);
1939 mod
= (modrm
>> 6) & 3;
1941 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1942 val
= insn_get(s
, ot
);
1943 gen_op_movl_T0_im(val
);
1945 gen_op_st_T0_A0
[ot
]();
1947 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
1950 case 0x8b: /* mov Ev, Gv */
1954 ot
= dflag
? OT_LONG
: OT_WORD
;
1955 modrm
= ldub(s
->pc
++);
1956 reg
= (modrm
>> 3) & 7;
1958 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1959 gen_op_mov_reg_T0
[ot
][reg
]();
1961 case 0x8e: /* mov seg, Gv */
1962 ot
= dflag
? OT_LONG
: OT_WORD
;
1963 modrm
= ldub(s
->pc
++);
1964 reg
= (modrm
>> 3) & 7;
1965 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1966 if (reg
>= 6 || reg
== R_CS
)
1968 gen_movl_seg_T0(s
, reg
);
1970 case 0x8c: /* mov Gv, seg */
1971 ot
= dflag
? OT_LONG
: OT_WORD
;
1972 modrm
= ldub(s
->pc
++);
1973 reg
= (modrm
>> 3) & 7;
1976 gen_op_movl_T0_seg(reg
);
1977 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1980 case 0x1b6: /* movzbS Gv, Eb */
1981 case 0x1b7: /* movzwS Gv, Eb */
1982 case 0x1be: /* movsbS Gv, Eb */
1983 case 0x1bf: /* movswS Gv, Eb */
1986 /* d_ot is the size of destination */
1987 d_ot
= dflag
+ OT_WORD
;
1988 /* ot is the size of source */
1989 ot
= (b
& 1) + OT_BYTE
;
1990 modrm
= ldub(s
->pc
++);
1991 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1992 mod
= (modrm
>> 6) & 3;
1996 gen_op_mov_TN_reg
[ot
][0][rm
]();
1997 switch(ot
| (b
& 8)) {
1999 gen_op_movzbl_T0_T0();
2002 gen_op_movsbl_T0_T0();
2005 gen_op_movzwl_T0_T0();
2009 gen_op_movswl_T0_T0();
2012 gen_op_mov_reg_T0
[d_ot
][reg
]();
2014 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2016 gen_op_lds_T0_A0
[ot
]();
2018 gen_op_ldu_T0_A0
[ot
]();
2020 gen_op_mov_reg_T0
[d_ot
][reg
]();
2025 case 0x8d: /* lea */
2026 ot
= dflag
? OT_LONG
: OT_WORD
;
2027 modrm
= ldub(s
->pc
++);
2028 reg
= (modrm
>> 3) & 7;
2029 /* we must ensure that no segment is added */
2030 s
->prefix
&= ~(PREFIX_CS
| PREFIX_SS
| PREFIX_DS
|
2031 PREFIX_ES
| PREFIX_FS
| PREFIX_GS
);
2034 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2036 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2039 case 0xa0: /* mov EAX, Ov */
2041 case 0xa2: /* mov Ov, EAX */
2046 ot
= dflag
? OT_LONG
: OT_WORD
;
2048 offset_addr
= insn_get(s
, OT_LONG
);
2050 offset_addr
= insn_get(s
, OT_WORD
);
2051 gen_op_movl_A0_im(offset_addr
);
2052 /* handle override */
2053 /* XXX: factorize that */
2055 int override
, must_add_seg
;
2057 must_add_seg
= s
->addseg
;
2058 if (s
->prefix
& (PREFIX_CS
| PREFIX_SS
| PREFIX_DS
|
2059 PREFIX_ES
| PREFIX_FS
| PREFIX_GS
)) {
2060 if (s
->prefix
& PREFIX_ES
)
2062 else if (s
->prefix
& PREFIX_CS
)
2064 else if (s
->prefix
& PREFIX_SS
)
2066 else if (s
->prefix
& PREFIX_DS
)
2068 else if (s
->prefix
& PREFIX_FS
)
2075 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2079 gen_op_ld_T0_A0
[ot
]();
2080 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2082 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2083 gen_op_st_T0_A0
[ot
]();
2087 case 0xb0 ... 0xb7: /* mov R, Ib */
2088 val
= insn_get(s
, OT_BYTE
);
2089 gen_op_movl_T0_im(val
);
2090 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2092 case 0xb8 ... 0xbf: /* mov R, Iv */
2093 ot
= dflag
? OT_LONG
: OT_WORD
;
2094 val
= insn_get(s
, ot
);
2095 reg
= OR_EAX
+ (b
& 7);
2096 gen_op_movl_T0_im(val
);
2097 gen_op_mov_reg_T0
[ot
][reg
]();
2100 case 0x91 ... 0x97: /* xchg R, EAX */
2101 ot
= dflag
? OT_LONG
: OT_WORD
;
2106 case 0x87: /* xchg Ev, Gv */
2110 ot
= dflag
? OT_LONG
: OT_WORD
;
2111 modrm
= ldub(s
->pc
++);
2112 reg
= (modrm
>> 3) & 7;
2113 mod
= (modrm
>> 6) & 3;
2117 gen_op_mov_TN_reg
[ot
][0][reg
]();
2118 gen_op_mov_TN_reg
[ot
][1][rm
]();
2119 gen_op_mov_reg_T0
[ot
][rm
]();
2120 gen_op_mov_reg_T1
[ot
][reg
]();
2122 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2123 gen_op_mov_TN_reg
[ot
][0][reg
]();
2124 gen_op_ld_T1_A0
[ot
]();
2125 gen_op_st_T0_A0
[ot
]();
2126 gen_op_mov_reg_T1
[ot
][reg
]();
2129 case 0xc4: /* les Gv */
2132 case 0xc5: /* lds Gv */
2135 case 0x1b2: /* lss Gv */
2138 case 0x1b4: /* lfs Gv */
2141 case 0x1b5: /* lgs Gv */
2144 ot
= dflag
? OT_LONG
: OT_WORD
;
2145 modrm
= ldub(s
->pc
++);
2146 reg
= (modrm
>> 3) & 7;
2147 mod
= (modrm
>> 6) & 3;
2150 gen_op_ld_T1_A0
[ot
]();
2151 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2152 /* load the segment first to handle exceptions properly */
2153 gen_op_lduw_T0_A0();
2154 gen_movl_seg_T0(s
, op
);
2155 /* then put the data */
2156 gen_op_mov_reg_T1
[ot
][reg
]();
2159 /************************/
2170 ot
= dflag
? OT_LONG
: OT_WORD
;
2172 modrm
= ldub(s
->pc
++);
2173 mod
= (modrm
>> 6) & 3;
2175 op
= (modrm
>> 3) & 7;
2178 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2179 gen_op_ld_T0_A0
[ot
]();
2182 opreg
= rm
+ OR_EAX
;
2187 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2190 shift
= ldub(s
->pc
++);
2192 gen_shifti(s
, op
, ot
, opreg
, shift
);
2196 gen_op_st_T0_A0
[ot
]();
2211 case 0x1a4: /* shld imm */
2215 case 0x1a5: /* shld cl */
2219 case 0x1ac: /* shrd imm */
2223 case 0x1ad: /* shrd cl */
2227 ot
= dflag
? OT_LONG
: OT_WORD
;
2228 modrm
= ldub(s
->pc
++);
2229 mod
= (modrm
>> 6) & 3;
2231 reg
= (modrm
>> 3) & 7;
2234 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2235 gen_op_ld_T0_A0
[ot
]();
2237 gen_op_mov_TN_reg
[ot
][0][rm
]();
2239 gen_op_mov_TN_reg
[ot
][1][reg
]();
2242 val
= ldub(s
->pc
++);
2245 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2246 if (op
== 0 && ot
!= OT_WORD
)
2247 s
->cc_op
= CC_OP_SHLB
+ ot
;
2249 s
->cc_op
= CC_OP_SARB
+ ot
;
2252 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2253 gen_op_set_cc_op(s
->cc_op
);
2254 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2255 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2258 gen_op_st_T0_A0
[ot
]();
2260 gen_op_mov_reg_T0
[ot
][rm
]();
2264 /************************/
2267 modrm
= ldub(s
->pc
++);
2268 mod
= (modrm
>> 6) & 3;
2270 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2274 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2276 case 0x00 ... 0x07: /* fxxxs */
2277 case 0x10 ... 0x17: /* fixxxl */
2278 case 0x20 ... 0x27: /* fxxxl */
2279 case 0x30 ... 0x37: /* fixxx */
2286 gen_op_flds_FT0_A0();
2289 gen_op_fildl_FT0_A0();
2292 gen_op_fldl_FT0_A0();
2296 gen_op_fild_FT0_A0();
2300 gen_op_fp_arith_ST0_FT0
[op1
]();
2302 /* fcomp needs pop */
2307 case 0x08: /* flds */
2308 case 0x0a: /* fsts */
2309 case 0x0b: /* fstps */
2310 case 0x18: /* fildl */
2311 case 0x1a: /* fistl */
2312 case 0x1b: /* fistpl */
2313 case 0x28: /* fldl */
2314 case 0x2a: /* fstl */
2315 case 0x2b: /* fstpl */
2316 case 0x38: /* filds */
2317 case 0x3a: /* fists */
2318 case 0x3b: /* fistps */
2325 gen_op_flds_ST0_A0();
2328 gen_op_fildl_ST0_A0();
2331 gen_op_fldl_ST0_A0();
2335 gen_op_fild_ST0_A0();
2342 gen_op_fsts_ST0_A0();
2345 gen_op_fistl_ST0_A0();
2348 gen_op_fstl_ST0_A0();
2352 gen_op_fist_ST0_A0();
2360 case 0x0d: /* fldcw mem */
2363 case 0x0f: /* fnstcw mem */
2366 case 0x1d: /* fldt mem */
2368 gen_op_fldt_ST0_A0();
2370 case 0x1f: /* fstpt mem */
2371 gen_op_fstt_ST0_A0();
2374 case 0x2f: /* fnstsw mem */
2377 case 0x3c: /* fbld */
2379 gen_op_fbld_ST0_A0();
2381 case 0x3e: /* fbstp */
2382 gen_op_fbst_ST0_A0();
2385 case 0x3d: /* fildll */
2387 gen_op_fildll_ST0_A0();
2389 case 0x3f: /* fistpll */
2390 gen_op_fistll_ST0_A0();
2397 /* register float ops */
2401 case 0x08: /* fld sti */
2403 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2405 case 0x09: /* fxchg sti */
2406 gen_op_fxchg_ST0_STN(opreg
);
2408 case 0x0a: /* grp d9/2 */
2416 case 0x0c: /* grp d9/4 */
2426 gen_op_fcom_ST0_FT0();
2435 case 0x0d: /* grp d9/5 */
2444 gen_op_fldl2t_ST0();
2448 gen_op_fldl2e_ST0();
2456 gen_op_fldlg2_ST0();
2460 gen_op_fldln2_ST0();
2471 case 0x0e: /* grp d9/6 */
2482 case 3: /* fpatan */
2485 case 4: /* fxtract */
2488 case 5: /* fprem1 */
2491 case 6: /* fdecstp */
2495 case 7: /* fincstp */
2500 case 0x0f: /* grp d9/7 */
2505 case 1: /* fyl2xp1 */
2511 case 3: /* fsincos */
2514 case 5: /* fscale */
2517 case 4: /* frndint */
2529 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2530 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2531 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2537 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2541 gen_op_fmov_FT0_STN(opreg
);
2542 gen_op_fp_arith_ST0_FT0
[op1
]();
2546 case 0x02: /* fcom */
2547 gen_op_fmov_FT0_STN(opreg
);
2548 gen_op_fcom_ST0_FT0();
2550 case 0x03: /* fcomp */
2551 gen_op_fmov_FT0_STN(opreg
);
2552 gen_op_fcom_ST0_FT0();
2555 case 0x15: /* da/5 */
2557 case 1: /* fucompp */
2558 gen_op_fmov_FT0_STN(1);
2559 gen_op_fucom_ST0_FT0();
2572 case 3: /* fninit */
2579 case 0x2a: /* fst sti */
2580 gen_op_fmov_STN_ST0(opreg
);
2582 case 0x2b: /* fstp sti */
2583 gen_op_fmov_STN_ST0(opreg
);
2586 case 0x2c: /* fucom st(i) */
2587 gen_op_fmov_FT0_STN(opreg
);
2588 gen_op_fucom_ST0_FT0();
2590 case 0x2d: /* fucomp st(i) */
2591 gen_op_fmov_FT0_STN(opreg
);
2592 gen_op_fucom_ST0_FT0();
2595 case 0x33: /* de/3 */
2597 case 1: /* fcompp */
2598 gen_op_fmov_FT0_STN(1);
2599 gen_op_fcom_ST0_FT0();
2607 case 0x3c: /* df/4 */
2610 gen_op_fnstsw_EAX();
2621 /************************/
2623 case 0xa4: /* movsS */
2628 ot
= dflag
? OT_LONG
: OT_WORD
;
2629 if (prefixes
& PREFIX_REPZ
) {
2630 gen_op_movs
[3 + ot
]();
2636 case 0xaa: /* stosS */
2641 ot
= dflag
? OT_LONG
: OT_WORD
;
2642 if (prefixes
& PREFIX_REPZ
) {
2643 gen_op_stos
[3 + ot
]();
2648 case 0xac: /* lodsS */
2653 ot
= dflag
? OT_LONG
: OT_WORD
;
2654 if (prefixes
& PREFIX_REPZ
) {
2655 gen_op_lods
[3 + ot
]();
2660 case 0xae: /* scasS */
2665 ot
= dflag
? OT_LONG
: OT_WORD
;
2666 if (prefixes
& PREFIX_REPNZ
) {
2667 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2668 gen_op_set_cc_op(s
->cc_op
);
2669 gen_op_scas
[6 + ot
]();
2670 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2671 } else if (prefixes
& PREFIX_REPZ
) {
2672 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2673 gen_op_set_cc_op(s
->cc_op
);
2674 gen_op_scas
[3 + ot
]();
2675 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2678 s
->cc_op
= CC_OP_SUBB
+ ot
;
2682 case 0xa6: /* cmpsS */
2687 ot
= dflag
? OT_LONG
: OT_WORD
;
2688 if (prefixes
& PREFIX_REPNZ
) {
2689 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2690 gen_op_set_cc_op(s
->cc_op
);
2691 gen_op_cmps
[6 + ot
]();
2692 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2693 } else if (prefixes
& PREFIX_REPZ
) {
2694 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2695 gen_op_set_cc_op(s
->cc_op
);
2696 gen_op_cmps
[3 + ot
]();
2697 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2700 s
->cc_op
= CC_OP_SUBB
+ ot
;
2704 /************************/
2706 case 0x6c: /* insS */
2711 ot
= dflag
? OT_LONG
: OT_WORD
;
2712 if (prefixes
& PREFIX_REPZ
) {
2713 gen_op_ins
[3 + ot
]();
2718 case 0x6e: /* outsS */
2723 ot
= dflag
? OT_LONG
: OT_WORD
;
2724 if (prefixes
& PREFIX_REPZ
) {
2725 gen_op_outs
[3 + ot
]();
2735 ot
= dflag
? OT_LONG
: OT_WORD
;
2736 val
= ldub(s
->pc
++);
2737 gen_op_movl_T0_im(val
);
2739 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2746 ot
= dflag
? OT_LONG
: OT_WORD
;
2747 val
= ldub(s
->pc
++);
2748 gen_op_movl_T0_im(val
);
2749 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2757 ot
= dflag
? OT_LONG
: OT_WORD
;
2758 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2760 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2767 ot
= dflag
? OT_LONG
: OT_WORD
;
2768 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2769 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2773 /************************/
2775 case 0xc2: /* ret im */
2780 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2782 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2784 gen_op_andl_T0_ffff();
2788 case 0xc3: /* ret */
2792 gen_op_andl_T0_ffff();
2796 case 0xca: /* lret im */
2802 gen_op_andl_T0_ffff();
2807 gen_movl_seg_T0(s
, R_CS
);
2809 /* add stack offset */
2811 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2813 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2816 case 0xcb: /* lret */
2820 gen_op_andl_T0_ffff();
2825 gen_movl_seg_T0(s
, R_CS
);
2829 case 0xe8: /* call im */
2831 unsigned int next_eip
;
2832 ot
= dflag
? OT_LONG
: OT_WORD
;
2833 val
= insn_get(s
, ot
);
2834 next_eip
= s
->pc
- s
->cs_base
;
2838 gen_op_movl_T0_im(next_eip
);
2844 case 0x9a: /* lcall im */
2846 unsigned int selector
, offset
;
2848 ot
= dflag
? OT_LONG
: OT_WORD
;
2849 offset
= insn_get(s
, ot
);
2850 selector
= insn_get(s
, OT_WORD
);
2852 /* push return segment + offset */
2853 gen_op_movl_T0_seg(R_CS
);
2855 next_eip
= s
->pc
- s
->cs_base
;
2856 gen_op_movl_T0_im(next_eip
);
2859 /* change cs and pc */
2860 gen_op_movl_T0_im(selector
);
2861 gen_movl_seg_T0(s
, R_CS
);
2862 gen_op_jmp_im((unsigned long)offset
);
2866 case 0xe9: /* jmp */
2867 ot
= dflag
? OT_LONG
: OT_WORD
;
2868 val
= insn_get(s
, ot
);
2869 val
+= s
->pc
- s
->cs_base
;
2875 case 0xea: /* ljmp im */
2877 unsigned int selector
, offset
;
2879 ot
= dflag
? OT_LONG
: OT_WORD
;
2880 offset
= insn_get(s
, ot
);
2881 selector
= insn_get(s
, OT_WORD
);
2883 /* change cs and pc */
2884 gen_op_movl_T0_im(selector
);
2885 gen_movl_seg_T0(s
, R_CS
);
2886 gen_op_jmp_im((unsigned long)offset
);
2890 case 0xeb: /* jmp Jb */
2891 val
= (int8_t)insn_get(s
, OT_BYTE
);
2892 val
+= s
->pc
- s
->cs_base
;
2898 case 0x70 ... 0x7f: /* jcc Jb */
2899 val
= (int8_t)insn_get(s
, OT_BYTE
);
2901 case 0x180 ... 0x18f: /* jcc Jv */
2903 val
= insn_get(s
, OT_LONG
);
2905 val
= (int16_t)insn_get(s
, OT_WORD
);
2908 next_eip
= s
->pc
- s
->cs_base
;
2912 gen_jcc(s
, b
, val
, next_eip
);
2916 case 0x190 ... 0x19f: /* setcc Gv */
2917 modrm
= ldub(s
->pc
++);
2919 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
2921 case 0x140 ... 0x14f: /* cmov Gv, Ev */
2922 ot
= dflag
? OT_LONG
: OT_WORD
;
2923 modrm
= ldub(s
->pc
++);
2924 reg
= (modrm
>> 3) & 7;
2925 mod
= (modrm
>> 6) & 3;
2928 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2929 gen_op_ld_T1_A0
[ot
]();
2932 gen_op_mov_TN_reg
[ot
][1][rm
]();
2934 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
2937 /************************/
2939 case 0x9c: /* pushf */
2940 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2941 gen_op_set_cc_op(s
->cc_op
);
2942 gen_op_movl_T0_eflags();
2945 case 0x9d: /* popf */
2947 gen_op_movl_eflags_T0();
2949 s
->cc_op
= CC_OP_EFLAGS
;
2951 case 0x9e: /* sahf */
2952 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
2953 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2954 gen_op_set_cc_op(s
->cc_op
);
2955 gen_op_movb_eflags_T0();
2956 s
->cc_op
= CC_OP_EFLAGS
;
2958 case 0x9f: /* lahf */
2959 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2960 gen_op_set_cc_op(s
->cc_op
);
2961 gen_op_movl_T0_eflags();
2962 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
2964 case 0xf5: /* cmc */
2965 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2966 gen_op_set_cc_op(s
->cc_op
);
2968 s
->cc_op
= CC_OP_EFLAGS
;
2970 case 0xf8: /* clc */
2971 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2972 gen_op_set_cc_op(s
->cc_op
);
2974 s
->cc_op
= CC_OP_EFLAGS
;
2976 case 0xf9: /* stc */
2977 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2978 gen_op_set_cc_op(s
->cc_op
);
2980 s
->cc_op
= CC_OP_EFLAGS
;
2982 case 0xfc: /* cld */
2985 case 0xfd: /* std */
2989 /************************/
2990 /* bit operations */
2991 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2992 ot
= dflag
? OT_LONG
: OT_WORD
;
2993 modrm
= ldub(s
->pc
++);
2994 op
= (modrm
>> 3) & 7;
2995 mod
= (modrm
>> 6) & 3;
2998 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2999 gen_op_ld_T0_A0
[ot
]();
3001 gen_op_mov_TN_reg
[ot
][0][rm
]();
3004 val
= ldub(s
->pc
++);
3005 gen_op_movl_T1_im(val
);
3009 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3010 s
->cc_op
= CC_OP_SARB
+ ot
;
3013 gen_op_st_T0_A0
[ot
]();
3015 gen_op_mov_reg_T0
[ot
][rm
]();
3018 case 0x1a3: /* bt Gv, Ev */
3021 case 0x1ab: /* bts */
3024 case 0x1b3: /* btr */
3027 case 0x1bb: /* btc */
3030 ot
= dflag
? OT_LONG
: OT_WORD
;
3031 modrm
= ldub(s
->pc
++);
3032 reg
= (modrm
>> 3) & 7;
3033 mod
= (modrm
>> 6) & 3;
3035 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3037 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3038 /* specific case: we need to add a displacement */
3040 gen_op_add_bitw_A0_T1();
3042 gen_op_add_bitl_A0_T1();
3043 gen_op_ld_T0_A0
[ot
]();
3045 gen_op_mov_TN_reg
[ot
][0][rm
]();
3047 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3048 s
->cc_op
= CC_OP_SARB
+ ot
;
3051 gen_op_st_T0_A0
[ot
]();
3053 gen_op_mov_reg_T0
[ot
][rm
]();
3056 case 0x1bc: /* bsf */
3057 case 0x1bd: /* bsr */
3058 ot
= dflag
? OT_LONG
: OT_WORD
;
3059 modrm
= ldub(s
->pc
++);
3060 reg
= (modrm
>> 3) & 7;
3061 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3062 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3063 /* NOTE: we always write back the result. Intel doc says it is
3064 undefined if T0 == 0 */
3065 gen_op_mov_reg_T0
[ot
][reg
]();
3066 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3068 /************************/
3070 case 0x27: /* daa */
3071 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3072 gen_op_set_cc_op(s
->cc_op
);
3074 s
->cc_op
= CC_OP_EFLAGS
;
3076 case 0x2f: /* das */
3077 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3078 gen_op_set_cc_op(s
->cc_op
);
3080 s
->cc_op
= CC_OP_EFLAGS
;
3082 case 0x37: /* aaa */
3083 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3084 gen_op_set_cc_op(s
->cc_op
);
3086 s
->cc_op
= CC_OP_EFLAGS
;
3088 case 0x3f: /* aas */
3089 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3090 gen_op_set_cc_op(s
->cc_op
);
3092 s
->cc_op
= CC_OP_EFLAGS
;
3094 case 0xd4: /* aam */
3095 val
= ldub(s
->pc
++);
3097 s
->cc_op
= CC_OP_LOGICB
;
3099 case 0xd5: /* aad */
3100 val
= ldub(s
->pc
++);
3102 s
->cc_op
= CC_OP_LOGICB
;
3104 /************************/
3106 case 0x90: /* nop */
3108 case 0xcc: /* int3 */
3109 gen_op_int3((long)pc_start
);
3112 case 0xcd: /* int N */
3113 val
= ldub(s
->pc
++);
3114 /* XXX: currently we ignore the interrupt number */
3115 gen_op_int_im((long)pc_start
);
3118 case 0xce: /* into */
3119 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3120 gen_op_set_cc_op(s
->cc_op
);
3121 gen_op_into((long)pc_start
, (long)s
->pc
);
3124 case 0x1c8 ... 0x1cf: /* bswap reg */
3126 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3128 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3130 case 0xd6: /* salc */
3131 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3132 gen_op_set_cc_op(s
->cc_op
);
3135 case 0xe0: /* loopnz */
3136 case 0xe1: /* loopz */
3137 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3138 gen_op_set_cc_op(s
->cc_op
);
3140 case 0xe2: /* loop */
3141 case 0xe3: /* jecxz */
3142 val
= (int8_t)insn_get(s
, OT_BYTE
);
3143 next_eip
= s
->pc
- s
->cs_base
;
3147 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3150 case 0x131: /* rdtsc */
3154 case 0x1a2: /* cpuid */
3161 /* lock generation */
3162 if (s
->prefix
& PREFIX_LOCK
)
3166 /* XXX: ensure that no lock was generated */
3170 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3171 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3173 /* flags read by an operation */
3174 static uint16_t opc_read_flags
[NB_OPS
] = {
3175 [INDEX_op_aas
] = CC_A
,
3176 [INDEX_op_aaa
] = CC_A
,
3177 [INDEX_op_das
] = CC_A
| CC_C
,
3178 [INDEX_op_daa
] = CC_A
| CC_C
,
3180 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3181 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3182 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3183 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3184 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3185 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3187 [INDEX_op_into
] = CC_O
,
3189 [INDEX_op_jo_cc
] = CC_O
,
3190 [INDEX_op_jb_cc
] = CC_C
,
3191 [INDEX_op_jz_cc
] = CC_Z
,
3192 [INDEX_op_jbe_cc
] = CC_Z
| CC_C
,
3193 [INDEX_op_js_cc
] = CC_S
,
3194 [INDEX_op_jp_cc
] = CC_P
,
3195 [INDEX_op_jl_cc
] = CC_O
| CC_S
,
3196 [INDEX_op_jle_cc
] = CC_O
| CC_S
| CC_Z
,
3198 [INDEX_op_jb_subb
] = CC_C
,
3199 [INDEX_op_jb_subw
] = CC_C
,
3200 [INDEX_op_jb_subl
] = CC_C
,
3202 [INDEX_op_jz_subb
] = CC_Z
,
3203 [INDEX_op_jz_subw
] = CC_Z
,
3204 [INDEX_op_jz_subl
] = CC_Z
,
3206 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3207 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3208 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3210 [INDEX_op_js_subb
] = CC_S
,
3211 [INDEX_op_js_subw
] = CC_S
,
3212 [INDEX_op_js_subl
] = CC_S
,
3214 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3215 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3216 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3218 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3219 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3220 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3222 [INDEX_op_loopnzw
] = CC_Z
,
3223 [INDEX_op_loopnzl
] = CC_Z
,
3224 [INDEX_op_loopzw
] = CC_Z
,
3225 [INDEX_op_loopzl
] = CC_Z
,
3227 [INDEX_op_seto_T0_cc
] = CC_O
,
3228 [INDEX_op_setb_T0_cc
] = CC_C
,
3229 [INDEX_op_setz_T0_cc
] = CC_Z
,
3230 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3231 [INDEX_op_sets_T0_cc
] = CC_S
,
3232 [INDEX_op_setp_T0_cc
] = CC_P
,
3233 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3234 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3236 [INDEX_op_setb_T0_subb
] = CC_C
,
3237 [INDEX_op_setb_T0_subw
] = CC_C
,
3238 [INDEX_op_setb_T0_subl
] = CC_C
,
3240 [INDEX_op_setz_T0_subb
] = CC_Z
,
3241 [INDEX_op_setz_T0_subw
] = CC_Z
,
3242 [INDEX_op_setz_T0_subl
] = CC_Z
,
3244 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3245 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3246 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3248 [INDEX_op_sets_T0_subb
] = CC_S
,
3249 [INDEX_op_sets_T0_subw
] = CC_S
,
3250 [INDEX_op_sets_T0_subl
] = CC_S
,
3252 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3253 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3254 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3256 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3257 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3258 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3260 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3261 [INDEX_op_cmc
] = CC_C
,
3262 [INDEX_op_salc
] = CC_C
,
3264 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3265 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3266 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3267 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3268 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3269 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3272 /* flags written by an operation */
3273 static uint16_t opc_write_flags
[NB_OPS
] = {
3274 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3275 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3276 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3277 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3278 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3279 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3280 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3281 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3282 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3283 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3284 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3285 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3286 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3287 [INDEX_op_incl_T0_cc
] = CC_OSZAP
,
3288 [INDEX_op_decl_T0_cc
] = CC_OSZAP
,
3289 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3291 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3292 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3293 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3294 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3295 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3296 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3297 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3298 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3301 [INDEX_op_aam
] = CC_OSZAPC
,
3302 [INDEX_op_aad
] = CC_OSZAPC
,
3303 [INDEX_op_aas
] = CC_OSZAPC
,
3304 [INDEX_op_aaa
] = CC_OSZAPC
,
3305 [INDEX_op_das
] = CC_OSZAPC
,
3306 [INDEX_op_daa
] = CC_OSZAPC
,
3308 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3309 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3310 [INDEX_op_clc
] = CC_C
,
3311 [INDEX_op_stc
] = CC_C
,
3312 [INDEX_op_cmc
] = CC_C
,
3314 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3315 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3316 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3317 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3318 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3319 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3321 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3322 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3323 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3324 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3325 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3326 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3328 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3329 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3330 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3332 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3333 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3334 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3336 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3337 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3338 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3340 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3341 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3342 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3343 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3345 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3346 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3347 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3348 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3350 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3351 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3352 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3353 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3354 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3355 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3356 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3357 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3359 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3360 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3361 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3362 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3364 [INDEX_op_scasb
] = CC_OSZAPC
,
3365 [INDEX_op_scasw
] = CC_OSZAPC
,
3366 [INDEX_op_scasl
] = CC_OSZAPC
,
3367 [INDEX_op_repz_scasb
] = CC_OSZAPC
,
3368 [INDEX_op_repz_scasw
] = CC_OSZAPC
,
3369 [INDEX_op_repz_scasl
] = CC_OSZAPC
,
3370 [INDEX_op_repnz_scasb
] = CC_OSZAPC
,
3371 [INDEX_op_repnz_scasw
] = CC_OSZAPC
,
3372 [INDEX_op_repnz_scasl
] = CC_OSZAPC
,
3374 [INDEX_op_cmpsb
] = CC_OSZAPC
,
3375 [INDEX_op_cmpsw
] = CC_OSZAPC
,
3376 [INDEX_op_cmpsl
] = CC_OSZAPC
,
3377 [INDEX_op_repz_cmpsb
] = CC_OSZAPC
,
3378 [INDEX_op_repz_cmpsw
] = CC_OSZAPC
,
3379 [INDEX_op_repz_cmpsl
] = CC_OSZAPC
,
3380 [INDEX_op_repnz_cmpsb
] = CC_OSZAPC
,
3381 [INDEX_op_repnz_cmpsw
] = CC_OSZAPC
,
3382 [INDEX_op_repnz_cmpsl
] = CC_OSZAPC
,
3384 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3385 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3388 /* simpler form of an operation if no flags need to be generated */
3389 static uint16_t opc_simpler
[NB_OPS
] = {
3390 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3391 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3392 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3393 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3394 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3395 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3396 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3397 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3399 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3400 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3401 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3403 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3404 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3405 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3407 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3408 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3409 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3411 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3412 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3413 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3415 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3416 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3417 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3420 static void optimize_flags_init(void)
3423 /* put default values in arrays */
3424 for(i
= 0; i
< NB_OPS
; i
++) {
3425 if (opc_simpler
[i
] == 0)
3430 /* CPU flags computation optimization: we move backward thru the
3431 generated code to see which flags are needed. The operation is
3432 modified if suitable */
3433 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3436 int live_flags
, write_flags
, op
;
3438 opc_ptr
= opc_buf
+ opc_buf_len
;
3439 /* live_flags contains the flags needed by the next instructions
3440 in the code. At the end of the bloc, we consider that all the
3442 live_flags
= CC_OSZAPC
;
3443 while (opc_ptr
> opc_buf
) {
3445 /* if none of the flags written by the instruction is used,
3446 then we can try to find a simpler instruction */
3447 write_flags
= opc_write_flags
[op
];
3448 if ((live_flags
& write_flags
) == 0) {
3449 *opc_ptr
= opc_simpler
[op
];
3451 /* compute the live flags before the instruction */
3452 live_flags
&= ~write_flags
;
3453 live_flags
|= opc_read_flags
[op
];
3459 static const char *op_str
[] = {
3461 #include "opc-i386.h"
3465 static void dump_ops(const uint16_t *opc_buf
)
3467 const uint16_t *opc_ptr
;
3472 fprintf(logfile
, "0x%04x: %s\n", opc_ptr
- opc_buf
- 1, op_str
[c
]);
3473 if (c
== INDEX_op_end
)
3480 /* XXX: make this buffer thread safe */
3481 /* XXX: make safe guess about sizes */
3482 #define MAX_OP_PER_INSTR 32
3483 #define OPC_BUF_SIZE 512
3484 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3486 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3488 static uint16_t gen_opc_buf
[OPC_BUF_SIZE
];
3489 static uint32_t gen_opparam_buf
[OPPARAM_BUF_SIZE
];
3491 /* return non zero if the very first instruction is invalid so that
3492 the virtual CPU can trigger an exception. */
3493 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
3494 int *gen_code_size_ptr
,
3495 uint8_t *pc_start
, uint8_t *cs_base
, int flags
)
3497 DisasContext dc1
, *dc
= &dc1
;
3499 uint16_t *gen_opc_end
;
3503 struct disassemble_info disasm_info
;
3506 /* generate intermediate code */
3508 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3509 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3510 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3511 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3512 dc
->cc_op
= CC_OP_DYNAMIC
;
3513 dc
->cs_base
= cs_base
;
3515 gen_opc_ptr
= gen_opc_buf
;
3516 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3517 gen_opparam_ptr
= gen_opparam_buf
;
3522 ret
= disas_insn(dc
, pc_ptr
);
3524 /* we trigger an illegal instruction operation only if it
3525 is the first instruction. Otherwise, we simply stop
3526 generating the code just before it */
3527 if (pc_ptr
== pc_start
)
3532 pc_ptr
= (void *)ret
;
3533 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
);
3534 /* we must store the eflags state if it is not already done */
3535 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3536 gen_op_set_cc_op(dc
->cc_op
);
3537 if (dc
->is_jmp
!= 1) {
3538 /* we add an additionnal jmp to update the simulated PC */
3539 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3541 *gen_opc_ptr
= INDEX_op_end
;
3543 /* optimize flag computations */
3549 INIT_DISASSEMBLE_INFO(disasm_info
, logfile
, fprintf
);
3551 disasm_info
.flavour
= bfd_get_flavour (abfd
);
3552 disasm_info
.arch
= bfd_get_arch (abfd
);
3553 disasm_info
.mach
= bfd_get_mach (abfd
);
3555 disasm_info
.endian
= BFD_ENDIAN_LITTLE
;
3557 disasm_info
.mach
= bfd_mach_i386_i386
;
3559 disasm_info
.mach
= bfd_mach_i386_i8086
;
3560 fprintf(logfile
, "----------------\n");
3561 fprintf(logfile
, "IN:\n");
3562 disasm_info
.buffer
= pc_start
;
3563 disasm_info
.buffer_vma
= (unsigned long)pc_start
;
3564 disasm_info
.buffer_length
= pc_ptr
- pc_start
;
3566 while (pc
< pc_ptr
) {
3567 fprintf(logfile
, "0x%08lx: ", (long)pc
);
3568 count
= print_insn_i386((unsigned long)pc
, &disasm_info
);
3569 fprintf(logfile
, "\n");
3572 fprintf(logfile
, "\n");
3574 fprintf(logfile
, "OP:\n");
3575 dump_ops(gen_opc_buf
);
3576 fprintf(logfile
, "\n");
3580 /* optimize flag computations */
3581 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3585 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3586 dump_ops(gen_opc_buf
);
3587 fprintf(logfile
, "\n");
3591 /* generate machine code */
3592 gen_code_size
= dyngen_code(gen_code_buf
, gen_opc_buf
, gen_opparam_buf
);
3593 flush_icache_range((unsigned long)gen_code_buf
, (unsigned long)(gen_code_buf
+ gen_code_size
));
3594 *gen_code_size_ptr
= gen_code_size
;
3601 INIT_DISASSEMBLE_INFO(disasm_info
, logfile
, fprintf
);
3603 disasm_info
.flavour
= bfd_get_flavour (abfd
);
3604 disasm_info
.arch
= bfd_get_arch (abfd
);
3605 disasm_info
.mach
= bfd_get_mach (abfd
);
3607 #ifdef WORDS_BIGENDIAN
3608 disasm_info
.endian
= BFD_ENDIAN_BIG
;
3610 disasm_info
.endian
= BFD_ENDIAN_LITTLE
;
3612 disasm_info
.mach
= bfd_mach_i386_i386
;
3615 disasm_info
.buffer
= pc
;
3616 disasm_info
.buffer_vma
= (unsigned long)pc
;
3617 disasm_info
.buffer_length
= *gen_code_size_ptr
;
3618 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
3619 while (pc
< gen_code_buf
+ *gen_code_size_ptr
) {
3620 fprintf(logfile
, "0x%08lx: ", (long)pc
);
3621 count
= print_insn_i386((unsigned long)pc
, &disasm_info
);
3622 fprintf(logfile
, "\n");
3625 fprintf(logfile
, "\n");
3632 CPUX86State
*cpu_x86_init(void)
3638 cpu_x86_tblocks_init();
3640 env
= malloc(sizeof(CPUX86State
));
3643 memset(env
, 0, sizeof(CPUX86State
));
3644 /* basic FPU init */
3645 for(i
= 0;i
< 8; i
++)
3651 /* init various static tables */
3654 optimize_flags_init();
3659 void cpu_x86_close(CPUX86State
*env
)