4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 /* XXX: move that elsewhere */
37 static uint16_t *gen_opc_ptr
;
38 static uint32_t *gen_opparam_ptr
;
39 int __op_param1
, __op_param2
, __op_param3
;
40 #ifdef USE_DIRECT_JUMP
41 int __op_jmp0
, __op_jmp1
;
45 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
51 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
57 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
64 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
66 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
70 p
= start
& ~(MIN_CACHE_LINE_SIZE
- 1);
71 stop
= (stop
+ MIN_CACHE_LINE_SIZE
- 1) & ~(MIN_CACHE_LINE_SIZE
- 1);
73 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
74 asm volatile ("dcbst 0,%0" : : "r"(p
) : "memory");
76 asm volatile ("sync" : : : "memory");
77 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
78 asm volatile ("icbi 0,%0" : : "r"(p
) : "memory");
80 asm volatile ("sync" : : : "memory");
81 asm volatile ("isync" : : : "memory");
86 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
94 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
98 p
= start
& ~(8UL - 1UL);
99 stop
= (stop
+ (8UL - 1UL)) & ~(8UL - 1UL);
101 for (; p
< stop
; p
+= 8)
102 __asm__
__volatile__("flush\t%0" : : "r" (p
));
107 extern FILE *logfile
;
110 #define PREFIX_REPZ 0x01
111 #define PREFIX_REPNZ 0x02
112 #define PREFIX_LOCK 0x04
113 #define PREFIX_DATA 0x08
114 #define PREFIX_ADR 0x10
116 typedef struct DisasContext
{
117 /* current insn context */
118 int override
; /* -1 if no override */
121 uint8_t *pc
; /* pc = eip + cs_base */
122 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
123 static state change (stop translation) */
124 /* current block context */
125 uint8_t *cs_base
; /* base of CS segment */
126 int code32
; /* 32 bit code segment */
127 int ss32
; /* 32 bit stack segment */
128 int cc_op
; /* current CC operation */
129 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
130 int f_st
; /* currently unused */
131 int vm86
; /* vm86 mode */
134 int tf
; /* TF cpu flag */
135 TranslationBlock
*tb
;
138 /* i386 arith/logic operations */
158 OP_SHL1
, /* undocumented */
163 #define DEF(s, n, copy_size) INDEX_op_ ## s,
164 #include "opc-i386.h"
180 /* I386 int registers */
181 OR_EAX
, /* MUST be even numbered */
189 OR_TMP0
, /* temporary operand register */
191 OR_A0
, /* temporary register used when doing address evaluation */
192 OR_ZERO
, /* fixed zero register */
196 typedef void (GenOpFunc
)(void);
197 typedef void (GenOpFunc1
)(long);
198 typedef void (GenOpFunc2
)(long, long);
199 typedef void (GenOpFunc3
)(long, long, long);
201 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
234 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
267 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
290 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
360 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
371 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
383 gen_op_addl_A0_EAX_s1
,
384 gen_op_addl_A0_ECX_s1
,
385 gen_op_addl_A0_EDX_s1
,
386 gen_op_addl_A0_EBX_s1
,
387 gen_op_addl_A0_ESP_s1
,
388 gen_op_addl_A0_EBP_s1
,
389 gen_op_addl_A0_ESI_s1
,
390 gen_op_addl_A0_EDI_s1
,
393 gen_op_addl_A0_EAX_s2
,
394 gen_op_addl_A0_ECX_s2
,
395 gen_op_addl_A0_EDX_s2
,
396 gen_op_addl_A0_EBX_s2
,
397 gen_op_addl_A0_ESP_s2
,
398 gen_op_addl_A0_EBP_s2
,
399 gen_op_addl_A0_ESI_s2
,
400 gen_op_addl_A0_EDI_s2
,
403 gen_op_addl_A0_EAX_s3
,
404 gen_op_addl_A0_ECX_s3
,
405 gen_op_addl_A0_EDX_s3
,
406 gen_op_addl_A0_EBX_s3
,
407 gen_op_addl_A0_ESP_s3
,
408 gen_op_addl_A0_EBP_s3
,
409 gen_op_addl_A0_ESI_s3
,
410 gen_op_addl_A0_EDI_s3
,
414 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
416 gen_op_cmovw_EAX_T1_T0
,
417 gen_op_cmovw_ECX_T1_T0
,
418 gen_op_cmovw_EDX_T1_T0
,
419 gen_op_cmovw_EBX_T1_T0
,
420 gen_op_cmovw_ESP_T1_T0
,
421 gen_op_cmovw_EBP_T1_T0
,
422 gen_op_cmovw_ESI_T1_T0
,
423 gen_op_cmovw_EDI_T1_T0
,
426 gen_op_cmovl_EAX_T1_T0
,
427 gen_op_cmovl_ECX_T1_T0
,
428 gen_op_cmovl_EDX_T1_T0
,
429 gen_op_cmovl_EBX_T1_T0
,
430 gen_op_cmovl_ESP_T1_T0
,
431 gen_op_cmovl_EBP_T1_T0
,
432 gen_op_cmovl_ESI_T1_T0
,
433 gen_op_cmovl_EDI_T1_T0
,
437 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
438 gen_op_addl_T0_T1_cc
,
442 gen_op_andl_T0_T1_cc
,
443 gen_op_subl_T0_T1_cc
,
444 gen_op_xorl_T0_T1_cc
,
445 gen_op_cmpl_T0_T1_cc
,
448 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
450 gen_op_adcb_T0_T1_cc
,
451 gen_op_sbbb_T0_T1_cc
,
454 gen_op_adcw_T0_T1_cc
,
455 gen_op_sbbw_T0_T1_cc
,
458 gen_op_adcl_T0_T1_cc
,
459 gen_op_sbbl_T0_T1_cc
,
463 static const int cc_op_arithb
[8] = {
474 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
475 gen_op_cmpxchgb_T0_T1_EAX_cc
,
476 gen_op_cmpxchgw_T0_T1_EAX_cc
,
477 gen_op_cmpxchgl_T0_T1_EAX_cc
,
480 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
482 gen_op_rolb_T0_T1_cc
,
483 gen_op_rorb_T0_T1_cc
,
484 gen_op_rclb_T0_T1_cc
,
485 gen_op_rcrb_T0_T1_cc
,
486 gen_op_shlb_T0_T1_cc
,
487 gen_op_shrb_T0_T1_cc
,
488 gen_op_shlb_T0_T1_cc
,
489 gen_op_sarb_T0_T1_cc
,
492 gen_op_rolw_T0_T1_cc
,
493 gen_op_rorw_T0_T1_cc
,
494 gen_op_rclw_T0_T1_cc
,
495 gen_op_rcrw_T0_T1_cc
,
496 gen_op_shlw_T0_T1_cc
,
497 gen_op_shrw_T0_T1_cc
,
498 gen_op_shlw_T0_T1_cc
,
499 gen_op_sarw_T0_T1_cc
,
502 gen_op_roll_T0_T1_cc
,
503 gen_op_rorl_T0_T1_cc
,
504 gen_op_rcll_T0_T1_cc
,
505 gen_op_rcrl_T0_T1_cc
,
506 gen_op_shll_T0_T1_cc
,
507 gen_op_shrl_T0_T1_cc
,
508 gen_op_shll_T0_T1_cc
,
509 gen_op_sarl_T0_T1_cc
,
513 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
515 gen_op_shldw_T0_T1_im_cc
,
516 gen_op_shrdw_T0_T1_im_cc
,
519 gen_op_shldl_T0_T1_im_cc
,
520 gen_op_shrdl_T0_T1_im_cc
,
524 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
526 gen_op_shldw_T0_T1_ECX_cc
,
527 gen_op_shrdw_T0_T1_ECX_cc
,
530 gen_op_shldl_T0_T1_ECX_cc
,
531 gen_op_shrdl_T0_T1_ECX_cc
,
535 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
538 gen_op_btsw_T0_T1_cc
,
539 gen_op_btrw_T0_T1_cc
,
540 gen_op_btcw_T0_T1_cc
,
544 gen_op_btsl_T0_T1_cc
,
545 gen_op_btrl_T0_T1_cc
,
546 gen_op_btcl_T0_T1_cc
,
550 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
561 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
566 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
571 /* sign does not matter */
572 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
578 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
584 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
590 /* the _a32 and _a16 string operations use A0 as the base register. */
592 #define STRINGOP(x) \
593 gen_op_ ## x ## b_fast, \
594 gen_op_ ## x ## w_fast, \
595 gen_op_ ## x ## l_fast, \
596 gen_op_ ## x ## b_a32, \
597 gen_op_ ## x ## w_a32, \
598 gen_op_ ## x ## l_a32, \
599 gen_op_ ## x ## b_a16, \
600 gen_op_ ## x ## w_a16, \
601 gen_op_ ## x ## l_a16,
603 static GenOpFunc
*gen_op_movs
[9 * 2] = {
608 static GenOpFunc
*gen_op_stos
[9 * 2] = {
613 static GenOpFunc
*gen_op_lods
[9 * 2] = {
618 static GenOpFunc
*gen_op_scas
[9 * 3] = {
624 static GenOpFunc
*gen_op_cmps
[9 * 3] = {
630 static GenOpFunc
*gen_op_ins
[9 * 2] = {
636 static GenOpFunc
*gen_op_outs
[9 * 2] = {
642 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
646 override
= s
->override
;
649 if (s
->addseg
&& override
< 0)
652 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
660 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
661 /* 16 address, always override */
667 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
684 static GenOpFunc
*gen_op_in
[3] = {
690 static GenOpFunc
*gen_op_out
[3] = {
707 static GenOpFunc3
*gen_jcc_sub
[3][8] = {
739 static GenOpFunc2
*gen_op_loop
[2][4] = {
754 static GenOpFunc
*gen_setcc_slow
[8] = {
765 static GenOpFunc
*gen_setcc_sub
[3][8] = {
770 gen_op_setbe_T0_subb
,
774 gen_op_setle_T0_subb
,
780 gen_op_setbe_T0_subw
,
784 gen_op_setle_T0_subw
,
790 gen_op_setbe_T0_subl
,
794 gen_op_setle_T0_subl
,
798 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
804 gen_op_fsubr_ST0_FT0
,
806 gen_op_fdivr_ST0_FT0
,
809 /* NOTE the exception in "r" op ordering */
810 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
815 gen_op_fsubr_STN_ST0
,
817 gen_op_fdivr_STN_ST0
,
821 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
824 gen_op_mov_TN_reg
[ot
][0][d
]();
826 gen_op_mov_TN_reg
[ot
][1][s
]();
827 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
828 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
829 gen_op_set_cc_op(s1
->cc_op
);
830 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
831 s1
->cc_op
= CC_OP_DYNAMIC
;
833 gen_op_arith_T0_T1_cc
[op
]();
834 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
836 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
837 gen_op_mov_reg_T0
[ot
][d
]();
840 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
842 gen_op_movl_T1_im(c
);
843 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
846 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
849 gen_op_mov_TN_reg
[ot
][0][d
]();
850 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
851 gen_op_set_cc_op(s1
->cc_op
);
854 s1
->cc_op
= CC_OP_INCB
+ ot
;
857 s1
->cc_op
= CC_OP_DECB
+ ot
;
860 gen_op_mov_reg_T0
[ot
][d
]();
863 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
866 gen_op_mov_TN_reg
[ot
][0][d
]();
868 gen_op_mov_TN_reg
[ot
][1][s
]();
869 /* for zero counts, flags are not updated, so must do it dynamically */
870 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
871 gen_op_set_cc_op(s1
->cc_op
);
873 gen_op_shift_T0_T1_cc
[ot
][op
]();
876 gen_op_mov_reg_T0
[ot
][d
]();
877 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
880 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
882 /* currently not optimized */
883 gen_op_movl_T1_im(c
);
884 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
887 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
894 int mod
, rm
, code
, override
, must_add_seg
;
896 override
= s
->override
;
897 must_add_seg
= s
->addseg
;
900 mod
= (modrm
>> 6) & 3;
912 code
= ldub(s
->pc
++);
913 scale
= (code
>> 6) & 3;
914 index
= (code
>> 3) & 7;
929 disp
= (int8_t)ldub(s
->pc
++);
939 gen_op_movl_A0_reg
[base
]();
941 gen_op_addl_A0_im(disp
);
943 gen_op_movl_A0_im(disp
);
945 if (havesib
&& (index
!= 4 || scale
!= 0)) {
946 gen_op_addl_A0_reg_sN
[scale
][index
]();
950 if (base
== R_EBP
|| base
== R_ESP
)
955 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
963 gen_op_movl_A0_im(disp
);
964 rm
= 0; /* avoid SS override */
971 disp
= (int8_t)ldub(s
->pc
++);
981 gen_op_movl_A0_reg
[R_EBX
]();
982 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
985 gen_op_movl_A0_reg
[R_EBX
]();
986 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
989 gen_op_movl_A0_reg
[R_EBP
]();
990 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
993 gen_op_movl_A0_reg
[R_EBP
]();
994 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
997 gen_op_movl_A0_reg
[R_ESI
]();
1000 gen_op_movl_A0_reg
[R_EDI
]();
1003 gen_op_movl_A0_reg
[R_EBP
]();
1007 gen_op_movl_A0_reg
[R_EBX
]();
1011 gen_op_addl_A0_im(disp
);
1012 gen_op_andl_A0_ffff();
1016 if (rm
== 2 || rm
== 3 || rm
== 6)
1021 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
1031 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1033 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1035 int mod
, rm
, opreg
, disp
;
1037 mod
= (modrm
>> 6) & 3;
1042 gen_op_mov_TN_reg
[ot
][0][reg
]();
1043 gen_op_mov_reg_T0
[ot
][rm
]();
1045 gen_op_mov_TN_reg
[ot
][0][rm
]();
1047 gen_op_mov_reg_T0
[ot
][reg
]();
1050 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1053 gen_op_mov_TN_reg
[ot
][0][reg
]();
1054 gen_op_st_T0_A0
[ot
]();
1056 gen_op_ld_T0_A0
[ot
]();
1058 gen_op_mov_reg_T0
[ot
][reg
]();
1063 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1085 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1087 TranslationBlock
*tb
;
1092 jcc_op
= (b
>> 1) & 7;
1094 /* we optimize the cmp/jcc case */
1098 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1101 /* some jumps are easy to compute */
1128 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1131 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1143 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1144 gen_op_set_cc_op(s
->cc_op
);
1147 gen_setcc_slow
[jcc_op
]();
1153 func((long)tb
, val
, next_eip
);
1155 func((long)tb
, next_eip
, val
);
1160 static void gen_setcc(DisasContext
*s
, int b
)
1166 jcc_op
= (b
>> 1) & 7;
1168 /* we optimize the cmp/jcc case */
1172 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1177 /* some jumps are easy to compute */
1195 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1198 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1206 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1207 gen_op_set_cc_op(s
->cc_op
);
1208 func
= gen_setcc_slow
[jcc_op
];
1217 /* move T0 to seg_reg and compute if the CPU state may change */
1218 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
, unsigned int cur_eip
)
1221 gen_op_movl_seg_T0(seg_reg
, cur_eip
);
1223 gen_op_movl_seg_T0_vm(offsetof(CPUX86State
,segs
[seg_reg
]),
1224 offsetof(CPUX86State
,seg_cache
[seg_reg
].base
));
1225 if (!s
->addseg
&& seg_reg
< R_FS
)
1226 s
->is_jmp
= 2; /* abort translation because the register may
1227 have a non zero base */
1230 /* generate a push. It depends on ss32, addseg and dflag */
1231 static void gen_push_T0(DisasContext
*s
)
1241 gen_op_pushl_ss32_T0();
1243 gen_op_pushw_ss32_T0();
1247 gen_op_pushl_ss16_T0();
1249 gen_op_pushw_ss16_T0();
1253 /* two step pop is necessary for precise exceptions */
1254 static void gen_pop_T0(DisasContext
*s
)
1264 gen_op_popl_ss32_T0();
1266 gen_op_popw_ss32_T0();
1270 gen_op_popl_ss16_T0();
1272 gen_op_popw_ss16_T0();
1276 static void gen_pop_update(DisasContext
*s
)
1280 gen_op_addl_ESP_4();
1282 gen_op_addl_ESP_2();
1285 gen_op_addw_ESP_4();
1287 gen_op_addw_ESP_2();
1291 /* NOTE: wrap around in 16 bit not fully handled */
1292 static void gen_pusha(DisasContext
*s
)
1295 gen_op_movl_A0_ESP();
1296 gen_op_addl_A0_im(-16 << s
->dflag
);
1298 gen_op_andl_A0_ffff();
1299 gen_op_movl_T1_A0();
1301 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1302 for(i
= 0;i
< 8; i
++) {
1303 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1304 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1305 gen_op_addl_A0_im(2 << s
->dflag
);
1307 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1310 /* NOTE: wrap around in 16 bit not fully handled */
1311 static void gen_popa(DisasContext
*s
)
1314 gen_op_movl_A0_ESP();
1316 gen_op_andl_A0_ffff();
1317 gen_op_movl_T1_A0();
1318 gen_op_addl_T1_im(16 << s
->dflag
);
1320 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1321 for(i
= 0;i
< 8; i
++) {
1322 /* ESP is not reloaded */
1324 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1325 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1327 gen_op_addl_A0_im(2 << s
->dflag
);
1329 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1332 /* NOTE: wrap around in 16 bit not fully handled */
1333 /* XXX: check this */
1334 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1336 int ot
, level1
, addend
, opsize
;
1338 ot
= s
->dflag
+ OT_WORD
;
1341 opsize
= 2 << s
->dflag
;
1343 gen_op_movl_A0_ESP();
1344 gen_op_addl_A0_im(-opsize
);
1346 gen_op_andl_A0_ffff();
1347 gen_op_movl_T1_A0();
1349 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1351 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1352 gen_op_st_T0_A0
[ot
]();
1355 gen_op_addl_A0_im(-opsize
);
1356 gen_op_addl_T0_im(-opsize
);
1357 gen_op_st_T0_A0
[ot
]();
1359 gen_op_addl_A0_im(-opsize
);
1360 /* XXX: add st_T1_A0 ? */
1361 gen_op_movl_T0_T1();
1362 gen_op_st_T0_A0
[ot
]();
1364 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1365 addend
= -esp_addend
;
1367 addend
-= opsize
* (level1
+ 1);
1368 gen_op_addl_T1_im(addend
);
1369 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1372 static void gen_exception(DisasContext
*s
, int trapno
, unsigned int cur_eip
)
1374 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1375 gen_op_set_cc_op(s
->cc_op
);
1376 gen_op_jmp_im(cur_eip
);
1377 gen_op_raise_exception(trapno
);
1381 /* an interrupt is different from an exception because of the
1382 priviledge checks */
1383 static void gen_interrupt(DisasContext
*s
, int intno
,
1384 unsigned int cur_eip
, unsigned int next_eip
)
1386 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1387 gen_op_set_cc_op(s
->cc_op
);
1388 gen_op_jmp_im(cur_eip
);
1389 gen_op_raise_interrupt(intno
, next_eip
);
1393 /* generate a jump to eip. No segment change must happen before as a
1394 direct call to the next block may occur */
1395 static void gen_jmp(DisasContext
*s
, unsigned int eip
)
1397 TranslationBlock
*tb
= s
->tb
;
1399 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1400 gen_op_set_cc_op(s
->cc_op
);
1401 gen_op_jmp_tb_next((long)tb
, eip
);
1405 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1406 is set to true if the instruction sets the PC (last instruction of
1408 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1410 int b
, prefixes
, aflag
, dflag
;
1412 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1413 unsigned int next_eip
;
1423 /* check prefixes */
1426 prefixes
|= PREFIX_REPZ
;
1429 prefixes
|= PREFIX_REPNZ
;
1432 prefixes
|= PREFIX_LOCK
;
1453 prefixes
|= PREFIX_DATA
;
1456 prefixes
|= PREFIX_ADR
;
1460 if (prefixes
& PREFIX_DATA
)
1462 if (prefixes
& PREFIX_ADR
)
1465 s
->prefix
= prefixes
;
1469 /* lock generation */
1470 if (prefixes
& PREFIX_LOCK
)
1473 /* now check op code */
1477 /**************************/
1478 /* extended op code */
1479 b
= ldub(s
->pc
++) | 0x100;
1482 /**************************/
1500 ot
= dflag
? OT_LONG
: OT_WORD
;
1503 case 0: /* OP Ev, Gv */
1504 modrm
= ldub(s
->pc
++);
1505 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1506 mod
= (modrm
>> 6) & 3;
1509 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1510 gen_op_ld_T0_A0
[ot
]();
1513 opreg
= OR_EAX
+ rm
;
1515 gen_op(s
, op
, ot
, opreg
, reg
);
1516 if (mod
!= 3 && op
!= 7) {
1517 gen_op_st_T0_A0
[ot
]();
1520 case 1: /* OP Gv, Ev */
1521 modrm
= ldub(s
->pc
++);
1522 mod
= (modrm
>> 6) & 3;
1523 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1526 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1527 gen_op_ld_T1_A0
[ot
]();
1530 opreg
= OR_EAX
+ rm
;
1532 gen_op(s
, op
, ot
, reg
, opreg
);
1534 case 2: /* OP A, Iv */
1535 val
= insn_get(s
, ot
);
1536 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1542 case 0x80: /* GRP1 */
1551 ot
= dflag
? OT_LONG
: OT_WORD
;
1553 modrm
= ldub(s
->pc
++);
1554 mod
= (modrm
>> 6) & 3;
1556 op
= (modrm
>> 3) & 7;
1559 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1560 gen_op_ld_T0_A0
[ot
]();
1563 opreg
= rm
+ OR_EAX
;
1570 val
= insn_get(s
, ot
);
1573 val
= (int8_t)insn_get(s
, OT_BYTE
);
1577 gen_opi(s
, op
, ot
, opreg
, val
);
1578 if (op
!= 7 && mod
!= 3) {
1579 gen_op_st_T0_A0
[ot
]();
1584 /**************************/
1585 /* inc, dec, and other misc arith */
1586 case 0x40 ... 0x47: /* inc Gv */
1587 ot
= dflag
? OT_LONG
: OT_WORD
;
1588 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1590 case 0x48 ... 0x4f: /* dec Gv */
1591 ot
= dflag
? OT_LONG
: OT_WORD
;
1592 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1594 case 0xf6: /* GRP3 */
1599 ot
= dflag
? OT_LONG
: OT_WORD
;
1601 modrm
= ldub(s
->pc
++);
1602 mod
= (modrm
>> 6) & 3;
1604 op
= (modrm
>> 3) & 7;
1606 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1607 gen_op_ld_T0_A0
[ot
]();
1609 gen_op_mov_TN_reg
[ot
][0][rm
]();
1614 val
= insn_get(s
, ot
);
1615 gen_op_movl_T1_im(val
);
1616 gen_op_testl_T0_T1_cc();
1617 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1622 gen_op_st_T0_A0
[ot
]();
1624 gen_op_mov_reg_T0
[ot
][rm
]();
1628 gen_op_negl_T0_cc();
1630 gen_op_st_T0_A0
[ot
]();
1632 gen_op_mov_reg_T0
[ot
][rm
]();
1634 s
->cc_op
= CC_OP_SUBB
+ ot
;
1639 gen_op_mulb_AL_T0();
1642 gen_op_mulw_AX_T0();
1646 gen_op_mull_EAX_T0();
1649 s
->cc_op
= CC_OP_MUL
;
1654 gen_op_imulb_AL_T0();
1657 gen_op_imulw_AX_T0();
1661 gen_op_imull_EAX_T0();
1664 s
->cc_op
= CC_OP_MUL
;
1669 gen_op_divb_AL_T0(pc_start
- s
->cs_base
);
1672 gen_op_divw_AX_T0(pc_start
- s
->cs_base
);
1676 gen_op_divl_EAX_T0(pc_start
- s
->cs_base
);
1683 gen_op_idivb_AL_T0(pc_start
- s
->cs_base
);
1686 gen_op_idivw_AX_T0(pc_start
- s
->cs_base
);
1690 gen_op_idivl_EAX_T0(pc_start
- s
->cs_base
);
1699 case 0xfe: /* GRP4 */
1700 case 0xff: /* GRP5 */
1704 ot
= dflag
? OT_LONG
: OT_WORD
;
1706 modrm
= ldub(s
->pc
++);
1707 mod
= (modrm
>> 6) & 3;
1709 op
= (modrm
>> 3) & 7;
1710 if (op
>= 2 && b
== 0xfe) {
1714 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1715 if (op
!= 3 && op
!= 5)
1716 gen_op_ld_T0_A0
[ot
]();
1718 gen_op_mov_TN_reg
[ot
][0][rm
]();
1722 case 0: /* inc Ev */
1723 gen_inc(s
, ot
, OR_TMP0
, 1);
1725 gen_op_st_T0_A0
[ot
]();
1727 gen_op_mov_reg_T0
[ot
][rm
]();
1729 case 1: /* dec Ev */
1730 gen_inc(s
, ot
, OR_TMP0
, -1);
1732 gen_op_st_T0_A0
[ot
]();
1734 gen_op_mov_reg_T0
[ot
][rm
]();
1736 case 2: /* call Ev */
1737 /* XXX: optimize if memory (no and is necessary) */
1739 gen_op_andl_T0_ffff();
1741 next_eip
= s
->pc
- s
->cs_base
;
1742 gen_op_movl_T0_im(next_eip
);
1746 case 3: /* lcall Ev */
1747 /* push return segment + offset */
1748 gen_op_movl_T0_seg(R_CS
);
1750 next_eip
= s
->pc
- s
->cs_base
;
1751 gen_op_movl_T0_im(next_eip
);
1754 gen_op_ld_T1_A0
[ot
]();
1755 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1756 gen_op_lduw_T0_A0();
1757 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
1758 gen_op_movl_T0_T1();
1762 case 4: /* jmp Ev */
1764 gen_op_andl_T0_ffff();
1768 case 5: /* ljmp Ev */
1769 gen_op_ld_T1_A0
[ot
]();
1770 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1771 gen_op_lduw_T0_A0();
1772 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
1773 gen_op_movl_T0_T1();
1777 case 6: /* push Ev */
1785 case 0x84: /* test Ev, Gv */
1790 ot
= dflag
? OT_LONG
: OT_WORD
;
1792 modrm
= ldub(s
->pc
++);
1793 mod
= (modrm
>> 6) & 3;
1795 reg
= (modrm
>> 3) & 7;
1797 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1798 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1799 gen_op_testl_T0_T1_cc();
1800 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1803 case 0xa8: /* test eAX, Iv */
1808 ot
= dflag
? OT_LONG
: OT_WORD
;
1809 val
= insn_get(s
, ot
);
1811 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1812 gen_op_movl_T1_im(val
);
1813 gen_op_testl_T0_T1_cc();
1814 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1817 case 0x98: /* CWDE/CBW */
1819 gen_op_movswl_EAX_AX();
1821 gen_op_movsbw_AX_AL();
1823 case 0x99: /* CDQ/CWD */
1825 gen_op_movslq_EDX_EAX();
1827 gen_op_movswl_DX_AX();
1829 case 0x1af: /* imul Gv, Ev */
1830 case 0x69: /* imul Gv, Ev, I */
1832 ot
= dflag
? OT_LONG
: OT_WORD
;
1833 modrm
= ldub(s
->pc
++);
1834 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1835 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1837 val
= insn_get(s
, ot
);
1838 gen_op_movl_T1_im(val
);
1839 } else if (b
== 0x6b) {
1840 val
= insn_get(s
, OT_BYTE
);
1841 gen_op_movl_T1_im(val
);
1843 gen_op_mov_TN_reg
[ot
][1][reg
]();
1846 if (ot
== OT_LONG
) {
1847 gen_op_imull_T0_T1();
1849 gen_op_imulw_T0_T1();
1851 gen_op_mov_reg_T0
[ot
][reg
]();
1852 s
->cc_op
= CC_OP_MUL
;
1855 case 0x1c1: /* xadd Ev, Gv */
1859 ot
= dflag
? OT_LONG
: OT_WORD
;
1860 modrm
= ldub(s
->pc
++);
1861 reg
= (modrm
>> 3) & 7;
1862 mod
= (modrm
>> 6) & 3;
1865 gen_op_mov_TN_reg
[ot
][0][reg
]();
1866 gen_op_mov_TN_reg
[ot
][1][rm
]();
1867 gen_op_addl_T0_T1_cc();
1868 gen_op_mov_reg_T0
[ot
][rm
]();
1869 gen_op_mov_reg_T1
[ot
][reg
]();
1871 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1872 gen_op_mov_TN_reg
[ot
][0][reg
]();
1873 gen_op_ld_T1_A0
[ot
]();
1874 gen_op_addl_T0_T1_cc();
1875 gen_op_st_T0_A0
[ot
]();
1876 gen_op_mov_reg_T1
[ot
][reg
]();
1878 s
->cc_op
= CC_OP_ADDB
+ ot
;
1881 case 0x1b1: /* cmpxchg Ev, Gv */
1885 ot
= dflag
? OT_LONG
: OT_WORD
;
1886 modrm
= ldub(s
->pc
++);
1887 reg
= (modrm
>> 3) & 7;
1888 mod
= (modrm
>> 6) & 3;
1889 gen_op_mov_TN_reg
[ot
][1][reg
]();
1892 gen_op_mov_TN_reg
[ot
][0][rm
]();
1893 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1894 gen_op_mov_reg_T0
[ot
][rm
]();
1896 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1897 gen_op_ld_T0_A0
[ot
]();
1898 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1899 gen_op_st_T0_A0
[ot
]();
1901 s
->cc_op
= CC_OP_SUBB
+ ot
;
1903 case 0x1c7: /* cmpxchg8b */
1904 modrm
= ldub(s
->pc
++);
1905 mod
= (modrm
>> 6) & 3;
1908 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1909 gen_op_set_cc_op(s
->cc_op
);
1910 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1912 s
->cc_op
= CC_OP_EFLAGS
;
1915 /**************************/
1917 case 0x50 ... 0x57: /* push */
1918 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1921 case 0x58 ... 0x5f: /* pop */
1922 ot
= dflag
? OT_LONG
: OT_WORD
;
1924 gen_op_mov_reg_T0
[ot
][b
& 7]();
1927 case 0x60: /* pusha */
1930 case 0x61: /* popa */
1933 case 0x68: /* push Iv */
1935 ot
= dflag
? OT_LONG
: OT_WORD
;
1937 val
= insn_get(s
, ot
);
1939 val
= (int8_t)insn_get(s
, OT_BYTE
);
1940 gen_op_movl_T0_im(val
);
1943 case 0x8f: /* pop Ev */
1944 ot
= dflag
? OT_LONG
: OT_WORD
;
1945 modrm
= ldub(s
->pc
++);
1947 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1950 case 0xc8: /* enter */
1955 level
= ldub(s
->pc
++);
1956 gen_enter(s
, val
, level
);
1959 case 0xc9: /* leave */
1960 /* XXX: exception not precise (ESP is update before potential exception) */
1962 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1963 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1965 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1966 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1969 ot
= dflag
? OT_LONG
: OT_WORD
;
1970 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1973 case 0x06: /* push es */
1974 case 0x0e: /* push cs */
1975 case 0x16: /* push ss */
1976 case 0x1e: /* push ds */
1977 gen_op_movl_T0_seg(b
>> 3);
1980 case 0x1a0: /* push fs */
1981 case 0x1a8: /* push gs */
1982 gen_op_movl_T0_seg((b
>> 3) & 7);
1985 case 0x07: /* pop es */
1986 case 0x17: /* pop ss */
1987 case 0x1f: /* pop ds */
1989 gen_movl_seg_T0(s
, b
>> 3, pc_start
- s
->cs_base
);
1992 case 0x1a1: /* pop fs */
1993 case 0x1a9: /* pop gs */
1995 gen_movl_seg_T0(s
, (b
>> 3) & 7, pc_start
- s
->cs_base
);
1999 /**************************/
2002 case 0x89: /* mov Gv, Ev */
2006 ot
= dflag
? OT_LONG
: OT_WORD
;
2007 modrm
= ldub(s
->pc
++);
2008 reg
= (modrm
>> 3) & 7;
2010 /* generate a generic store */
2011 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
2014 case 0xc7: /* mov Ev, Iv */
2018 ot
= dflag
? OT_LONG
: OT_WORD
;
2019 modrm
= ldub(s
->pc
++);
2020 mod
= (modrm
>> 6) & 3;
2022 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2023 val
= insn_get(s
, ot
);
2024 gen_op_movl_T0_im(val
);
2026 gen_op_st_T0_A0
[ot
]();
2028 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
2031 case 0x8b: /* mov Ev, Gv */
2035 ot
= dflag
? OT_LONG
: OT_WORD
;
2036 modrm
= ldub(s
->pc
++);
2037 reg
= (modrm
>> 3) & 7;
2039 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2040 gen_op_mov_reg_T0
[ot
][reg
]();
2042 case 0x8e: /* mov seg, Gv */
2043 ot
= dflag
? OT_LONG
: OT_WORD
;
2044 modrm
= ldub(s
->pc
++);
2045 reg
= (modrm
>> 3) & 7;
2046 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2047 if (reg
>= 6 || reg
== R_CS
)
2049 gen_movl_seg_T0(s
, reg
, pc_start
- s
->cs_base
);
2051 case 0x8c: /* mov Gv, seg */
2052 ot
= dflag
? OT_LONG
: OT_WORD
;
2053 modrm
= ldub(s
->pc
++);
2054 reg
= (modrm
>> 3) & 7;
2057 gen_op_movl_T0_seg(reg
);
2058 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2061 case 0x1b6: /* movzbS Gv, Eb */
2062 case 0x1b7: /* movzwS Gv, Eb */
2063 case 0x1be: /* movsbS Gv, Eb */
2064 case 0x1bf: /* movswS Gv, Eb */
2067 /* d_ot is the size of destination */
2068 d_ot
= dflag
+ OT_WORD
;
2069 /* ot is the size of source */
2070 ot
= (b
& 1) + OT_BYTE
;
2071 modrm
= ldub(s
->pc
++);
2072 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2073 mod
= (modrm
>> 6) & 3;
2077 gen_op_mov_TN_reg
[ot
][0][rm
]();
2078 switch(ot
| (b
& 8)) {
2080 gen_op_movzbl_T0_T0();
2083 gen_op_movsbl_T0_T0();
2086 gen_op_movzwl_T0_T0();
2090 gen_op_movswl_T0_T0();
2093 gen_op_mov_reg_T0
[d_ot
][reg
]();
2095 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2097 gen_op_lds_T0_A0
[ot
]();
2099 gen_op_ldu_T0_A0
[ot
]();
2101 gen_op_mov_reg_T0
[d_ot
][reg
]();
2106 case 0x8d: /* lea */
2107 ot
= dflag
? OT_LONG
: OT_WORD
;
2108 modrm
= ldub(s
->pc
++);
2109 reg
= (modrm
>> 3) & 7;
2110 /* we must ensure that no segment is added */
2114 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2116 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2119 case 0xa0: /* mov EAX, Ov */
2121 case 0xa2: /* mov Ov, EAX */
2126 ot
= dflag
? OT_LONG
: OT_WORD
;
2128 offset_addr
= insn_get(s
, OT_LONG
);
2130 offset_addr
= insn_get(s
, OT_WORD
);
2131 gen_op_movl_A0_im(offset_addr
);
2132 /* handle override */
2134 int override
, must_add_seg
;
2135 must_add_seg
= s
->addseg
;
2136 if (s
->override
>= 0) {
2137 override
= s
->override
;
2143 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2147 gen_op_ld_T0_A0
[ot
]();
2148 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2150 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2151 gen_op_st_T0_A0
[ot
]();
2154 case 0xd7: /* xlat */
2155 gen_op_movl_A0_reg
[R_EBX
]();
2156 gen_op_addl_A0_AL();
2158 gen_op_andl_A0_ffff();
2159 /* handle override */
2161 int override
, must_add_seg
;
2162 must_add_seg
= s
->addseg
;
2164 if (s
->override
>= 0) {
2165 override
= s
->override
;
2171 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2174 gen_op_ldub_T0_A0();
2175 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2177 case 0xb0 ... 0xb7: /* mov R, Ib */
2178 val
= insn_get(s
, OT_BYTE
);
2179 gen_op_movl_T0_im(val
);
2180 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2182 case 0xb8 ... 0xbf: /* mov R, Iv */
2183 ot
= dflag
? OT_LONG
: OT_WORD
;
2184 val
= insn_get(s
, ot
);
2185 reg
= OR_EAX
+ (b
& 7);
2186 gen_op_movl_T0_im(val
);
2187 gen_op_mov_reg_T0
[ot
][reg
]();
2190 case 0x91 ... 0x97: /* xchg R, EAX */
2191 ot
= dflag
? OT_LONG
: OT_WORD
;
2196 case 0x87: /* xchg Ev, Gv */
2200 ot
= dflag
? OT_LONG
: OT_WORD
;
2201 modrm
= ldub(s
->pc
++);
2202 reg
= (modrm
>> 3) & 7;
2203 mod
= (modrm
>> 6) & 3;
2207 gen_op_mov_TN_reg
[ot
][0][reg
]();
2208 gen_op_mov_TN_reg
[ot
][1][rm
]();
2209 gen_op_mov_reg_T0
[ot
][rm
]();
2210 gen_op_mov_reg_T1
[ot
][reg
]();
2212 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2213 gen_op_mov_TN_reg
[ot
][0][reg
]();
2214 /* for xchg, lock is implicit */
2215 if (!(prefixes
& PREFIX_LOCK
))
2217 gen_op_ld_T1_A0
[ot
]();
2218 gen_op_st_T0_A0
[ot
]();
2219 if (!(prefixes
& PREFIX_LOCK
))
2221 gen_op_mov_reg_T1
[ot
][reg
]();
2224 case 0xc4: /* les Gv */
2227 case 0xc5: /* lds Gv */
2230 case 0x1b2: /* lss Gv */
2233 case 0x1b4: /* lfs Gv */
2236 case 0x1b5: /* lgs Gv */
2239 ot
= dflag
? OT_LONG
: OT_WORD
;
2240 modrm
= ldub(s
->pc
++);
2241 reg
= (modrm
>> 3) & 7;
2242 mod
= (modrm
>> 6) & 3;
2245 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2246 gen_op_ld_T1_A0
[ot
]();
2247 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2248 /* load the segment first to handle exceptions properly */
2249 gen_op_lduw_T0_A0();
2250 gen_movl_seg_T0(s
, op
, pc_start
- s
->cs_base
);
2251 /* then put the data */
2252 gen_op_mov_reg_T1
[ot
][reg
]();
2255 /************************/
2266 ot
= dflag
? OT_LONG
: OT_WORD
;
2268 modrm
= ldub(s
->pc
++);
2269 mod
= (modrm
>> 6) & 3;
2271 op
= (modrm
>> 3) & 7;
2274 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2275 gen_op_ld_T0_A0
[ot
]();
2278 opreg
= rm
+ OR_EAX
;
2283 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2286 shift
= ldub(s
->pc
++);
2288 gen_shifti(s
, op
, ot
, opreg
, shift
);
2292 gen_op_st_T0_A0
[ot
]();
2307 case 0x1a4: /* shld imm */
2311 case 0x1a5: /* shld cl */
2315 case 0x1ac: /* shrd imm */
2319 case 0x1ad: /* shrd cl */
2323 ot
= dflag
? OT_LONG
: OT_WORD
;
2324 modrm
= ldub(s
->pc
++);
2325 mod
= (modrm
>> 6) & 3;
2327 reg
= (modrm
>> 3) & 7;
2330 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2331 gen_op_ld_T0_A0
[ot
]();
2333 gen_op_mov_TN_reg
[ot
][0][rm
]();
2335 gen_op_mov_TN_reg
[ot
][1][reg
]();
2338 val
= ldub(s
->pc
++);
2341 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2342 if (op
== 0 && ot
!= OT_WORD
)
2343 s
->cc_op
= CC_OP_SHLB
+ ot
;
2345 s
->cc_op
= CC_OP_SARB
+ ot
;
2348 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2349 gen_op_set_cc_op(s
->cc_op
);
2350 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2351 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2354 gen_op_st_T0_A0
[ot
]();
2356 gen_op_mov_reg_T0
[ot
][rm
]();
2360 /************************/
2363 modrm
= ldub(s
->pc
++);
2364 mod
= (modrm
>> 6) & 3;
2366 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2370 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2372 case 0x00 ... 0x07: /* fxxxs */
2373 case 0x10 ... 0x17: /* fixxxl */
2374 case 0x20 ... 0x27: /* fxxxl */
2375 case 0x30 ... 0x37: /* fixxx */
2382 gen_op_flds_FT0_A0();
2385 gen_op_fildl_FT0_A0();
2388 gen_op_fldl_FT0_A0();
2392 gen_op_fild_FT0_A0();
2396 gen_op_fp_arith_ST0_FT0
[op1
]();
2398 /* fcomp needs pop */
2403 case 0x08: /* flds */
2404 case 0x0a: /* fsts */
2405 case 0x0b: /* fstps */
2406 case 0x18: /* fildl */
2407 case 0x1a: /* fistl */
2408 case 0x1b: /* fistpl */
2409 case 0x28: /* fldl */
2410 case 0x2a: /* fstl */
2411 case 0x2b: /* fstpl */
2412 case 0x38: /* filds */
2413 case 0x3a: /* fists */
2414 case 0x3b: /* fistps */
2421 gen_op_flds_ST0_A0();
2424 gen_op_fildl_ST0_A0();
2427 gen_op_fldl_ST0_A0();
2431 gen_op_fild_ST0_A0();
2438 gen_op_fsts_ST0_A0();
2441 gen_op_fistl_ST0_A0();
2444 gen_op_fstl_ST0_A0();
2448 gen_op_fist_ST0_A0();
2456 case 0x0d: /* fldcw mem */
2459 case 0x0f: /* fnstcw mem */
2462 case 0x1d: /* fldt mem */
2464 gen_op_fldt_ST0_A0();
2466 case 0x1f: /* fstpt mem */
2467 gen_op_fstt_ST0_A0();
2470 case 0x2f: /* fnstsw mem */
2473 case 0x3c: /* fbld */
2475 gen_op_fbld_ST0_A0();
2477 case 0x3e: /* fbstp */
2478 gen_op_fbst_ST0_A0();
2481 case 0x3d: /* fildll */
2483 gen_op_fildll_ST0_A0();
2485 case 0x3f: /* fistpll */
2486 gen_op_fistll_ST0_A0();
2493 /* register float ops */
2497 case 0x08: /* fld sti */
2499 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2501 case 0x09: /* fxchg sti */
2502 gen_op_fxchg_ST0_STN(opreg
);
2504 case 0x0a: /* grp d9/2 */
2512 case 0x0c: /* grp d9/4 */
2522 gen_op_fcom_ST0_FT0();
2531 case 0x0d: /* grp d9/5 */
2540 gen_op_fldl2t_ST0();
2544 gen_op_fldl2e_ST0();
2552 gen_op_fldlg2_ST0();
2556 gen_op_fldln2_ST0();
2567 case 0x0e: /* grp d9/6 */
2578 case 3: /* fpatan */
2581 case 4: /* fxtract */
2584 case 5: /* fprem1 */
2587 case 6: /* fdecstp */
2591 case 7: /* fincstp */
2596 case 0x0f: /* grp d9/7 */
2601 case 1: /* fyl2xp1 */
2607 case 3: /* fsincos */
2610 case 5: /* fscale */
2613 case 4: /* frndint */
2625 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2626 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2627 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2633 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2637 gen_op_fmov_FT0_STN(opreg
);
2638 gen_op_fp_arith_ST0_FT0
[op1
]();
2642 case 0x02: /* fcom */
2643 gen_op_fmov_FT0_STN(opreg
);
2644 gen_op_fcom_ST0_FT0();
2646 case 0x03: /* fcomp */
2647 gen_op_fmov_FT0_STN(opreg
);
2648 gen_op_fcom_ST0_FT0();
2651 case 0x15: /* da/5 */
2653 case 1: /* fucompp */
2654 gen_op_fmov_FT0_STN(1);
2655 gen_op_fucom_ST0_FT0();
2668 case 3: /* fninit */
2675 case 0x2a: /* fst sti */
2676 gen_op_fmov_STN_ST0(opreg
);
2678 case 0x2b: /* fstp sti */
2679 gen_op_fmov_STN_ST0(opreg
);
2682 case 0x2c: /* fucom st(i) */
2683 gen_op_fmov_FT0_STN(opreg
);
2684 gen_op_fucom_ST0_FT0();
2686 case 0x2d: /* fucomp st(i) */
2687 gen_op_fmov_FT0_STN(opreg
);
2688 gen_op_fucom_ST0_FT0();
2691 case 0x33: /* de/3 */
2693 case 1: /* fcompp */
2694 gen_op_fmov_FT0_STN(1);
2695 gen_op_fcom_ST0_FT0();
2703 case 0x3c: /* df/4 */
2706 gen_op_fnstsw_EAX();
2717 /************************/
2720 case 0xa4: /* movsS */
2725 ot
= dflag
? OT_LONG
: OT_WORD
;
2727 if (prefixes
& PREFIX_REPZ
) {
2728 gen_string_ds(s
, ot
, gen_op_movs
+ 9);
2730 gen_string_ds(s
, ot
, gen_op_movs
);
2734 case 0xaa: /* stosS */
2739 ot
= dflag
? OT_LONG
: OT_WORD
;
2741 if (prefixes
& PREFIX_REPZ
) {
2742 gen_string_es(s
, ot
, gen_op_stos
+ 9);
2744 gen_string_es(s
, ot
, gen_op_stos
);
2747 case 0xac: /* lodsS */
2752 ot
= dflag
? OT_LONG
: OT_WORD
;
2753 if (prefixes
& PREFIX_REPZ
) {
2754 gen_string_ds(s
, ot
, gen_op_lods
+ 9);
2756 gen_string_ds(s
, ot
, gen_op_lods
);
2759 case 0xae: /* scasS */
2764 ot
= dflag
? OT_LONG
: OT_WORD
;
2765 if (prefixes
& PREFIX_REPNZ
) {
2766 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2767 gen_op_set_cc_op(s
->cc_op
);
2768 gen_string_es(s
, ot
, gen_op_scas
+ 9 * 2);
2769 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2770 } else if (prefixes
& PREFIX_REPZ
) {
2771 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2772 gen_op_set_cc_op(s
->cc_op
);
2773 gen_string_es(s
, ot
, gen_op_scas
+ 9);
2774 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2776 gen_string_es(s
, ot
, gen_op_scas
);
2777 s
->cc_op
= CC_OP_SUBB
+ ot
;
2781 case 0xa6: /* cmpsS */
2786 ot
= dflag
? OT_LONG
: OT_WORD
;
2787 if (prefixes
& PREFIX_REPNZ
) {
2788 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2789 gen_op_set_cc_op(s
->cc_op
);
2790 gen_string_ds(s
, ot
, gen_op_cmps
+ 9 * 2);
2791 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2792 } else if (prefixes
& PREFIX_REPZ
) {
2793 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2794 gen_op_set_cc_op(s
->cc_op
);
2795 gen_string_ds(s
, ot
, gen_op_cmps
+ 9);
2796 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2798 gen_string_ds(s
, ot
, gen_op_cmps
);
2799 s
->cc_op
= CC_OP_SUBB
+ ot
;
2802 case 0x6c: /* insS */
2804 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2805 /* NOTE: even for (E)CX = 0 the exception is raised */
2806 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2811 ot
= dflag
? OT_LONG
: OT_WORD
;
2812 if (prefixes
& PREFIX_REPZ
) {
2813 gen_string_es(s
, ot
, gen_op_ins
+ 9);
2815 gen_string_es(s
, ot
, gen_op_ins
);
2819 case 0x6e: /* outsS */
2821 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2822 /* NOTE: even for (E)CX = 0 the exception is raised */
2823 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2828 ot
= dflag
? OT_LONG
: OT_WORD
;
2829 if (prefixes
& PREFIX_REPZ
) {
2830 gen_string_ds(s
, ot
, gen_op_outs
+ 9);
2832 gen_string_ds(s
, ot
, gen_op_outs
);
2837 /************************/
2841 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2842 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2847 ot
= dflag
? OT_LONG
: OT_WORD
;
2848 val
= ldub(s
->pc
++);
2849 gen_op_movl_T0_im(val
);
2851 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2856 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2857 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2862 ot
= dflag
? OT_LONG
: OT_WORD
;
2863 val
= ldub(s
->pc
++);
2864 gen_op_movl_T0_im(val
);
2865 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2871 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2872 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2877 ot
= dflag
? OT_LONG
: OT_WORD
;
2878 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2880 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2885 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2886 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2891 ot
= dflag
? OT_LONG
: OT_WORD
;
2892 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2893 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2898 /************************/
2900 case 0xc2: /* ret im */
2905 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2907 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2909 gen_op_andl_T0_ffff();
2913 case 0xc3: /* ret */
2917 gen_op_andl_T0_ffff();
2921 case 0xca: /* lret im */
2922 /* XXX: not restartable */
2928 gen_op_andl_T0_ffff();
2933 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
2935 /* add stack offset */
2937 gen_op_addl_ESP_im(val
);
2939 gen_op_addw_ESP_im(val
);
2942 case 0xcb: /* lret */
2943 /* XXX: not restartable */
2947 gen_op_andl_T0_ffff();
2952 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
2956 case 0xcf: /* iret */
2957 if (s
->vm86
&& s
->iopl
!= 3) {
2958 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2960 /* XXX: not restartable */
2964 gen_op_andl_T0_ffff();
2969 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
2974 gen_op_movl_eflags_T0();
2976 gen_op_movw_eflags_T0();
2979 s
->cc_op
= CC_OP_EFLAGS
;
2983 case 0xe8: /* call im */
2985 unsigned int next_eip
;
2986 ot
= dflag
? OT_LONG
: OT_WORD
;
2987 val
= insn_get(s
, ot
);
2988 next_eip
= s
->pc
- s
->cs_base
;
2992 gen_op_movl_T0_im(next_eip
);
2997 case 0x9a: /* lcall im */
2999 unsigned int selector
, offset
;
3001 ot
= dflag
? OT_LONG
: OT_WORD
;
3002 offset
= insn_get(s
, ot
);
3003 selector
= insn_get(s
, OT_WORD
);
3005 /* push return segment + offset */
3006 gen_op_movl_T0_seg(R_CS
);
3008 next_eip
= s
->pc
- s
->cs_base
;
3009 gen_op_movl_T0_im(next_eip
);
3012 /* change cs and pc */
3013 gen_op_movl_T0_im(selector
);
3014 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
3015 gen_op_jmp_im((unsigned long)offset
);
3019 case 0xe9: /* jmp */
3020 ot
= dflag
? OT_LONG
: OT_WORD
;
3021 val
= insn_get(s
, ot
);
3022 val
+= s
->pc
- s
->cs_base
;
3027 case 0xea: /* ljmp im */
3029 unsigned int selector
, offset
;
3031 ot
= dflag
? OT_LONG
: OT_WORD
;
3032 offset
= insn_get(s
, ot
);
3033 selector
= insn_get(s
, OT_WORD
);
3035 /* change cs and pc */
3036 gen_op_movl_T0_im(selector
);
3037 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
3038 gen_op_jmp_im((unsigned long)offset
);
3042 case 0xeb: /* jmp Jb */
3043 val
= (int8_t)insn_get(s
, OT_BYTE
);
3044 val
+= s
->pc
- s
->cs_base
;
3049 case 0x70 ... 0x7f: /* jcc Jb */
3050 val
= (int8_t)insn_get(s
, OT_BYTE
);
3052 case 0x180 ... 0x18f: /* jcc Jv */
3054 val
= insn_get(s
, OT_LONG
);
3056 val
= (int16_t)insn_get(s
, OT_WORD
);
3059 next_eip
= s
->pc
- s
->cs_base
;
3063 gen_jcc(s
, b
, val
, next_eip
);
3066 case 0x190 ... 0x19f: /* setcc Gv */
3067 modrm
= ldub(s
->pc
++);
3069 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
3071 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3072 ot
= dflag
? OT_LONG
: OT_WORD
;
3073 modrm
= ldub(s
->pc
++);
3074 reg
= (modrm
>> 3) & 7;
3075 mod
= (modrm
>> 6) & 3;
3078 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3079 gen_op_ld_T1_A0
[ot
]();
3082 gen_op_mov_TN_reg
[ot
][1][rm
]();
3084 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
3087 /************************/
3089 case 0x9c: /* pushf */
3090 if (s
->vm86
&& s
->iopl
!= 3) {
3091 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3093 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3094 gen_op_set_cc_op(s
->cc_op
);
3095 gen_op_movl_T0_eflags();
3099 case 0x9d: /* popf */
3100 if (s
->vm86
&& s
->iopl
!= 3) {
3101 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3105 gen_op_movl_eflags_T0();
3107 gen_op_movw_eflags_T0();
3110 s
->cc_op
= CC_OP_EFLAGS
;
3111 s
->is_jmp
= 2; /* abort translation because TF flag may change */
3114 case 0x9e: /* sahf */
3115 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
3116 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3117 gen_op_set_cc_op(s
->cc_op
);
3118 gen_op_movb_eflags_T0();
3119 s
->cc_op
= CC_OP_EFLAGS
;
3121 case 0x9f: /* lahf */
3122 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3123 gen_op_set_cc_op(s
->cc_op
);
3124 gen_op_movl_T0_eflags();
3125 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
3127 case 0xf5: /* cmc */
3128 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3129 gen_op_set_cc_op(s
->cc_op
);
3131 s
->cc_op
= CC_OP_EFLAGS
;
3133 case 0xf8: /* clc */
3134 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3135 gen_op_set_cc_op(s
->cc_op
);
3137 s
->cc_op
= CC_OP_EFLAGS
;
3139 case 0xf9: /* stc */
3140 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3141 gen_op_set_cc_op(s
->cc_op
);
3143 s
->cc_op
= CC_OP_EFLAGS
;
3145 case 0xfc: /* cld */
3148 case 0xfd: /* std */
3152 /************************/
3153 /* bit operations */
3154 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3155 ot
= dflag
? OT_LONG
: OT_WORD
;
3156 modrm
= ldub(s
->pc
++);
3157 op
= (modrm
>> 3) & 7;
3158 mod
= (modrm
>> 6) & 3;
3161 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3162 gen_op_ld_T0_A0
[ot
]();
3164 gen_op_mov_TN_reg
[ot
][0][rm
]();
3167 val
= ldub(s
->pc
++);
3168 gen_op_movl_T1_im(val
);
3172 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3173 s
->cc_op
= CC_OP_SARB
+ ot
;
3176 gen_op_st_T0_A0
[ot
]();
3178 gen_op_mov_reg_T0
[ot
][rm
]();
3181 case 0x1a3: /* bt Gv, Ev */
3184 case 0x1ab: /* bts */
3187 case 0x1b3: /* btr */
3190 case 0x1bb: /* btc */
3193 ot
= dflag
? OT_LONG
: OT_WORD
;
3194 modrm
= ldub(s
->pc
++);
3195 reg
= (modrm
>> 3) & 7;
3196 mod
= (modrm
>> 6) & 3;
3198 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3200 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3201 /* specific case: we need to add a displacement */
3203 gen_op_add_bitw_A0_T1();
3205 gen_op_add_bitl_A0_T1();
3206 gen_op_ld_T0_A0
[ot
]();
3208 gen_op_mov_TN_reg
[ot
][0][rm
]();
3210 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3211 s
->cc_op
= CC_OP_SARB
+ ot
;
3214 gen_op_st_T0_A0
[ot
]();
3216 gen_op_mov_reg_T0
[ot
][rm
]();
3219 case 0x1bc: /* bsf */
3220 case 0x1bd: /* bsr */
3221 ot
= dflag
? OT_LONG
: OT_WORD
;
3222 modrm
= ldub(s
->pc
++);
3223 reg
= (modrm
>> 3) & 7;
3224 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3225 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3226 /* NOTE: we always write back the result. Intel doc says it is
3227 undefined if T0 == 0 */
3228 gen_op_mov_reg_T0
[ot
][reg
]();
3229 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3231 /************************/
3233 case 0x27: /* daa */
3234 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3235 gen_op_set_cc_op(s
->cc_op
);
3237 s
->cc_op
= CC_OP_EFLAGS
;
3239 case 0x2f: /* das */
3240 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3241 gen_op_set_cc_op(s
->cc_op
);
3243 s
->cc_op
= CC_OP_EFLAGS
;
3245 case 0x37: /* aaa */
3246 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3247 gen_op_set_cc_op(s
->cc_op
);
3249 s
->cc_op
= CC_OP_EFLAGS
;
3251 case 0x3f: /* aas */
3252 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3253 gen_op_set_cc_op(s
->cc_op
);
3255 s
->cc_op
= CC_OP_EFLAGS
;
3257 case 0xd4: /* aam */
3258 val
= ldub(s
->pc
++);
3260 s
->cc_op
= CC_OP_LOGICB
;
3262 case 0xd5: /* aad */
3263 val
= ldub(s
->pc
++);
3265 s
->cc_op
= CC_OP_LOGICB
;
3267 /************************/
3269 case 0x90: /* nop */
3271 case 0x9b: /* fwait */
3273 case 0xcc: /* int3 */
3274 gen_interrupt(s
, EXCP03_INT3
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3276 case 0xcd: /* int N */
3277 val
= ldub(s
->pc
++);
3278 /* XXX: add error code for vm86 GPF */
3280 gen_interrupt(s
, val
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3282 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3284 case 0xce: /* into */
3285 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3286 gen_op_set_cc_op(s
->cc_op
);
3287 gen_op_into(s
->pc
- s
->cs_base
);
3289 case 0xfa: /* cli */
3291 if (s
->cpl
<= s
->iopl
) {
3294 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3300 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3304 case 0xfb: /* sti */
3306 if (s
->cpl
<= s
->iopl
) {
3309 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3315 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3319 case 0x62: /* bound */
3320 ot
= dflag
? OT_LONG
: OT_WORD
;
3321 modrm
= ldub(s
->pc
++);
3322 reg
= (modrm
>> 3) & 7;
3323 mod
= (modrm
>> 6) & 3;
3326 gen_op_mov_reg_T0
[ot
][reg
]();
3327 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3329 gen_op_boundw(pc_start
- s
->cs_base
);
3331 gen_op_boundl(pc_start
- s
->cs_base
);
3333 case 0x1c8 ... 0x1cf: /* bswap reg */
3335 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3337 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3339 case 0xd6: /* salc */
3340 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3341 gen_op_set_cc_op(s
->cc_op
);
3344 case 0xe0: /* loopnz */
3345 case 0xe1: /* loopz */
3346 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3347 gen_op_set_cc_op(s
->cc_op
);
3349 case 0xe2: /* loop */
3350 case 0xe3: /* jecxz */
3351 val
= (int8_t)insn_get(s
, OT_BYTE
);
3352 next_eip
= s
->pc
- s
->cs_base
;
3356 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3359 case 0x131: /* rdtsc */
3362 case 0x1a2: /* cpuid */
3365 case 0xf4: /* hlt */
3366 /* XXX: if cpl == 0, then should do something else */
3367 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3369 case 0x102: /* lar */
3370 case 0x103: /* lsl */
3373 ot
= dflag
? OT_LONG
: OT_WORD
;
3374 modrm
= ldub(s
->pc
++);
3375 reg
= (modrm
>> 3) & 7;
3376 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3377 gen_op_mov_TN_reg
[ot
][1][reg
]();
3378 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3379 gen_op_set_cc_op(s
->cc_op
);
3384 s
->cc_op
= CC_OP_EFLAGS
;
3385 gen_op_mov_reg_T1
[ot
][reg
]();
3390 /* lock generation */
3391 if (s
->prefix
& PREFIX_LOCK
)
3395 /* XXX: ensure that no lock was generated */
3399 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3400 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3402 /* flags read by an operation */
3403 static uint16_t opc_read_flags
[NB_OPS
] = {
3404 [INDEX_op_aas
] = CC_A
,
3405 [INDEX_op_aaa
] = CC_A
,
3406 [INDEX_op_das
] = CC_A
| CC_C
,
3407 [INDEX_op_daa
] = CC_A
| CC_C
,
3409 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3410 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3411 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3412 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3413 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3414 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3416 /* subtle: due to the incl/decl implementation, C is used */
3417 [INDEX_op_incl_T0_cc
] = CC_C
,
3418 [INDEX_op_decl_T0_cc
] = CC_C
,
3420 [INDEX_op_into
] = CC_O
,
3422 [INDEX_op_jb_subb
] = CC_C
,
3423 [INDEX_op_jb_subw
] = CC_C
,
3424 [INDEX_op_jb_subl
] = CC_C
,
3426 [INDEX_op_jz_subb
] = CC_Z
,
3427 [INDEX_op_jz_subw
] = CC_Z
,
3428 [INDEX_op_jz_subl
] = CC_Z
,
3430 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3431 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3432 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3434 [INDEX_op_js_subb
] = CC_S
,
3435 [INDEX_op_js_subw
] = CC_S
,
3436 [INDEX_op_js_subl
] = CC_S
,
3438 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3439 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3440 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3442 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3443 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3444 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3446 [INDEX_op_loopnzw
] = CC_Z
,
3447 [INDEX_op_loopnzl
] = CC_Z
,
3448 [INDEX_op_loopzw
] = CC_Z
,
3449 [INDEX_op_loopzl
] = CC_Z
,
3451 [INDEX_op_seto_T0_cc
] = CC_O
,
3452 [INDEX_op_setb_T0_cc
] = CC_C
,
3453 [INDEX_op_setz_T0_cc
] = CC_Z
,
3454 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3455 [INDEX_op_sets_T0_cc
] = CC_S
,
3456 [INDEX_op_setp_T0_cc
] = CC_P
,
3457 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3458 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3460 [INDEX_op_setb_T0_subb
] = CC_C
,
3461 [INDEX_op_setb_T0_subw
] = CC_C
,
3462 [INDEX_op_setb_T0_subl
] = CC_C
,
3464 [INDEX_op_setz_T0_subb
] = CC_Z
,
3465 [INDEX_op_setz_T0_subw
] = CC_Z
,
3466 [INDEX_op_setz_T0_subl
] = CC_Z
,
3468 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3469 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3470 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3472 [INDEX_op_sets_T0_subb
] = CC_S
,
3473 [INDEX_op_sets_T0_subw
] = CC_S
,
3474 [INDEX_op_sets_T0_subl
] = CC_S
,
3476 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3477 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3478 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3480 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3481 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3482 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3484 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3485 [INDEX_op_cmc
] = CC_C
,
3486 [INDEX_op_salc
] = CC_C
,
3488 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3489 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3490 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3491 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3492 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3493 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3496 /* flags written by an operation */
3497 static uint16_t opc_write_flags
[NB_OPS
] = {
3498 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3499 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3500 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3501 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3502 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3503 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3504 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3505 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3506 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3507 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3508 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3509 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3510 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3511 /* subtle: due to the incl/decl implementation, C is used */
3512 [INDEX_op_incl_T0_cc
] = CC_OSZAPC
,
3513 [INDEX_op_decl_T0_cc
] = CC_OSZAPC
,
3514 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3516 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3517 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3518 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3519 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3520 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3521 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3522 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3523 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3526 [INDEX_op_aam
] = CC_OSZAPC
,
3527 [INDEX_op_aad
] = CC_OSZAPC
,
3528 [INDEX_op_aas
] = CC_OSZAPC
,
3529 [INDEX_op_aaa
] = CC_OSZAPC
,
3530 [INDEX_op_das
] = CC_OSZAPC
,
3531 [INDEX_op_daa
] = CC_OSZAPC
,
3533 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3534 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
3535 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3536 [INDEX_op_clc
] = CC_C
,
3537 [INDEX_op_stc
] = CC_C
,
3538 [INDEX_op_cmc
] = CC_C
,
3540 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3541 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3542 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3543 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3544 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3545 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3547 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3548 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3549 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3550 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3551 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3552 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3554 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3555 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3556 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3558 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3559 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3560 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3562 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3563 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3564 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3566 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3567 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3568 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3569 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3571 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3572 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3573 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3574 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3576 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3577 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3578 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3579 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3580 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3581 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3582 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3583 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3585 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3586 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3587 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3588 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3591 #define STRINGOP(x) \
3592 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3593 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3594 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3595 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3596 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3597 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3598 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3599 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3600 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3604 STRINGOP(repnz_scas
)
3607 STRINGOP(repnz_cmps
)
3609 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
3610 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3611 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3613 [INDEX_op_cmpxchg8b
] = CC_Z
,
3614 [INDEX_op_lar
] = CC_Z
,
3615 [INDEX_op_lsl
] = CC_Z
,
3618 /* simpler form of an operation if no flags need to be generated */
3619 static uint16_t opc_simpler
[NB_OPS
] = {
3620 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3621 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3622 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3623 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3624 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3625 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3626 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3627 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3629 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3630 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3631 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3633 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3634 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3635 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3637 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3638 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3639 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3641 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3642 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3643 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3645 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3646 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3647 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3650 static void optimize_flags_init(void)
3653 /* put default values in arrays */
3654 for(i
= 0; i
< NB_OPS
; i
++) {
3655 if (opc_simpler
[i
] == 0)
3660 /* CPU flags computation optimization: we move backward thru the
3661 generated code to see which flags are needed. The operation is
3662 modified if suitable */
3663 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3666 int live_flags
, write_flags
, op
;
3668 opc_ptr
= opc_buf
+ opc_buf_len
;
3669 /* live_flags contains the flags needed by the next instructions
3670 in the code. At the end of the bloc, we consider that all the
3672 live_flags
= CC_OSZAPC
;
3673 while (opc_ptr
> opc_buf
) {
3675 /* if none of the flags written by the instruction is used,
3676 then we can try to find a simpler instruction */
3677 write_flags
= opc_write_flags
[op
];
3678 if ((live_flags
& write_flags
) == 0) {
3679 *opc_ptr
= opc_simpler
[op
];
3681 /* compute the live flags before the instruction */
3682 live_flags
&= ~write_flags
;
3683 live_flags
|= opc_read_flags
[op
];
3689 static const char *op_str
[] = {
3690 #define DEF(s, n, copy_size) #s,
3691 #include "opc-i386.h"
3695 static uint8_t op_nb_args
[] = {
3696 #define DEF(s, n, copy_size) n,
3697 #include "opc-i386.h"
3701 static void dump_ops(const uint16_t *opc_buf
, const uint32_t *opparam_buf
)
3703 const uint16_t *opc_ptr
;
3704 const uint32_t *opparam_ptr
;
3708 opparam_ptr
= opparam_buf
;
3712 fprintf(logfile
, "0x%04x: %s",
3713 (int)(opc_ptr
- opc_buf
- 1), op_str
[c
]);
3714 for(i
= 0; i
< n
; i
++) {
3715 fprintf(logfile
, " 0x%x", opparam_ptr
[i
]);
3717 fprintf(logfile
, "\n");
3718 if (c
== INDEX_op_end
)
3726 /* XXX: make safe guess about sizes */
3727 #define MAX_OP_PER_INSTR 32
3728 #define OPC_BUF_SIZE 512
3729 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3731 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3733 static uint16_t gen_opc_buf
[OPC_BUF_SIZE
];
3734 static uint32_t gen_opparam_buf
[OPPARAM_BUF_SIZE
];
3735 static uint32_t gen_opc_pc
[OPC_BUF_SIZE
];
3736 static uint8_t gen_opc_instr_start
[OPC_BUF_SIZE
];
3738 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3739 basic block 'tb'. If search_pc is TRUE, also generate PC
3740 information for each intermediate instruction. */
3741 static inline int gen_intermediate_code(TranslationBlock
*tb
, int search_pc
)
3743 DisasContext dc1
, *dc
= &dc1
;
3745 uint16_t *gen_opc_end
;
3751 /* generate intermediate code */
3752 pc_start
= (uint8_t *)tb
->pc
;
3753 cs_base
= (uint8_t *)tb
->cs_base
;
3756 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3757 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3758 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3759 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3760 dc
->vm86
= (flags
>> GEN_FLAG_VM_SHIFT
) & 1;
3761 dc
->cpl
= (flags
>> GEN_FLAG_CPL_SHIFT
) & 3;
3762 dc
->iopl
= (flags
>> GEN_FLAG_IOPL_SHIFT
) & 3;
3763 dc
->tf
= (flags
>> GEN_FLAG_TF_SHIFT
) & 1;
3764 dc
->cc_op
= CC_OP_DYNAMIC
;
3765 dc
->cs_base
= cs_base
;
3768 gen_opc_ptr
= gen_opc_buf
;
3769 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3770 gen_opparam_ptr
= gen_opparam_buf
;
3777 j
= gen_opc_ptr
- gen_opc_buf
;
3781 gen_opc_instr_start
[lj
++] = 0;
3782 gen_opc_pc
[lj
] = (uint32_t)pc_ptr
;
3783 gen_opc_instr_start
[lj
] = 1;
3786 ret
= disas_insn(dc
, pc_ptr
);
3788 /* we trigger an illegal instruction operation only if it
3789 is the first instruction. Otherwise, we simply stop
3790 generating the code just before it */
3791 if (pc_ptr
== pc_start
)
3796 pc_ptr
= (void *)ret
;
3797 /* if single step mode, we generate only one instruction and
3798 generate an exception */
3801 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
3802 (pc_ptr
- pc_start
) < (TARGET_PAGE_SIZE
- 32));
3803 /* we must store the eflags state if it is not already done */
3804 if (dc
->is_jmp
!= 3) {
3805 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3806 gen_op_set_cc_op(dc
->cc_op
);
3807 if (dc
->is_jmp
!= 1) {
3808 /* we add an additionnal jmp to update the simulated PC */
3809 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3813 gen_op_raise_exception(EXCP01_SSTP
);
3815 if (dc
->is_jmp
!= 3) {
3816 /* indicate that the hash table must be used to find the next TB */
3820 *gen_opc_ptr
= INDEX_op_end
;
3824 fprintf(logfile
, "----------------\n");
3825 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
3826 disas(logfile
, pc_start
, pc_ptr
- pc_start
,
3827 dc
->code32
? DISAS_I386_I386
: DISAS_I386_I8086
);
3828 fprintf(logfile
, "\n");
3830 fprintf(logfile
, "OP:\n");
3831 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3832 fprintf(logfile
, "\n");
3836 /* optimize flag computations */
3837 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3841 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3842 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3843 fprintf(logfile
, "\n");
3847 tb
->size
= pc_ptr
- pc_start
;
3852 /* return non zero if the very first instruction is invalid so that
3853 the virtual CPU can trigger an exception.
3855 '*gen_code_size_ptr' contains the size of the generated code (host
3858 int cpu_x86_gen_code(TranslationBlock
*tb
,
3859 int max_code_size
, int *gen_code_size_ptr
)
3861 uint8_t *gen_code_buf
;
3864 if (gen_intermediate_code(tb
, 0) < 0)
3867 /* generate machine code */
3868 tb
->tb_next_offset
[0] = 0xffff;
3869 tb
->tb_next_offset
[1] = 0xffff;
3870 gen_code_buf
= tb
->tc_ptr
;
3871 gen_code_size
= dyngen_code(gen_code_buf
, tb
->tb_next_offset
,
3872 #ifdef USE_DIRECT_JUMP
3877 gen_opc_buf
, gen_opparam_buf
);
3878 flush_icache_range((unsigned long)gen_code_buf
, (unsigned long)(gen_code_buf
+ gen_code_size
));
3880 *gen_code_size_ptr
= gen_code_size
;
3883 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
3884 disas(logfile
, gen_code_buf
, *gen_code_size_ptr
, DISAS_TARGET
);
3885 fprintf(logfile
, "\n");
3892 static const unsigned short opc_copy_size
[] = {
3893 #define DEF(s, n, copy_size) copy_size,
3894 #include "opc-i386.h"
3898 /* The simulated PC corresponding to
3899 'searched_pc' in the generated code is searched. 0 is returned if
3900 found. *found_pc contains the found PC.
3902 int cpu_x86_search_pc(TranslationBlock
*tb
,
3903 uint32_t *found_pc
, unsigned long searched_pc
)
3906 unsigned long tc_ptr
;
3909 if (gen_intermediate_code(tb
, 1) < 0)
3912 /* find opc index corresponding to search_pc */
3913 tc_ptr
= (unsigned long)tb
->tc_ptr
;
3914 if (searched_pc
< tc_ptr
)
3917 opc_ptr
= gen_opc_buf
;
3920 if (c
== INDEX_op_end
)
3922 tc_ptr
+= opc_copy_size
[c
];
3923 if (searched_pc
< tc_ptr
)
3927 j
= opc_ptr
- gen_opc_buf
;
3928 /* now find start of instruction before */
3929 while (gen_opc_instr_start
[j
] == 0)
3931 *found_pc
= gen_opc_pc
[j
];
3936 CPUX86State
*cpu_x86_init(void)
3942 cpu_x86_tblocks_init();
3944 env
= malloc(sizeof(CPUX86State
));
3947 memset(env
, 0, sizeof(CPUX86State
));
3948 /* basic FPU init */
3949 for(i
= 0;i
< 8; i
++)
3952 /* flags setup : we activate the IRQs by default as in user mode */
3953 env
->eflags
= 0x2 | IF_MASK
;
3955 /* init various static tables */
3958 optimize_flags_init();
3964 void cpu_x86_close(CPUX86State
*env
)
3969 static const char *cc_op_str
[] = {
4002 void cpu_x86_dump_state(CPUX86State
*env
, FILE *f
, int flags
)
4005 char cc_op_name
[32];
4007 eflags
= env
->eflags
;
4008 fprintf(f
, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4009 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4010 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4011 env
->regs
[R_EAX
], env
->regs
[R_EBX
], env
->regs
[R_ECX
], env
->regs
[R_EDX
],
4012 env
->regs
[R_ESI
], env
->regs
[R_EDI
], env
->regs
[R_EBP
], env
->regs
[R_ESP
],
4014 eflags
& DF_MASK
? 'D' : '-',
4015 eflags
& CC_O
? 'O' : '-',
4016 eflags
& CC_S
? 'S' : '-',
4017 eflags
& CC_Z
? 'Z' : '-',
4018 eflags
& CC_A
? 'A' : '-',
4019 eflags
& CC_P
? 'P' : '-',
4020 eflags
& CC_C
? 'C' : '-');
4021 fprintf(f
, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4028 if (flags
& X86_DUMP_CCOP
) {
4029 if ((unsigned)env
->cc_op
< CC_OP_NB
)
4030 strcpy(cc_op_name
, cc_op_str
[env
->cc_op
]);
4032 snprintf(cc_op_name
, sizeof(cc_op_name
), "[%d]", env
->cc_op
);
4033 fprintf(f
, "CCS=%08x CCD=%08x CCO=%-8s\n",
4034 env
->cc_src
, env
->cc_dst
, cc_op_name
);
4036 if (flags
& X86_DUMP_FPU
) {
4037 fprintf(f
, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
4038 (double)env
->fpregs
[0],
4039 (double)env
->fpregs
[1],
4040 (double)env
->fpregs
[2],
4041 (double)env
->fpregs
[3]);
4042 fprintf(f
, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
4043 (double)env
->fpregs
[4],
4044 (double)env
->fpregs
[5],
4045 (double)env
->fpregs
[7],
4046 (double)env
->fpregs
[8]);