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.
38 #define offsetof(type, field) ((size_t) &((type *)0)->field)
41 static uint8_t *gen_code_ptr
;
42 int __op_param1
, __op_param2
, __op_param3
;
48 static void error(const char *fmt
, ...)
53 fprintf(stderr
, "\n");
54 vfprintf(stderr
, fmt
, ap
);
55 fprintf(stderr
, "\n");
61 #define PREFIX_REPNZ 2
64 #define PREFIX_SS 0x10
65 #define PREFIX_DS 0x20
66 #define PREFIX_ES 0x40
67 #define PREFIX_FS 0x80
68 #define PREFIX_GS 0x100
69 #define PREFIX_DATA 0x200
70 #define PREFIX_ADR 0x400
71 #define PREFIX_FWAIT 0x800
73 typedef struct DisasContext
{
74 /* current insn context */
77 uint8_t *pc
; /* current pc */
78 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
79 static state change (stop translation) */
80 /* current block context */
81 int code32
; /* 32 bit code segment */
82 int cc_op
; /* current CC operation */
83 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
84 int f_st
; /* currently unused */
87 /* i386 arith/logic operations */
107 OP_SHL1
, /* undocumented */
122 /* I386 int registers */
123 OR_EAX
, /* MUST be even numbered */
131 OR_TMP0
, /* temporary operand register */
133 OR_A0
, /* temporary register used when doing address evaluation */
134 OR_ZERO
, /* fixed zero register */
138 typedef void (GenOpFunc
)(void);
139 typedef void (GenOpFunc1
)(long);
140 typedef void (GenOpFunc2
)(long, long);
142 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
175 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
208 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
231 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
301 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
312 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
324 gen_op_addl_A0_EAX_s1
,
325 gen_op_addl_A0_ECX_s1
,
326 gen_op_addl_A0_EDX_s1
,
327 gen_op_addl_A0_EBX_s1
,
328 gen_op_addl_A0_ESP_s1
,
329 gen_op_addl_A0_EBP_s1
,
330 gen_op_addl_A0_ESI_s1
,
331 gen_op_addl_A0_EDI_s1
,
334 gen_op_addl_A0_EAX_s2
,
335 gen_op_addl_A0_ECX_s2
,
336 gen_op_addl_A0_EDX_s2
,
337 gen_op_addl_A0_EBX_s2
,
338 gen_op_addl_A0_ESP_s2
,
339 gen_op_addl_A0_EBP_s2
,
340 gen_op_addl_A0_ESI_s2
,
341 gen_op_addl_A0_EDI_s2
,
344 gen_op_addl_A0_EAX_s3
,
345 gen_op_addl_A0_ECX_s3
,
346 gen_op_addl_A0_EDX_s3
,
347 gen_op_addl_A0_EBX_s3
,
348 gen_op_addl_A0_ESP_s3
,
349 gen_op_addl_A0_EBP_s3
,
350 gen_op_addl_A0_ESI_s3
,
351 gen_op_addl_A0_EDI_s3
,
355 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
356 gen_op_addl_T0_T1_cc
,
360 gen_op_andl_T0_T1_cc
,
361 gen_op_subl_T0_T1_cc
,
362 gen_op_xorl_T0_T1_cc
,
363 gen_op_cmpl_T0_T1_cc
,
366 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
368 gen_op_adcb_T0_T1_cc
,
369 gen_op_sbbb_T0_T1_cc
,
372 gen_op_adcw_T0_T1_cc
,
373 gen_op_sbbw_T0_T1_cc
,
376 gen_op_adcl_T0_T1_cc
,
377 gen_op_sbbl_T0_T1_cc
,
381 static const int cc_op_arithb
[8] = {
392 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
394 gen_op_rolb_T0_T1_cc
,
395 gen_op_rorb_T0_T1_cc
,
396 gen_op_rclb_T0_T1_cc
,
397 gen_op_rcrb_T0_T1_cc
,
398 gen_op_shlb_T0_T1_cc
,
399 gen_op_shrb_T0_T1_cc
,
400 gen_op_shlb_T0_T1_cc
,
401 gen_op_sarb_T0_T1_cc
,
404 gen_op_rolw_T0_T1_cc
,
405 gen_op_rorw_T0_T1_cc
,
406 gen_op_rclw_T0_T1_cc
,
407 gen_op_rcrw_T0_T1_cc
,
408 gen_op_shlw_T0_T1_cc
,
409 gen_op_shrw_T0_T1_cc
,
410 gen_op_shlw_T0_T1_cc
,
411 gen_op_sarw_T0_T1_cc
,
414 gen_op_roll_T0_T1_cc
,
415 gen_op_rorl_T0_T1_cc
,
416 gen_op_rcll_T0_T1_cc
,
417 gen_op_rcrl_T0_T1_cc
,
418 gen_op_shll_T0_T1_cc
,
419 gen_op_shrl_T0_T1_cc
,
420 gen_op_shll_T0_T1_cc
,
421 gen_op_sarl_T0_T1_cc
,
425 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
427 gen_op_shldw_T0_T1_im_cc
,
428 gen_op_shrdw_T0_T1_im_cc
,
431 gen_op_shldl_T0_T1_im_cc
,
432 gen_op_shrdl_T0_T1_im_cc
,
436 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
438 gen_op_shldw_T0_T1_ECX_cc
,
439 gen_op_shrdw_T0_T1_ECX_cc
,
442 gen_op_shldl_T0_T1_ECX_cc
,
443 gen_op_shrdl_T0_T1_ECX_cc
,
447 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
450 gen_op_btsw_T0_T1_cc
,
451 gen_op_btrw_T0_T1_cc
,
452 gen_op_btcw_T0_T1_cc
,
456 gen_op_btsl_T0_T1_cc
,
457 gen_op_btrl_T0_T1_cc
,
458 gen_op_btcl_T0_T1_cc
,
462 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
473 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
478 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
483 /* sign does not matter */
484 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
490 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
496 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
502 static GenOpFunc
*gen_op_movs
[6] = {
511 static GenOpFunc
*gen_op_stos
[6] = {
520 static GenOpFunc
*gen_op_lods
[6] = {
529 static GenOpFunc
*gen_op_scas
[9] = {
541 static GenOpFunc
*gen_op_cmps
[9] = {
553 static GenOpFunc
*gen_op_ins
[6] = {
563 static GenOpFunc
*gen_op_outs
[6] = {
572 static GenOpFunc
*gen_op_in
[3] = {
578 static GenOpFunc
*gen_op_out
[3] = {
595 static GenOpFunc2
*gen_jcc_slow
[8] = {
606 static GenOpFunc2
*gen_jcc_sub
[3][8] = {
639 static GenOpFunc
*gen_setcc_slow
[8] = {
650 static GenOpFunc
*gen_setcc_sub
[3][8] = {
655 gen_op_setbe_T0_subb
,
659 gen_op_setle_T0_subb
,
665 gen_op_setbe_T0_subw
,
669 gen_op_setle_T0_subw
,
675 gen_op_setbe_T0_subl
,
679 gen_op_setle_T0_subl
,
683 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
689 gen_op_fsubr_ST0_FT0
,
691 gen_op_fdivr_ST0_FT0
,
694 /* NOTE the exception in "r" op ordering */
695 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
700 gen_op_fsubr_STN_ST0
,
702 gen_op_fdivr_STN_ST0
,
706 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
709 gen_op_mov_TN_reg
[ot
][0][d
]();
711 gen_op_mov_TN_reg
[ot
][1][s
]();
712 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
713 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
714 gen_op_set_cc_op(s1
->cc_op
);
715 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
716 s1
->cc_op
= CC_OP_DYNAMIC
;
718 gen_op_arith_T0_T1_cc
[op
]();
719 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
721 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
722 gen_op_mov_reg_T0
[ot
][d
]();
725 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
727 gen_op_movl_T1_im(c
);
728 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
731 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
734 gen_op_mov_TN_reg
[ot
][0][d
]();
735 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
736 gen_op_set_cc_op(s1
->cc_op
);
739 s1
->cc_op
= CC_OP_INCB
+ ot
;
742 s1
->cc_op
= CC_OP_DECB
+ ot
;
745 gen_op_mov_reg_T0
[ot
][d
]();
748 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
751 gen_op_mov_TN_reg
[ot
][0][d
]();
753 gen_op_mov_TN_reg
[ot
][1][s
]();
754 /* for zero counts, flags are not updated, so must do it dynamically */
755 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
756 gen_op_set_cc_op(s1
->cc_op
);
758 gen_op_shift_T0_T1_cc
[ot
][op
]();
761 gen_op_mov_reg_T0
[ot
][d
]();
762 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
765 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
767 /* currently not optimized */
768 gen_op_movl_T1_im(c
);
769 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
772 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
779 int mod
, rm
, code
, override
, must_add_seg
;
781 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
782 /* XXX: fix lea case */
784 must_add_seg
= s
->addseg
;
785 if (s
->prefix
& (PREFIX_CS
| PREFIX_SS
| PREFIX_DS
|
786 PREFIX_ES
| PREFIX_FS
| PREFIX_GS
)) {
787 if (s
->prefix
& PREFIX_ES
)
789 else if (s
->prefix
& PREFIX_CS
)
791 else if (s
->prefix
& PREFIX_SS
)
793 else if (s
->prefix
& PREFIX_DS
)
795 else if (s
->prefix
& PREFIX_FS
)
802 mod
= (modrm
>> 6) & 3;
814 code
= ldub(s
->pc
++);
815 scale
= (code
>> 6) & 3;
816 index
= (code
>> 3) & 7;
831 disp
= (int8_t)ldub(s
->pc
++);
841 gen_op_movl_A0_reg
[base
]();
843 gen_op_addl_A0_im(disp
);
845 gen_op_movl_A0_im(disp
);
847 if (havesib
&& (index
!= 4 || scale
!= 0)) {
848 gen_op_addl_A0_reg_sN
[scale
][index
]();
852 if (base
== R_EBP
|| base
== R_ESP
)
857 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
865 gen_op_movl_A0_im(disp
);
866 rm
= 0; /* avoid SS override */
873 disp
= (int8_t)ldub(s
->pc
++);
883 gen_op_movl_A0_reg
[R_EBX
]();
884 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
887 gen_op_movl_A0_reg
[R_EBX
]();
888 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
891 gen_op_movl_A0_reg
[R_EBP
]();
892 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
895 gen_op_movl_A0_reg
[R_EBP
]();
896 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
899 gen_op_movl_A0_reg
[R_ESI
]();
902 gen_op_movl_A0_reg
[R_EDI
]();
905 gen_op_movl_A0_reg
[R_EBP
]();
909 gen_op_movl_A0_reg
[R_EBX
]();
913 gen_op_addl_A0_im(disp
);
914 gen_op_andl_A0_ffff();
918 if (rm
== 2 || rm
== 3 || rm
== 6)
923 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
933 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
935 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
937 int mod
, rm
, opreg
, disp
;
939 mod
= (modrm
>> 6) & 3;
944 gen_op_mov_TN_reg
[ot
][0][reg
]();
945 gen_op_mov_reg_T0
[ot
][rm
]();
947 gen_op_mov_TN_reg
[ot
][0][rm
]();
949 gen_op_mov_reg_T0
[ot
][reg
]();
952 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
955 gen_op_mov_TN_reg
[ot
][0][reg
]();
956 gen_op_st_T0_A0
[ot
]();
958 gen_op_ld_T0_A0
[ot
]();
960 gen_op_mov_reg_T0
[ot
][reg
]();
965 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
987 static void gen_jcc(DisasContext
*s
, int b
, int val
)
993 jcc_op
= (b
>> 1) & 7;
995 /* we optimize the cmp/jcc case */
999 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1004 /* some jumps are easy to compute */
1031 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1034 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1042 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1043 gen_op_set_cc_op(s
->cc_op
);
1044 func
= gen_jcc_slow
[jcc_op
];
1048 func(val
, (long)s
->pc
);
1050 func((long)s
->pc
, val
);
1054 static void gen_setcc(DisasContext
*s
, int b
)
1060 jcc_op
= (b
>> 1) & 7;
1062 /* we optimize the cmp/jcc case */
1066 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1071 /* some jumps are easy to compute */
1089 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1092 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1100 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1101 gen_op_set_cc_op(s
->cc_op
);
1102 func
= gen_setcc_slow
[jcc_op
];
1111 /* move T0 to seg_reg and compute if the CPU state may change */
1112 void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
)
1114 gen_op_movl_seg_T0(seg_reg
);
1115 if (!s
->addseg
&& seg_reg
< R_FS
)
1116 s
->is_jmp
= 2; /* abort translation because the register may
1117 have a non zero base */
1120 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1121 is set to true if the instruction sets the PC (last instruction of
1123 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1125 int b
, prefixes
, aflag
, dflag
;
1127 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1133 // cur_pc = s->pc; /* for insn generation */
1137 /* check prefixes */
1140 prefixes
|= PREFIX_REPZ
;
1143 prefixes
|= PREFIX_REPNZ
;
1146 prefixes
|= PREFIX_LOCK
;
1149 prefixes
|= PREFIX_CS
;
1152 prefixes
|= PREFIX_SS
;
1155 prefixes
|= PREFIX_DS
;
1158 prefixes
|= PREFIX_ES
;
1161 prefixes
|= PREFIX_FS
;
1164 prefixes
|= PREFIX_GS
;
1167 prefixes
|= PREFIX_DATA
;
1170 prefixes
|= PREFIX_ADR
;
1173 prefixes
|= PREFIX_FWAIT
;
1177 if (prefixes
& PREFIX_DATA
)
1179 if (prefixes
& PREFIX_ADR
)
1182 s
->prefix
= prefixes
;
1186 /* now check op code */
1190 /**************************/
1191 /* extended op code */
1192 b
= ldub(s
->pc
++) | 0x100;
1195 /**************************/
1213 ot
= dflag
? OT_LONG
: OT_WORD
;
1216 case 0: /* OP Ev, Gv */
1217 modrm
= ldub(s
->pc
++);
1218 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1219 mod
= (modrm
>> 6) & 3;
1222 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1223 gen_op_ld_T0_A0
[ot
]();
1226 opreg
= OR_EAX
+ rm
;
1228 gen_op(s
, op
, ot
, opreg
, reg
);
1229 if (mod
!= 3 && op
!= 7) {
1230 gen_op_st_T0_A0
[ot
]();
1233 case 1: /* OP Gv, Ev */
1234 modrm
= ldub(s
->pc
++);
1235 mod
= (modrm
>> 6) & 3;
1236 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1239 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1240 gen_op_ld_T1_A0
[ot
]();
1243 opreg
= OR_EAX
+ rm
;
1245 gen_op(s
, op
, ot
, reg
, opreg
);
1247 case 2: /* OP A, Iv */
1248 val
= insn_get(s
, ot
);
1249 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1255 case 0x80: /* GRP1 */
1264 ot
= dflag
? OT_LONG
: OT_WORD
;
1266 modrm
= ldub(s
->pc
++);
1267 mod
= (modrm
>> 6) & 3;
1269 op
= (modrm
>> 3) & 7;
1272 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1273 gen_op_ld_T0_A0
[ot
]();
1276 opreg
= rm
+ OR_EAX
;
1283 val
= insn_get(s
, ot
);
1286 val
= (int8_t)insn_get(s
, OT_BYTE
);
1290 gen_opi(s
, op
, ot
, opreg
, val
);
1291 if (op
!= 7 && mod
!= 3) {
1292 gen_op_st_T0_A0
[ot
]();
1297 /**************************/
1298 /* inc, dec, and other misc arith */
1299 case 0x40 ... 0x47: /* inc Gv */
1300 ot
= dflag
? OT_LONG
: OT_WORD
;
1301 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1303 case 0x48 ... 0x4f: /* dec Gv */
1304 ot
= dflag
? OT_LONG
: OT_WORD
;
1305 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1307 case 0xf6: /* GRP3 */
1312 ot
= dflag
? OT_LONG
: OT_WORD
;
1314 modrm
= ldub(s
->pc
++);
1315 mod
= (modrm
>> 6) & 3;
1317 op
= (modrm
>> 3) & 7;
1319 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1320 gen_op_ld_T0_A0
[ot
]();
1322 gen_op_mov_TN_reg
[ot
][0][rm
]();
1327 val
= insn_get(s
, ot
);
1328 gen_op_movl_T1_im(val
);
1329 gen_op_testl_T0_T1_cc();
1330 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1335 gen_op_st_T0_A0
[ot
]();
1337 gen_op_mov_reg_T0
[ot
][rm
]();
1341 gen_op_negl_T0_cc();
1343 gen_op_st_T0_A0
[ot
]();
1345 gen_op_mov_reg_T0
[ot
][rm
]();
1347 s
->cc_op
= CC_OP_SUBB
+ ot
;
1352 gen_op_mulb_AL_T0();
1355 gen_op_mulw_AX_T0();
1359 gen_op_mull_EAX_T0();
1362 s
->cc_op
= CC_OP_MUL
;
1367 gen_op_imulb_AL_T0();
1370 gen_op_imulw_AX_T0();
1374 gen_op_imull_EAX_T0();
1377 s
->cc_op
= CC_OP_MUL
;
1382 gen_op_divb_AL_T0();
1385 gen_op_divw_AX_T0();
1389 gen_op_divl_EAX_T0();
1396 gen_op_idivb_AL_T0();
1399 gen_op_idivw_AX_T0();
1403 gen_op_idivl_EAX_T0();
1408 error("GRP3: bad instruction");
1413 case 0xfe: /* GRP4 */
1414 case 0xff: /* GRP5 */
1418 ot
= dflag
? OT_LONG
: OT_WORD
;
1420 modrm
= ldub(s
->pc
++);
1421 mod
= (modrm
>> 6) & 3;
1423 op
= (modrm
>> 3) & 7;
1424 if (op
>= 2 && b
== 0xfe) {
1425 error("GRP4: bad instruction");
1429 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1430 gen_op_ld_T0_A0
[ot
]();
1432 gen_op_mov_TN_reg
[ot
][0][rm
]();
1436 case 0: /* inc Ev */
1437 gen_inc(s
, ot
, OR_TMP0
, 1);
1439 gen_op_st_T0_A0
[ot
]();
1441 gen_op_mov_reg_T0
[ot
][rm
]();
1443 case 1: /* dec Ev */
1444 gen_inc(s
, ot
, OR_TMP0
, -1);
1446 gen_op_st_T0_A0
[ot
]();
1448 gen_op_mov_reg_T0
[ot
][rm
]();
1450 case 2: /* call Ev */
1451 gen_op_movl_T1_im((long)s
->pc
);
1456 case 4: /* jmp Ev */
1460 case 6: /* push Ev */
1464 error("GRP5: bad instruction");
1469 case 0x84: /* test Ev, Gv */
1474 ot
= dflag
? OT_LONG
: OT_WORD
;
1476 modrm
= ldub(s
->pc
++);
1477 mod
= (modrm
>> 6) & 3;
1479 reg
= (modrm
>> 3) & 7;
1481 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1482 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1483 gen_op_testl_T0_T1_cc();
1484 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1487 case 0xa8: /* test eAX, Iv */
1492 ot
= dflag
? OT_LONG
: OT_WORD
;
1493 val
= insn_get(s
, ot
);
1495 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1496 gen_op_movl_T1_im(val
);
1497 gen_op_testl_T0_T1_cc();
1498 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1501 case 0x98: /* CWDE/CBW */
1503 gen_op_movswl_EAX_AX();
1505 gen_op_movsbw_AX_AL();
1507 case 0x99: /* CDQ/CWD */
1509 gen_op_movslq_EDX_EAX();
1511 gen_op_movswl_DX_AX();
1513 case 0x1af: /* imul Gv, Ev */
1514 case 0x69: /* imul Gv, Ev, I */
1516 ot
= dflag
? OT_LONG
: OT_WORD
;
1517 modrm
= ldub(s
->pc
++);
1518 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1519 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1521 val
= insn_get(s
, ot
);
1522 gen_op_movl_T1_im(val
);
1523 } else if (b
== 0x6b) {
1524 val
= insn_get(s
, OT_BYTE
);
1525 gen_op_movl_T1_im(val
);
1527 gen_op_mov_TN_reg
[ot
][1][reg
]();
1530 if (ot
== OT_LONG
) {
1531 gen_op_imull_T0_T1();
1533 gen_op_imulw_T0_T1();
1535 gen_op_mov_reg_T0
[ot
][reg
]();
1536 s
->cc_op
= CC_OP_MUL
;
1539 /**************************/
1541 case 0x50 ... 0x57: /* push */
1542 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1545 case 0x58 ... 0x5f: /* pop */
1547 gen_op_mov_reg_T0
[OT_LONG
][b
& 7]();
1549 case 0x60: /* pusha */
1555 case 0x61: /* popa */
1561 case 0x68: /* push Iv */
1563 ot
= dflag
? OT_LONG
: OT_WORD
;
1565 val
= insn_get(s
, ot
);
1567 val
= (int8_t)insn_get(s
, OT_BYTE
);
1568 gen_op_movl_T0_im(val
);
1571 case 0x8f: /* pop Ev */
1572 ot
= dflag
? OT_LONG
: OT_WORD
;
1573 modrm
= ldub(s
->pc
++);
1575 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1577 case 0xc8: /* enter */
1582 level
= ldub(s
->pc
++);
1584 gen_op_enterl(val
, level
);
1587 case 0xc9: /* leave */
1588 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1589 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1591 gen_op_mov_reg_T0
[OT_LONG
][R_EBP
]();
1593 case 0x06: /* push es */
1594 case 0x0e: /* push cs */
1595 case 0x16: /* push ss */
1596 case 0x1e: /* push ds */
1597 gen_op_movl_T0_seg(b
>> 3);
1600 case 0x1a0: /* push fs */
1601 case 0x1a8: /* push gs */
1602 gen_op_movl_T0_seg(((b
>> 3) & 7) + R_FS
);
1605 case 0x07: /* pop es */
1606 case 0x17: /* pop ss */
1607 case 0x1f: /* pop ds */
1609 gen_movl_seg_T0(s
, b
>> 3);
1611 case 0x1a1: /* pop fs */
1612 case 0x1a9: /* pop gs */
1614 gen_movl_seg_T0(s
, ((b
>> 3) & 7) + R_FS
);
1617 /**************************/
1620 case 0x89: /* mov Gv, Ev */
1624 ot
= dflag
? OT_LONG
: OT_WORD
;
1625 modrm
= ldub(s
->pc
++);
1626 reg
= (modrm
>> 3) & 7;
1628 /* generate a generic store */
1629 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
1632 case 0xc7: /* mov Ev, Iv */
1636 ot
= dflag
? OT_LONG
: OT_WORD
;
1637 modrm
= ldub(s
->pc
++);
1638 mod
= (modrm
>> 6) & 3;
1640 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1641 val
= insn_get(s
, ot
);
1642 gen_op_movl_T0_im(val
);
1644 gen_op_st_T0_A0
[ot
]();
1646 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
1649 case 0x8b: /* mov Ev, Gv */
1653 ot
= dflag
? OT_LONG
: OT_WORD
;
1654 modrm
= ldub(s
->pc
++);
1655 reg
= (modrm
>> 3) & 7;
1657 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1658 gen_op_mov_reg_T0
[ot
][reg
]();
1660 case 0x8e: /* mov seg, Gv */
1661 ot
= dflag
? OT_LONG
: OT_WORD
;
1662 modrm
= ldub(s
->pc
++);
1663 reg
= (modrm
>> 3) & 7;
1664 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1667 gen_movl_seg_T0(s
, reg
);
1669 case 0x8c: /* mov Gv, seg */
1670 ot
= dflag
? OT_LONG
: OT_WORD
;
1671 modrm
= ldub(s
->pc
++);
1672 reg
= (modrm
>> 3) & 7;
1675 gen_op_movl_T0_seg(reg
);
1676 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1679 case 0x1b6: /* movzbS Gv, Eb */
1680 case 0x1b7: /* movzwS Gv, Eb */
1681 case 0x1be: /* movsbS Gv, Eb */
1682 case 0x1bf: /* movswS Gv, Eb */
1685 /* d_ot is the size of destination */
1686 d_ot
= dflag
+ OT_WORD
;
1687 /* ot is the size of source */
1688 ot
= (b
& 1) + OT_BYTE
;
1689 modrm
= ldub(s
->pc
++);
1690 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1691 mod
= (modrm
>> 6) & 3;
1695 gen_op_mov_TN_reg
[ot
][0][rm
]();
1696 switch(ot
| (b
& 8)) {
1698 gen_op_movzbl_T0_T0();
1701 gen_op_movsbl_T0_T0();
1704 gen_op_movzwl_T0_T0();
1708 gen_op_movswl_T0_T0();
1711 gen_op_mov_reg_T0
[d_ot
][reg
]();
1713 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1715 gen_op_lds_T0_A0
[ot
]();
1717 gen_op_ldu_T0_A0
[ot
]();
1719 gen_op_mov_reg_T0
[d_ot
][reg
]();
1724 case 0x8d: /* lea */
1725 ot
= dflag
? OT_LONG
: OT_WORD
;
1726 modrm
= ldub(s
->pc
++);
1727 reg
= (modrm
>> 3) & 7;
1728 /* we must ensure that no segment is added */
1729 s
->prefix
&= ~(PREFIX_CS
| PREFIX_SS
| PREFIX_DS
|
1730 PREFIX_ES
| PREFIX_FS
| PREFIX_GS
);
1733 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1735 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
1738 case 0xa0: /* mov EAX, Ov */
1740 case 0xa2: /* mov Ov, EAX */
1745 ot
= dflag
? OT_LONG
: OT_WORD
;
1747 offset_addr
= insn_get(s
, OT_LONG
);
1749 offset_addr
= insn_get(s
, OT_WORD
);
1750 gen_op_movl_A0_im(offset_addr
);
1752 gen_op_ld_T0_A0
[ot
]();
1753 gen_op_mov_reg_T0
[ot
][R_EAX
]();
1755 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
1756 gen_op_st_T0_A0
[ot
]();
1760 case 0xb0 ... 0xb7: /* mov R, Ib */
1761 val
= insn_get(s
, OT_BYTE
);
1762 gen_op_movl_T0_im(val
);
1763 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
1765 case 0xb8 ... 0xbf: /* mov R, Iv */
1766 ot
= dflag
? OT_LONG
: OT_WORD
;
1767 val
= insn_get(s
, ot
);
1768 reg
= OR_EAX
+ (b
& 7);
1769 gen_op_movl_T0_im(val
);
1770 gen_op_mov_reg_T0
[ot
][reg
]();
1773 case 0x91 ... 0x97: /* xchg R, EAX */
1774 ot
= dflag
? OT_LONG
: OT_WORD
;
1776 gen_op_mov_TN_reg
[ot
][0][reg
]();
1777 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
1778 gen_op_mov_reg_T0
[ot
][R_EAX
]();
1779 gen_op_mov_reg_T1
[ot
][reg
]();
1782 case 0x87: /* xchg Ev, Gv */
1786 ot
= dflag
? OT_LONG
: OT_WORD
;
1787 modrm
= ldub(s
->pc
++);
1788 reg
= (modrm
>> 3) & 7;
1790 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1791 gen_op_mov_TN_reg
[ot
][0][reg
]();
1792 gen_op_ld_T1_A0
[ot
]();
1793 gen_op_st_T0_A0
[ot
]();
1794 gen_op_mov_reg_T1
[ot
][reg
]();
1796 case 0xc4: /* les Gv */
1799 case 0xc5: /* lds Gv */
1802 case 0x1b2: /* lss Gv */
1805 case 0x1b4: /* lfs Gv */
1808 case 0x1b5: /* lgs Gv */
1811 ot
= dflag
? OT_LONG
: OT_WORD
;
1812 modrm
= ldub(s
->pc
++);
1813 reg
= (modrm
>> 3) & 7;
1814 mod
= (modrm
>> 6) & 3;
1817 gen_op_ld_T1_A0
[ot
]();
1818 op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1819 /* load the segment first to handle exceptions properly */
1820 gen_op_lduw_T0_A0();
1821 gen_movl_seg_T0(s
, op
);
1822 /* then put the data */
1823 gen_op_mov_reg_T1
[ot
][reg
]();
1826 /************************/
1837 ot
= dflag
? OT_LONG
: OT_WORD
;
1839 modrm
= ldub(s
->pc
++);
1840 mod
= (modrm
>> 6) & 3;
1842 op
= (modrm
>> 3) & 7;
1845 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1846 gen_op_ld_T0_A0
[ot
]();
1849 opreg
= rm
+ OR_EAX
;
1854 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
1857 shift
= ldub(s
->pc
++);
1859 gen_shifti(s
, op
, ot
, opreg
, shift
);
1863 gen_op_st_T0_A0
[ot
]();
1878 case 0x1a4: /* shld imm */
1882 case 0x1a5: /* shld cl */
1886 case 0x1ac: /* shrd imm */
1890 case 0x1ad: /* shrd cl */
1894 ot
= dflag
? OT_LONG
: OT_WORD
;
1895 modrm
= ldub(s
->pc
++);
1896 mod
= (modrm
>> 6) & 3;
1898 reg
= (modrm
>> 3) & 7;
1901 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1902 gen_op_ld_T0_A0
[ot
]();
1904 gen_op_mov_TN_reg
[ot
][0][rm
]();
1906 gen_op_mov_TN_reg
[ot
][1][reg
]();
1909 val
= ldub(s
->pc
++);
1912 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
1913 if (op
== 0 && ot
!= OT_WORD
)
1914 s
->cc_op
= CC_OP_SHLB
+ ot
;
1916 s
->cc_op
= CC_OP_SARB
+ ot
;
1919 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1920 gen_op_set_cc_op(s
->cc_op
);
1921 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
1922 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
1925 gen_op_st_T0_A0
[ot
]();
1927 gen_op_mov_reg_T0
[ot
][rm
]();
1931 /************************/
1934 modrm
= ldub(s
->pc
++);
1935 mod
= (modrm
>> 6) & 3;
1937 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
1941 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1943 case 0x00 ... 0x07: /* fxxxs */
1944 case 0x10 ... 0x17: /* fixxxl */
1945 case 0x20 ... 0x27: /* fxxxl */
1946 case 0x30 ... 0x37: /* fixxx */
1953 gen_op_flds_FT0_A0();
1956 gen_op_fildl_FT0_A0();
1959 gen_op_fldl_FT0_A0();
1963 gen_op_fild_FT0_A0();
1967 gen_op_fp_arith_ST0_FT0
[op1
]();
1969 /* fcomp needs pop */
1974 case 0x08: /* flds */
1975 case 0x0a: /* fsts */
1976 case 0x0b: /* fstps */
1977 case 0x18: /* fildl */
1978 case 0x1a: /* fistl */
1979 case 0x1b: /* fistpl */
1980 case 0x28: /* fldl */
1981 case 0x2a: /* fstl */
1982 case 0x2b: /* fstpl */
1983 case 0x38: /* filds */
1984 case 0x3a: /* fists */
1985 case 0x3b: /* fistps */
1992 gen_op_flds_ST0_A0();
1995 gen_op_fildl_ST0_A0();
1998 gen_op_fldl_ST0_A0();
2002 gen_op_fild_ST0_A0();
2009 gen_op_fsts_ST0_A0();
2012 gen_op_fistl_ST0_A0();
2015 gen_op_fstl_ST0_A0();
2019 gen_op_fist_ST0_A0();
2027 case 0x0d: /* fldcw mem */
2030 case 0x0f: /* fnstcw mem */
2033 case 0x1d: /* fldt mem */
2035 gen_op_fldt_ST0_A0();
2037 case 0x1f: /* fstpt mem */
2038 gen_op_fstt_ST0_A0();
2041 case 0x2f: /* fnstsw mem */
2044 case 0x3c: /* fbld */
2046 gen_op_fbld_ST0_A0();
2048 case 0x3e: /* fbstp */
2049 gen_op_fbst_ST0_A0();
2052 case 0x3d: /* fildll */
2054 gen_op_fildll_ST0_A0();
2056 case 0x3f: /* fistpll */
2057 gen_op_fistll_ST0_A0();
2061 error("unhandled FPm [op=0x%02x]\n", op
);
2065 /* register float ops */
2069 case 0x08: /* fld sti */
2071 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2073 case 0x09: /* fxchg sti */
2074 gen_op_fxchg_ST0_STN(opreg
);
2076 case 0x0a: /* grp d9/2 */
2081 error("unhandled FP GRP d9/2\n");
2085 case 0x0c: /* grp d9/4 */
2095 gen_op_fcom_ST0_FT0();
2104 case 0x0d: /* grp d9/5 */
2113 gen_op_fldl2t_ST0();
2117 gen_op_fldl2e_ST0();
2125 gen_op_fldlg2_ST0();
2129 gen_op_fldln2_ST0();
2140 case 0x0e: /* grp d9/6 */
2151 case 3: /* fpatan */
2154 case 4: /* fxtract */
2157 case 5: /* fprem1 */
2160 case 6: /* fdecstp */
2164 case 7: /* fincstp */
2169 case 0x0f: /* grp d9/7 */
2174 case 1: /* fyl2xp1 */
2180 case 3: /* fsincos */
2183 case 5: /* fscale */
2186 case 4: /* frndint */
2198 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2199 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2200 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2206 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2210 gen_op_fmov_FT0_STN(opreg
);
2211 gen_op_fp_arith_ST0_FT0
[op1
]();
2215 case 0x02: /* fcom */
2216 gen_op_fmov_FT0_STN(opreg
);
2217 gen_op_fcom_ST0_FT0();
2219 case 0x03: /* fcomp */
2220 gen_op_fmov_FT0_STN(opreg
);
2221 gen_op_fcom_ST0_FT0();
2224 case 0x15: /* da/5 */
2226 case 1: /* fucompp */
2227 gen_op_fmov_FT0_STN(1);
2228 gen_op_fucom_ST0_FT0();
2236 case 0x2a: /* fst sti */
2237 gen_op_fmov_STN_ST0(opreg
);
2239 case 0x2b: /* fstp sti */
2240 gen_op_fmov_STN_ST0(opreg
);
2243 case 0x2c: /* fucom st(i) */
2244 gen_op_fmov_FT0_STN(opreg
);
2245 gen_op_fucom_ST0_FT0();
2247 case 0x2d: /* fucomp st(i) */
2248 gen_op_fmov_FT0_STN(opreg
);
2249 gen_op_fucom_ST0_FT0();
2252 case 0x33: /* de/3 */
2254 case 1: /* fcompp */
2255 gen_op_fmov_FT0_STN(1);
2256 gen_op_fcom_ST0_FT0();
2264 case 0x3c: /* df/4 */
2267 gen_op_fnstsw_EAX();
2270 error("unhandled FP %x df/4\n", rm
);
2275 error("unhandled FPr [op=0x%x]\n", op
);
2280 /************************/
2282 case 0xa4: /* movsS */
2287 ot
= dflag
? OT_LONG
: OT_WORD
;
2288 if (prefixes
& PREFIX_REPZ
) {
2289 gen_op_movs
[3 + ot
]();
2295 case 0xaa: /* stosS */
2300 ot
= dflag
? OT_LONG
: OT_WORD
;
2301 if (prefixes
& PREFIX_REPZ
) {
2302 gen_op_stos
[3 + ot
]();
2307 case 0xac: /* lodsS */
2312 ot
= dflag
? OT_LONG
: OT_WORD
;
2313 if (prefixes
& PREFIX_REPZ
) {
2314 gen_op_lods
[3 + ot
]();
2319 case 0xae: /* scasS */
2324 ot
= dflag
? OT_LONG
: OT_WORD
;
2325 if (prefixes
& PREFIX_REPNZ
) {
2326 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2327 gen_op_set_cc_op(s
->cc_op
);
2328 gen_op_scas
[6 + ot
]();
2329 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2330 } else if (prefixes
& PREFIX_REPZ
) {
2331 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2332 gen_op_set_cc_op(s
->cc_op
);
2333 gen_op_scas
[3 + ot
]();
2334 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2337 s
->cc_op
= CC_OP_SUBB
+ ot
;
2341 case 0xa6: /* cmpsS */
2346 ot
= dflag
? OT_LONG
: OT_WORD
;
2347 if (prefixes
& PREFIX_REPNZ
) {
2348 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2349 gen_op_set_cc_op(s
->cc_op
);
2350 gen_op_cmps
[6 + ot
]();
2351 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2352 } else if (prefixes
& PREFIX_REPZ
) {
2353 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2354 gen_op_set_cc_op(s
->cc_op
);
2355 gen_op_cmps
[3 + ot
]();
2356 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2359 s
->cc_op
= CC_OP_SUBB
+ ot
;
2363 /************************/
2365 case 0x6c: /* insS */
2370 ot
= dflag
? OT_LONG
: OT_WORD
;
2371 if (prefixes
& PREFIX_REPZ
) {
2372 gen_op_ins
[3 + ot
]();
2377 case 0x6e: /* outsS */
2382 ot
= dflag
? OT_LONG
: OT_WORD
;
2383 if (prefixes
& PREFIX_REPZ
) {
2384 gen_op_outs
[3 + ot
]();
2394 ot
= dflag
? OT_LONG
: OT_WORD
;
2395 val
= ldub(s
->pc
++);
2396 gen_op_movl_T0_im(val
);
2398 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2405 ot
= dflag
? OT_LONG
: OT_WORD
;
2406 val
= ldub(s
->pc
++);
2407 gen_op_movl_T0_im(val
);
2408 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2416 ot
= dflag
? OT_LONG
: OT_WORD
;
2417 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2419 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2426 ot
= dflag
? OT_LONG
: OT_WORD
;
2427 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2428 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2432 /************************/
2434 case 0xc2: /* ret im */
2435 /* XXX: handle stack pop ? */
2439 gen_op_addl_ESP_im(val
);
2443 case 0xc3: /* ret */
2448 case 0xe8: /* call */
2449 val
= insn_get(s
, OT_LONG
);
2451 gen_op_movl_T1_im((long)s
->pc
);
2456 case 0xe9: /* jmp */
2457 val
= insn_get(s
, OT_LONG
);
2462 case 0xeb: /* jmp Jb */
2463 val
= (int8_t)insn_get(s
, OT_BYTE
);
2468 case 0x70 ... 0x7f: /* jcc Jb */
2469 val
= (int8_t)insn_get(s
, OT_BYTE
);
2472 case 0x180 ... 0x18f: /* jcc Jv */
2474 val
= insn_get(s
, OT_LONG
);
2476 val
= (int16_t)insn_get(s
, OT_WORD
);
2478 val
+= (long)s
->pc
; /* XXX: fix 16 bit wrap */
2484 case 0x190 ... 0x19f:
2485 modrm
= ldub(s
->pc
++);
2487 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
2490 /************************/
2492 case 0x9c: /* pushf */
2493 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2494 gen_op_set_cc_op(s
->cc_op
);
2495 gen_op_movl_T0_eflags();
2498 case 0x9d: /* popf */
2500 gen_op_movl_eflags_T0();
2501 s
->cc_op
= CC_OP_EFLAGS
;
2503 case 0x9e: /* sahf */
2504 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
2505 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2506 gen_op_set_cc_op(s
->cc_op
);
2507 gen_op_movb_eflags_T0();
2508 s
->cc_op
= CC_OP_EFLAGS
;
2510 case 0x9f: /* lahf */
2511 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2512 gen_op_set_cc_op(s
->cc_op
);
2513 gen_op_movl_T0_eflags();
2514 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
2516 case 0xf5: /* cmc */
2517 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2518 gen_op_set_cc_op(s
->cc_op
);
2520 s
->cc_op
= CC_OP_EFLAGS
;
2522 case 0xf8: /* clc */
2523 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2524 gen_op_set_cc_op(s
->cc_op
);
2526 s
->cc_op
= CC_OP_EFLAGS
;
2528 case 0xf9: /* stc */
2529 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2530 gen_op_set_cc_op(s
->cc_op
);
2532 s
->cc_op
= CC_OP_EFLAGS
;
2534 case 0xfc: /* cld */
2537 case 0xfd: /* std */
2541 /************************/
2542 /* bit operations */
2543 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2544 ot
= dflag
? OT_LONG
: OT_WORD
;
2545 modrm
= ldub(s
->pc
++);
2546 op
= (modrm
>> 3) & 7;
2547 mod
= (modrm
>> 6) & 3;
2550 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2551 gen_op_ld_T0_A0
[ot
]();
2553 gen_op_mov_TN_reg
[ot
][0][rm
]();
2556 val
= ldub(s
->pc
++);
2557 gen_op_movl_T1_im(val
);
2561 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
2562 s
->cc_op
= CC_OP_SARB
+ ot
;
2565 gen_op_st_T0_A0
[ot
]();
2567 gen_op_mov_reg_T0
[ot
][rm
]();
2570 case 0x1a3: /* bt Gv, Ev */
2573 case 0x1ab: /* bts */
2576 case 0x1b3: /* btr */
2579 case 0x1bb: /* btc */
2582 ot
= dflag
? OT_LONG
: OT_WORD
;
2583 modrm
= ldub(s
->pc
++);
2584 reg
= (modrm
>> 3) & 7;
2585 mod
= (modrm
>> 6) & 3;
2587 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
2589 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2590 /* specific case: we need to add a displacement */
2592 gen_op_add_bitw_A0_T1();
2594 gen_op_add_bitl_A0_T1();
2595 gen_op_ld_T0_A0
[ot
]();
2597 gen_op_mov_TN_reg
[ot
][0][rm
]();
2599 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
2600 s
->cc_op
= CC_OP_SARB
+ ot
;
2603 gen_op_st_T0_A0
[ot
]();
2605 gen_op_mov_reg_T0
[ot
][rm
]();
2608 case 0x1bc: /* bsf */
2609 case 0x1bd: /* bsr */
2610 ot
= dflag
? OT_LONG
: OT_WORD
;
2611 modrm
= ldub(s
->pc
++);
2612 reg
= (modrm
>> 3) & 7;
2613 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2614 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
2615 /* NOTE: we always write back the result. Intel doc says it is
2616 undefined if T0 == 0 */
2617 gen_op_mov_reg_T0
[ot
][reg
]();
2618 s
->cc_op
= CC_OP_LOGICB
+ ot
;
2620 /************************/
2622 case 0x27: /* daa */
2623 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2624 gen_op_set_cc_op(s
->cc_op
);
2626 s
->cc_op
= CC_OP_EFLAGS
;
2628 case 0x2f: /* das */
2629 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2630 gen_op_set_cc_op(s
->cc_op
);
2632 s
->cc_op
= CC_OP_EFLAGS
;
2634 case 0x37: /* aaa */
2635 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2636 gen_op_set_cc_op(s
->cc_op
);
2638 s
->cc_op
= CC_OP_EFLAGS
;
2640 case 0x3f: /* aas */
2641 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2642 gen_op_set_cc_op(s
->cc_op
);
2644 s
->cc_op
= CC_OP_EFLAGS
;
2646 case 0xd4: /* aam */
2647 val
= ldub(s
->pc
++);
2649 s
->cc_op
= CC_OP_LOGICB
;
2651 case 0xd5: /* aad */
2652 val
= ldub(s
->pc
++);
2654 s
->cc_op
= CC_OP_LOGICB
;
2656 /************************/
2658 case 0x90: /* nop */
2660 case 0xcc: /* int3 */
2661 gen_op_int3((long)pc_start
);
2664 case 0xcd: /* int N */
2665 val
= ldub(s
->pc
++);
2666 /* XXX: currently we ignore the interrupt number */
2667 gen_op_int_im((long)pc_start
);
2670 case 0xce: /* into */
2671 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2672 gen_op_set_cc_op(s
->cc_op
);
2673 gen_op_into((long)pc_start
, (long)s
->pc
);
2676 case 0x1c8 ... 0x1cf: /* bswap reg */
2678 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
2680 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
2682 case 0xd6: /* salc */
2683 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2684 gen_op_set_cc_op(s
->cc_op
);
2687 case 0x1a2: /* rdtsc */
2691 case 0x1a2: /* cpuid */
2696 error("unknown opcode 0x%x", b
);
2701 error("illegal opcode pc=0x%08Lx", (long)pc_start
);
2705 /* return the next pc */
2706 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
2707 int *gen_code_size_ptr
, uint8_t *pc_start
,
2710 DisasContext dc1
, *dc
= &dc1
;
2711 uint8_t *gen_code_end
, *pc_ptr
;
2714 struct disassemble_info disasm_info
;
2716 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
2717 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
2718 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
2719 dc
->cc_op
= CC_OP_DYNAMIC
;
2720 gen_code_ptr
= gen_code_buf
;
2721 gen_code_end
= gen_code_buf
+ max_code_size
- 4096;
2727 ret
= disas_insn(dc
, pc_ptr
);
2729 error("unknown instruction at PC=0x%x B=%02x %02x",
2730 pc_ptr
, pc_ptr
[0], pc_ptr
[1]);
2731 pc_ptr
= (void *)ret
;
2732 } while (!dc
->is_jmp
&& gen_code_ptr
< gen_code_end
);
2733 /* we must store the eflags state if it is not already done */
2734 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
2735 gen_op_set_cc_op(dc
->cc_op
);
2736 if (dc
->is_jmp
!= 1) {
2737 /* we add an additionnal jmp to update the simulated PC */
2741 *gen_code_size_ptr
= gen_code_ptr
- gen_code_buf
;
2748 INIT_DISASSEMBLE_INFO(disasm_info
, logfile
, fprintf
);
2750 disasm_info
.flavour
= bfd_get_flavour (abfd
);
2751 disasm_info
.arch
= bfd_get_arch (abfd
);
2752 disasm_info
.mach
= bfd_get_mach (abfd
);
2754 #ifdef WORDS_BIGENDIAN
2755 disasm_info
.endian
= BFD_ENDIAN_BIG
;
2757 disasm_info
.endian
= BFD_ENDIAN_LITTLE
;
2759 fprintf(logfile
, "IN:\n");
2760 disasm_info
.buffer
= pc_start
;
2761 disasm_info
.buffer_vma
= (unsigned long)pc_start
;
2762 disasm_info
.buffer_length
= pc_ptr
- pc_start
;
2764 while (pc
< pc_ptr
) {
2765 fprintf(logfile
, "0x%08lx: ", (long)pc
);
2766 count
= print_insn_i386((unsigned long)pc
, &disasm_info
);
2767 fprintf(logfile
, "\n");
2770 fprintf(logfile
, "\n");
2773 disasm_info
.buffer
= pc
;
2774 disasm_info
.buffer_vma
= (unsigned long)pc
;
2775 disasm_info
.buffer_length
= *gen_code_size_ptr
;
2776 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
2777 while (pc
< gen_code_ptr
) {
2778 fprintf(logfile
, "0x%08lx: ", (long)pc
);
2779 count
= print_insn_i386((unsigned long)pc
, &disasm_info
);
2780 fprintf(logfile
, "\n");
2783 fprintf(logfile
, "\n");
2789 CPUX86State
*cpu_x86_init(void)
2794 cpu_x86_tblocks_init();
2796 env
= malloc(sizeof(CPUX86State
));
2799 memset(env
, 0, sizeof(CPUX86State
));
2800 /* basic FPU init */
2801 for(i
= 0;i
< 8; i
++)
2805 env
->cc_op
= CC_OP_EFLAGS
;
2810 void cpu_x86_close(CPUX86State
*env
)