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
32 /* XXX: move that elsewhere */
33 static uint16_t *gen_opc_ptr
;
34 static uint32_t *gen_opparam_ptr
;
36 #define PREFIX_REPZ 0x01
37 #define PREFIX_REPNZ 0x02
38 #define PREFIX_LOCK 0x04
39 #define PREFIX_DATA 0x08
40 #define PREFIX_ADR 0x10
42 typedef struct DisasContext
{
43 /* current insn context */
44 int override
; /* -1 if no override */
47 uint8_t *pc
; /* pc = eip + cs_base */
48 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
49 static state change (stop translation) */
50 /* current block context */
51 uint8_t *cs_base
; /* base of CS segment */
52 int code32
; /* 32 bit code segment */
53 int ss32
; /* 32 bit stack segment */
54 int cc_op
; /* current CC operation */
55 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
56 int f_st
; /* currently unused */
57 int vm86
; /* vm86 mode */
60 int tf
; /* TF cpu flag */
61 struct TranslationBlock
*tb
;
64 /* i386 arith/logic operations */
84 OP_SHL1
, /* undocumented */
89 #define DEF(s, n, copy_size) INDEX_op_ ## s,
95 #include "gen-op-i386.h"
106 /* I386 int registers */
107 OR_EAX
, /* MUST be even numbered */
115 OR_TMP0
, /* temporary operand register */
117 OR_A0
, /* temporary register used when doing address evaluation */
118 OR_ZERO
, /* fixed zero register */
122 typedef void (GenOpFunc
)(void);
123 typedef void (GenOpFunc1
)(long);
124 typedef void (GenOpFunc2
)(long, long);
125 typedef void (GenOpFunc3
)(long, long, long);
127 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
160 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
193 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
216 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
286 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
297 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
309 gen_op_addl_A0_EAX_s1
,
310 gen_op_addl_A0_ECX_s1
,
311 gen_op_addl_A0_EDX_s1
,
312 gen_op_addl_A0_EBX_s1
,
313 gen_op_addl_A0_ESP_s1
,
314 gen_op_addl_A0_EBP_s1
,
315 gen_op_addl_A0_ESI_s1
,
316 gen_op_addl_A0_EDI_s1
,
319 gen_op_addl_A0_EAX_s2
,
320 gen_op_addl_A0_ECX_s2
,
321 gen_op_addl_A0_EDX_s2
,
322 gen_op_addl_A0_EBX_s2
,
323 gen_op_addl_A0_ESP_s2
,
324 gen_op_addl_A0_EBP_s2
,
325 gen_op_addl_A0_ESI_s2
,
326 gen_op_addl_A0_EDI_s2
,
329 gen_op_addl_A0_EAX_s3
,
330 gen_op_addl_A0_ECX_s3
,
331 gen_op_addl_A0_EDX_s3
,
332 gen_op_addl_A0_EBX_s3
,
333 gen_op_addl_A0_ESP_s3
,
334 gen_op_addl_A0_EBP_s3
,
335 gen_op_addl_A0_ESI_s3
,
336 gen_op_addl_A0_EDI_s3
,
340 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
342 gen_op_cmovw_EAX_T1_T0
,
343 gen_op_cmovw_ECX_T1_T0
,
344 gen_op_cmovw_EDX_T1_T0
,
345 gen_op_cmovw_EBX_T1_T0
,
346 gen_op_cmovw_ESP_T1_T0
,
347 gen_op_cmovw_EBP_T1_T0
,
348 gen_op_cmovw_ESI_T1_T0
,
349 gen_op_cmovw_EDI_T1_T0
,
352 gen_op_cmovl_EAX_T1_T0
,
353 gen_op_cmovl_ECX_T1_T0
,
354 gen_op_cmovl_EDX_T1_T0
,
355 gen_op_cmovl_EBX_T1_T0
,
356 gen_op_cmovl_ESP_T1_T0
,
357 gen_op_cmovl_EBP_T1_T0
,
358 gen_op_cmovl_ESI_T1_T0
,
359 gen_op_cmovl_EDI_T1_T0
,
363 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
364 gen_op_addl_T0_T1_cc
,
368 gen_op_andl_T0_T1_cc
,
369 gen_op_subl_T0_T1_cc
,
370 gen_op_xorl_T0_T1_cc
,
371 gen_op_cmpl_T0_T1_cc
,
374 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
376 gen_op_adcb_T0_T1_cc
,
377 gen_op_sbbb_T0_T1_cc
,
380 gen_op_adcw_T0_T1_cc
,
381 gen_op_sbbw_T0_T1_cc
,
384 gen_op_adcl_T0_T1_cc
,
385 gen_op_sbbl_T0_T1_cc
,
389 static const int cc_op_arithb
[8] = {
400 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
401 gen_op_cmpxchgb_T0_T1_EAX_cc
,
402 gen_op_cmpxchgw_T0_T1_EAX_cc
,
403 gen_op_cmpxchgl_T0_T1_EAX_cc
,
406 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
408 gen_op_rolb_T0_T1_cc
,
409 gen_op_rorb_T0_T1_cc
,
410 gen_op_rclb_T0_T1_cc
,
411 gen_op_rcrb_T0_T1_cc
,
412 gen_op_shlb_T0_T1_cc
,
413 gen_op_shrb_T0_T1_cc
,
414 gen_op_shlb_T0_T1_cc
,
415 gen_op_sarb_T0_T1_cc
,
418 gen_op_rolw_T0_T1_cc
,
419 gen_op_rorw_T0_T1_cc
,
420 gen_op_rclw_T0_T1_cc
,
421 gen_op_rcrw_T0_T1_cc
,
422 gen_op_shlw_T0_T1_cc
,
423 gen_op_shrw_T0_T1_cc
,
424 gen_op_shlw_T0_T1_cc
,
425 gen_op_sarw_T0_T1_cc
,
428 gen_op_roll_T0_T1_cc
,
429 gen_op_rorl_T0_T1_cc
,
430 gen_op_rcll_T0_T1_cc
,
431 gen_op_rcrl_T0_T1_cc
,
432 gen_op_shll_T0_T1_cc
,
433 gen_op_shrl_T0_T1_cc
,
434 gen_op_shll_T0_T1_cc
,
435 gen_op_sarl_T0_T1_cc
,
439 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
441 gen_op_shldw_T0_T1_im_cc
,
442 gen_op_shrdw_T0_T1_im_cc
,
445 gen_op_shldl_T0_T1_im_cc
,
446 gen_op_shrdl_T0_T1_im_cc
,
450 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
452 gen_op_shldw_T0_T1_ECX_cc
,
453 gen_op_shrdw_T0_T1_ECX_cc
,
456 gen_op_shldl_T0_T1_ECX_cc
,
457 gen_op_shrdl_T0_T1_ECX_cc
,
461 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
464 gen_op_btsw_T0_T1_cc
,
465 gen_op_btrw_T0_T1_cc
,
466 gen_op_btcw_T0_T1_cc
,
470 gen_op_btsl_T0_T1_cc
,
471 gen_op_btrl_T0_T1_cc
,
472 gen_op_btcl_T0_T1_cc
,
476 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
487 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
492 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
497 /* sign does not matter */
498 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
504 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
510 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
516 /* the _a32 and _a16 string operations use A0 as the base register. */
518 #define STRINGOP(x) \
519 gen_op_ ## x ## b_fast, \
520 gen_op_ ## x ## w_fast, \
521 gen_op_ ## x ## l_fast, \
522 gen_op_ ## x ## b_a32, \
523 gen_op_ ## x ## w_a32, \
524 gen_op_ ## x ## l_a32, \
525 gen_op_ ## x ## b_a16, \
526 gen_op_ ## x ## w_a16, \
527 gen_op_ ## x ## l_a16,
529 static GenOpFunc
*gen_op_movs
[9 * 2] = {
534 static GenOpFunc
*gen_op_stos
[9 * 2] = {
539 static GenOpFunc
*gen_op_lods
[9 * 2] = {
544 static GenOpFunc
*gen_op_scas
[9 * 3] = {
550 static GenOpFunc
*gen_op_cmps
[9 * 3] = {
556 static GenOpFunc
*gen_op_ins
[9 * 2] = {
562 static GenOpFunc
*gen_op_outs
[9 * 2] = {
568 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
572 override
= s
->override
;
575 if (s
->addseg
&& override
< 0)
578 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
586 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
587 /* 16 address, always override */
593 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
610 static GenOpFunc
*gen_op_in
[3] = {
616 static GenOpFunc
*gen_op_out
[3] = {
633 static GenOpFunc3
*gen_jcc_sub
[3][8] = {
665 static GenOpFunc2
*gen_op_loop
[2][4] = {
680 static GenOpFunc
*gen_setcc_slow
[8] = {
691 static GenOpFunc
*gen_setcc_sub
[3][8] = {
696 gen_op_setbe_T0_subb
,
700 gen_op_setle_T0_subb
,
706 gen_op_setbe_T0_subw
,
710 gen_op_setle_T0_subw
,
716 gen_op_setbe_T0_subl
,
720 gen_op_setle_T0_subl
,
724 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
730 gen_op_fsubr_ST0_FT0
,
732 gen_op_fdivr_ST0_FT0
,
735 /* NOTE the exception in "r" op ordering */
736 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
741 gen_op_fsubr_STN_ST0
,
743 gen_op_fdivr_STN_ST0
,
747 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
750 gen_op_mov_TN_reg
[ot
][0][d
]();
752 gen_op_mov_TN_reg
[ot
][1][s
]();
753 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
754 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
755 gen_op_set_cc_op(s1
->cc_op
);
756 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
757 s1
->cc_op
= CC_OP_DYNAMIC
;
759 gen_op_arith_T0_T1_cc
[op
]();
760 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
762 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
763 gen_op_mov_reg_T0
[ot
][d
]();
766 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
768 gen_op_movl_T1_im(c
);
769 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
772 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
775 gen_op_mov_TN_reg
[ot
][0][d
]();
776 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
777 gen_op_set_cc_op(s1
->cc_op
);
780 s1
->cc_op
= CC_OP_INCB
+ ot
;
783 s1
->cc_op
= CC_OP_DECB
+ ot
;
786 gen_op_mov_reg_T0
[ot
][d
]();
789 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
792 gen_op_mov_TN_reg
[ot
][0][d
]();
794 gen_op_mov_TN_reg
[ot
][1][s
]();
795 /* for zero counts, flags are not updated, so must do it dynamically */
796 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
797 gen_op_set_cc_op(s1
->cc_op
);
799 gen_op_shift_T0_T1_cc
[ot
][op
]();
802 gen_op_mov_reg_T0
[ot
][d
]();
803 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
806 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
808 /* currently not optimized */
809 gen_op_movl_T1_im(c
);
810 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
813 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
820 int mod
, rm
, code
, override
, must_add_seg
;
822 override
= s
->override
;
823 must_add_seg
= s
->addseg
;
826 mod
= (modrm
>> 6) & 3;
838 code
= ldub(s
->pc
++);
839 scale
= (code
>> 6) & 3;
840 index
= (code
>> 3) & 7;
855 disp
= (int8_t)ldub(s
->pc
++);
865 gen_op_movl_A0_reg
[base
]();
867 gen_op_addl_A0_im(disp
);
869 gen_op_movl_A0_im(disp
);
871 if (havesib
&& (index
!= 4 || scale
!= 0)) {
872 gen_op_addl_A0_reg_sN
[scale
][index
]();
876 if (base
== R_EBP
|| base
== R_ESP
)
881 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
889 gen_op_movl_A0_im(disp
);
890 rm
= 0; /* avoid SS override */
897 disp
= (int8_t)ldub(s
->pc
++);
907 gen_op_movl_A0_reg
[R_EBX
]();
908 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
911 gen_op_movl_A0_reg
[R_EBX
]();
912 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
915 gen_op_movl_A0_reg
[R_EBP
]();
916 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
919 gen_op_movl_A0_reg
[R_EBP
]();
920 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
923 gen_op_movl_A0_reg
[R_ESI
]();
926 gen_op_movl_A0_reg
[R_EDI
]();
929 gen_op_movl_A0_reg
[R_EBP
]();
933 gen_op_movl_A0_reg
[R_EBX
]();
937 gen_op_addl_A0_im(disp
);
938 gen_op_andl_A0_ffff();
942 if (rm
== 2 || rm
== 3 || rm
== 6)
947 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
957 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
959 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
961 int mod
, rm
, opreg
, disp
;
963 mod
= (modrm
>> 6) & 3;
968 gen_op_mov_TN_reg
[ot
][0][reg
]();
969 gen_op_mov_reg_T0
[ot
][rm
]();
971 gen_op_mov_TN_reg
[ot
][0][rm
]();
973 gen_op_mov_reg_T0
[ot
][reg
]();
976 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
979 gen_op_mov_TN_reg
[ot
][0][reg
]();
980 gen_op_st_T0_A0
[ot
]();
982 gen_op_ld_T0_A0
[ot
]();
984 gen_op_mov_reg_T0
[ot
][reg
]();
989 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1011 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1013 TranslationBlock
*tb
;
1018 jcc_op
= (b
>> 1) & 7;
1020 /* we optimize the cmp/jcc case */
1024 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1027 /* some jumps are easy to compute */
1054 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1057 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1069 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1070 gen_op_set_cc_op(s
->cc_op
);
1073 gen_setcc_slow
[jcc_op
]();
1079 func((long)tb
, val
, next_eip
);
1081 func((long)tb
, next_eip
, val
);
1086 static void gen_setcc(DisasContext
*s
, int b
)
1092 jcc_op
= (b
>> 1) & 7;
1094 /* we optimize the cmp/jcc case */
1098 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1103 /* some jumps are easy to compute */
1121 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1124 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1132 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1133 gen_op_set_cc_op(s
->cc_op
);
1134 func
= gen_setcc_slow
[jcc_op
];
1143 /* move T0 to seg_reg and compute if the CPU state may change */
1144 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
, unsigned int cur_eip
)
1147 gen_op_movl_seg_T0(seg_reg
, cur_eip
);
1149 gen_op_movl_seg_T0_vm(offsetof(CPUX86State
,segs
[seg_reg
]),
1150 offsetof(CPUX86State
,seg_cache
[seg_reg
].base
));
1151 if (!s
->addseg
&& seg_reg
< R_FS
)
1152 s
->is_jmp
= 2; /* abort translation because the register may
1153 have a non zero base */
1156 /* generate a push. It depends on ss32, addseg and dflag */
1157 static void gen_push_T0(DisasContext
*s
)
1167 gen_op_pushl_ss32_T0();
1169 gen_op_pushw_ss32_T0();
1173 gen_op_pushl_ss16_T0();
1175 gen_op_pushw_ss16_T0();
1179 /* two step pop is necessary for precise exceptions */
1180 static void gen_pop_T0(DisasContext
*s
)
1190 gen_op_popl_ss32_T0();
1192 gen_op_popw_ss32_T0();
1196 gen_op_popl_ss16_T0();
1198 gen_op_popw_ss16_T0();
1202 static inline void gen_stack_update(DisasContext
*s
, int addend
)
1206 gen_op_addl_ESP_2();
1207 else if (addend
== 4)
1208 gen_op_addl_ESP_4();
1210 gen_op_addl_ESP_im(addend
);
1213 gen_op_addw_ESP_2();
1214 else if (addend
== 4)
1215 gen_op_addw_ESP_4();
1217 gen_op_addw_ESP_im(addend
);
1221 static void gen_pop_update(DisasContext
*s
)
1223 gen_stack_update(s
, 2 << s
->dflag
);
1226 static void gen_stack_A0(DisasContext
*s
)
1228 gen_op_movl_A0_ESP();
1230 gen_op_andl_A0_ffff();
1231 gen_op_movl_T1_A0();
1233 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1236 /* NOTE: wrap around in 16 bit not fully handled */
1237 static void gen_pusha(DisasContext
*s
)
1240 gen_op_movl_A0_ESP();
1241 gen_op_addl_A0_im(-16 << s
->dflag
);
1243 gen_op_andl_A0_ffff();
1244 gen_op_movl_T1_A0();
1246 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1247 for(i
= 0;i
< 8; i
++) {
1248 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1249 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1250 gen_op_addl_A0_im(2 << s
->dflag
);
1252 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1255 /* NOTE: wrap around in 16 bit not fully handled */
1256 static void gen_popa(DisasContext
*s
)
1259 gen_op_movl_A0_ESP();
1261 gen_op_andl_A0_ffff();
1262 gen_op_movl_T1_A0();
1263 gen_op_addl_T1_im(16 << s
->dflag
);
1265 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1266 for(i
= 0;i
< 8; i
++) {
1267 /* ESP is not reloaded */
1269 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1270 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1272 gen_op_addl_A0_im(2 << s
->dflag
);
1274 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1277 /* NOTE: wrap around in 16 bit not fully handled */
1278 /* XXX: check this */
1279 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1281 int ot
, level1
, addend
, opsize
;
1283 ot
= s
->dflag
+ OT_WORD
;
1286 opsize
= 2 << s
->dflag
;
1288 gen_op_movl_A0_ESP();
1289 gen_op_addl_A0_im(-opsize
);
1291 gen_op_andl_A0_ffff();
1292 gen_op_movl_T1_A0();
1294 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1296 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1297 gen_op_st_T0_A0
[ot
]();
1300 gen_op_addl_A0_im(-opsize
);
1301 gen_op_addl_T0_im(-opsize
);
1302 gen_op_st_T0_A0
[ot
]();
1304 gen_op_addl_A0_im(-opsize
);
1305 /* XXX: add st_T1_A0 ? */
1306 gen_op_movl_T0_T1();
1307 gen_op_st_T0_A0
[ot
]();
1309 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1310 addend
= -esp_addend
;
1312 addend
-= opsize
* (level1
+ 1);
1313 gen_op_addl_T1_im(addend
);
1314 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1317 static void gen_exception(DisasContext
*s
, int trapno
, unsigned int cur_eip
)
1319 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1320 gen_op_set_cc_op(s
->cc_op
);
1321 gen_op_jmp_im(cur_eip
);
1322 gen_op_raise_exception(trapno
);
1326 /* an interrupt is different from an exception because of the
1327 priviledge checks */
1328 static void gen_interrupt(DisasContext
*s
, int intno
,
1329 unsigned int cur_eip
, unsigned int next_eip
)
1331 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1332 gen_op_set_cc_op(s
->cc_op
);
1333 gen_op_jmp_im(cur_eip
);
1334 gen_op_raise_interrupt(intno
, next_eip
);
1338 /* generate a jump to eip. No segment change must happen before as a
1339 direct call to the next block may occur */
1340 static void gen_jmp(DisasContext
*s
, unsigned int eip
)
1342 TranslationBlock
*tb
= s
->tb
;
1344 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1345 gen_op_set_cc_op(s
->cc_op
);
1346 gen_op_jmp_tb_next((long)tb
, eip
);
1350 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1351 is set to true if the instruction sets the PC (last instruction of
1353 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1355 int b
, prefixes
, aflag
, dflag
;
1357 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1358 unsigned int next_eip
;
1368 /* check prefixes */
1371 prefixes
|= PREFIX_REPZ
;
1374 prefixes
|= PREFIX_REPNZ
;
1377 prefixes
|= PREFIX_LOCK
;
1398 prefixes
|= PREFIX_DATA
;
1401 prefixes
|= PREFIX_ADR
;
1405 if (prefixes
& PREFIX_DATA
)
1407 if (prefixes
& PREFIX_ADR
)
1410 s
->prefix
= prefixes
;
1414 /* lock generation */
1415 if (prefixes
& PREFIX_LOCK
)
1418 /* now check op code */
1422 /**************************/
1423 /* extended op code */
1424 b
= ldub(s
->pc
++) | 0x100;
1427 /**************************/
1445 ot
= dflag
? OT_LONG
: OT_WORD
;
1448 case 0: /* OP Ev, Gv */
1449 modrm
= ldub(s
->pc
++);
1450 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1451 mod
= (modrm
>> 6) & 3;
1454 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1455 gen_op_ld_T0_A0
[ot
]();
1458 opreg
= OR_EAX
+ rm
;
1460 gen_op(s
, op
, ot
, opreg
, reg
);
1461 if (mod
!= 3 && op
!= 7) {
1462 gen_op_st_T0_A0
[ot
]();
1465 case 1: /* OP Gv, Ev */
1466 modrm
= ldub(s
->pc
++);
1467 mod
= (modrm
>> 6) & 3;
1468 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1471 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1472 gen_op_ld_T1_A0
[ot
]();
1475 opreg
= OR_EAX
+ rm
;
1477 gen_op(s
, op
, ot
, reg
, opreg
);
1479 case 2: /* OP A, Iv */
1480 val
= insn_get(s
, ot
);
1481 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1487 case 0x80: /* GRP1 */
1496 ot
= dflag
? OT_LONG
: OT_WORD
;
1498 modrm
= ldub(s
->pc
++);
1499 mod
= (modrm
>> 6) & 3;
1501 op
= (modrm
>> 3) & 7;
1504 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1505 gen_op_ld_T0_A0
[ot
]();
1508 opreg
= rm
+ OR_EAX
;
1515 val
= insn_get(s
, ot
);
1518 val
= (int8_t)insn_get(s
, OT_BYTE
);
1522 gen_opi(s
, op
, ot
, opreg
, val
);
1523 if (op
!= 7 && mod
!= 3) {
1524 gen_op_st_T0_A0
[ot
]();
1529 /**************************/
1530 /* inc, dec, and other misc arith */
1531 case 0x40 ... 0x47: /* inc Gv */
1532 ot
= dflag
? OT_LONG
: OT_WORD
;
1533 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1535 case 0x48 ... 0x4f: /* dec Gv */
1536 ot
= dflag
? OT_LONG
: OT_WORD
;
1537 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1539 case 0xf6: /* GRP3 */
1544 ot
= dflag
? OT_LONG
: OT_WORD
;
1546 modrm
= ldub(s
->pc
++);
1547 mod
= (modrm
>> 6) & 3;
1549 op
= (modrm
>> 3) & 7;
1551 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1552 gen_op_ld_T0_A0
[ot
]();
1554 gen_op_mov_TN_reg
[ot
][0][rm
]();
1559 val
= insn_get(s
, ot
);
1560 gen_op_movl_T1_im(val
);
1561 gen_op_testl_T0_T1_cc();
1562 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1567 gen_op_st_T0_A0
[ot
]();
1569 gen_op_mov_reg_T0
[ot
][rm
]();
1573 gen_op_negl_T0_cc();
1575 gen_op_st_T0_A0
[ot
]();
1577 gen_op_mov_reg_T0
[ot
][rm
]();
1579 s
->cc_op
= CC_OP_SUBB
+ ot
;
1584 gen_op_mulb_AL_T0();
1587 gen_op_mulw_AX_T0();
1591 gen_op_mull_EAX_T0();
1594 s
->cc_op
= CC_OP_MUL
;
1599 gen_op_imulb_AL_T0();
1602 gen_op_imulw_AX_T0();
1606 gen_op_imull_EAX_T0();
1609 s
->cc_op
= CC_OP_MUL
;
1614 gen_op_divb_AL_T0(pc_start
- s
->cs_base
);
1617 gen_op_divw_AX_T0(pc_start
- s
->cs_base
);
1621 gen_op_divl_EAX_T0(pc_start
- s
->cs_base
);
1628 gen_op_idivb_AL_T0(pc_start
- s
->cs_base
);
1631 gen_op_idivw_AX_T0(pc_start
- s
->cs_base
);
1635 gen_op_idivl_EAX_T0(pc_start
- s
->cs_base
);
1644 case 0xfe: /* GRP4 */
1645 case 0xff: /* GRP5 */
1649 ot
= dflag
? OT_LONG
: OT_WORD
;
1651 modrm
= ldub(s
->pc
++);
1652 mod
= (modrm
>> 6) & 3;
1654 op
= (modrm
>> 3) & 7;
1655 if (op
>= 2 && b
== 0xfe) {
1659 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1660 if (op
!= 3 && op
!= 5)
1661 gen_op_ld_T0_A0
[ot
]();
1663 gen_op_mov_TN_reg
[ot
][0][rm
]();
1667 case 0: /* inc Ev */
1668 gen_inc(s
, ot
, OR_TMP0
, 1);
1670 gen_op_st_T0_A0
[ot
]();
1672 gen_op_mov_reg_T0
[ot
][rm
]();
1674 case 1: /* dec Ev */
1675 gen_inc(s
, ot
, OR_TMP0
, -1);
1677 gen_op_st_T0_A0
[ot
]();
1679 gen_op_mov_reg_T0
[ot
][rm
]();
1681 case 2: /* call Ev */
1682 /* XXX: optimize if memory (no and is necessary) */
1684 gen_op_andl_T0_ffff();
1686 next_eip
= s
->pc
- s
->cs_base
;
1687 gen_op_movl_T0_im(next_eip
);
1691 case 3: /* lcall Ev */
1692 /* push return segment + offset */
1693 gen_op_movl_T0_seg(R_CS
);
1695 next_eip
= s
->pc
- s
->cs_base
;
1696 gen_op_movl_T0_im(next_eip
);
1699 gen_op_ld_T1_A0
[ot
]();
1700 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1701 gen_op_lduw_T0_A0();
1702 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
1703 gen_op_movl_T0_T1();
1707 case 4: /* jmp Ev */
1709 gen_op_andl_T0_ffff();
1713 case 5: /* ljmp Ev */
1714 gen_op_ld_T1_A0
[ot
]();
1715 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1716 gen_op_lduw_T0_A0();
1717 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
1718 gen_op_movl_T0_T1();
1722 case 6: /* push Ev */
1730 case 0x84: /* test Ev, Gv */
1735 ot
= dflag
? OT_LONG
: OT_WORD
;
1737 modrm
= ldub(s
->pc
++);
1738 mod
= (modrm
>> 6) & 3;
1740 reg
= (modrm
>> 3) & 7;
1742 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1743 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1744 gen_op_testl_T0_T1_cc();
1745 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1748 case 0xa8: /* test eAX, Iv */
1753 ot
= dflag
? OT_LONG
: OT_WORD
;
1754 val
= insn_get(s
, ot
);
1756 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1757 gen_op_movl_T1_im(val
);
1758 gen_op_testl_T0_T1_cc();
1759 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1762 case 0x98: /* CWDE/CBW */
1764 gen_op_movswl_EAX_AX();
1766 gen_op_movsbw_AX_AL();
1768 case 0x99: /* CDQ/CWD */
1770 gen_op_movslq_EDX_EAX();
1772 gen_op_movswl_DX_AX();
1774 case 0x1af: /* imul Gv, Ev */
1775 case 0x69: /* imul Gv, Ev, I */
1777 ot
= dflag
? OT_LONG
: OT_WORD
;
1778 modrm
= ldub(s
->pc
++);
1779 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1780 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1782 val
= insn_get(s
, ot
);
1783 gen_op_movl_T1_im(val
);
1784 } else if (b
== 0x6b) {
1785 val
= insn_get(s
, OT_BYTE
);
1786 gen_op_movl_T1_im(val
);
1788 gen_op_mov_TN_reg
[ot
][1][reg
]();
1791 if (ot
== OT_LONG
) {
1792 gen_op_imull_T0_T1();
1794 gen_op_imulw_T0_T1();
1796 gen_op_mov_reg_T0
[ot
][reg
]();
1797 s
->cc_op
= CC_OP_MUL
;
1800 case 0x1c1: /* xadd Ev, Gv */
1804 ot
= dflag
? OT_LONG
: OT_WORD
;
1805 modrm
= ldub(s
->pc
++);
1806 reg
= (modrm
>> 3) & 7;
1807 mod
= (modrm
>> 6) & 3;
1810 gen_op_mov_TN_reg
[ot
][0][reg
]();
1811 gen_op_mov_TN_reg
[ot
][1][rm
]();
1812 gen_op_addl_T0_T1_cc();
1813 gen_op_mov_reg_T0
[ot
][rm
]();
1814 gen_op_mov_reg_T1
[ot
][reg
]();
1816 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1817 gen_op_mov_TN_reg
[ot
][0][reg
]();
1818 gen_op_ld_T1_A0
[ot
]();
1819 gen_op_addl_T0_T1_cc();
1820 gen_op_st_T0_A0
[ot
]();
1821 gen_op_mov_reg_T1
[ot
][reg
]();
1823 s
->cc_op
= CC_OP_ADDB
+ ot
;
1826 case 0x1b1: /* cmpxchg Ev, Gv */
1830 ot
= dflag
? OT_LONG
: OT_WORD
;
1831 modrm
= ldub(s
->pc
++);
1832 reg
= (modrm
>> 3) & 7;
1833 mod
= (modrm
>> 6) & 3;
1834 gen_op_mov_TN_reg
[ot
][1][reg
]();
1837 gen_op_mov_TN_reg
[ot
][0][rm
]();
1838 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1839 gen_op_mov_reg_T0
[ot
][rm
]();
1841 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1842 gen_op_ld_T0_A0
[ot
]();
1843 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1844 gen_op_st_T0_A0
[ot
]();
1846 s
->cc_op
= CC_OP_SUBB
+ ot
;
1848 case 0x1c7: /* cmpxchg8b */
1849 modrm
= ldub(s
->pc
++);
1850 mod
= (modrm
>> 6) & 3;
1853 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1854 gen_op_set_cc_op(s
->cc_op
);
1855 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1857 s
->cc_op
= CC_OP_EFLAGS
;
1860 /**************************/
1862 case 0x50 ... 0x57: /* push */
1863 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1866 case 0x58 ... 0x5f: /* pop */
1867 ot
= dflag
? OT_LONG
: OT_WORD
;
1869 gen_op_mov_reg_T0
[ot
][b
& 7]();
1872 case 0x60: /* pusha */
1875 case 0x61: /* popa */
1878 case 0x68: /* push Iv */
1880 ot
= dflag
? OT_LONG
: OT_WORD
;
1882 val
= insn_get(s
, ot
);
1884 val
= (int8_t)insn_get(s
, OT_BYTE
);
1885 gen_op_movl_T0_im(val
);
1888 case 0x8f: /* pop Ev */
1889 ot
= dflag
? OT_LONG
: OT_WORD
;
1890 modrm
= ldub(s
->pc
++);
1892 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1895 case 0xc8: /* enter */
1900 level
= ldub(s
->pc
++);
1901 gen_enter(s
, val
, level
);
1904 case 0xc9: /* leave */
1905 /* XXX: exception not precise (ESP is updated before potential exception) */
1907 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1908 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1910 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1911 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1914 ot
= dflag
? OT_LONG
: OT_WORD
;
1915 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1918 case 0x06: /* push es */
1919 case 0x0e: /* push cs */
1920 case 0x16: /* push ss */
1921 case 0x1e: /* push ds */
1922 gen_op_movl_T0_seg(b
>> 3);
1925 case 0x1a0: /* push fs */
1926 case 0x1a8: /* push gs */
1927 gen_op_movl_T0_seg((b
>> 3) & 7);
1930 case 0x07: /* pop es */
1931 case 0x17: /* pop ss */
1932 case 0x1f: /* pop ds */
1934 gen_movl_seg_T0(s
, b
>> 3, pc_start
- s
->cs_base
);
1937 case 0x1a1: /* pop fs */
1938 case 0x1a9: /* pop gs */
1940 gen_movl_seg_T0(s
, (b
>> 3) & 7, pc_start
- s
->cs_base
);
1944 /**************************/
1947 case 0x89: /* mov Gv, Ev */
1951 ot
= dflag
? OT_LONG
: OT_WORD
;
1952 modrm
= ldub(s
->pc
++);
1953 reg
= (modrm
>> 3) & 7;
1955 /* generate a generic store */
1956 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
1959 case 0xc7: /* mov Ev, Iv */
1963 ot
= dflag
? OT_LONG
: OT_WORD
;
1964 modrm
= ldub(s
->pc
++);
1965 mod
= (modrm
>> 6) & 3;
1967 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1968 val
= insn_get(s
, ot
);
1969 gen_op_movl_T0_im(val
);
1971 gen_op_st_T0_A0
[ot
]();
1973 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
1976 case 0x8b: /* mov Ev, Gv */
1980 ot
= dflag
? OT_LONG
: OT_WORD
;
1981 modrm
= ldub(s
->pc
++);
1982 reg
= (modrm
>> 3) & 7;
1984 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1985 gen_op_mov_reg_T0
[ot
][reg
]();
1987 case 0x8e: /* mov seg, Gv */
1988 ot
= dflag
? OT_LONG
: OT_WORD
;
1989 modrm
= ldub(s
->pc
++);
1990 reg
= (modrm
>> 3) & 7;
1991 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1992 if (reg
>= 6 || reg
== R_CS
)
1994 gen_movl_seg_T0(s
, reg
, pc_start
- s
->cs_base
);
1996 case 0x8c: /* mov Gv, seg */
1997 ot
= dflag
? OT_LONG
: OT_WORD
;
1998 modrm
= ldub(s
->pc
++);
1999 reg
= (modrm
>> 3) & 7;
2002 gen_op_movl_T0_seg(reg
);
2003 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2006 case 0x1b6: /* movzbS Gv, Eb */
2007 case 0x1b7: /* movzwS Gv, Eb */
2008 case 0x1be: /* movsbS Gv, Eb */
2009 case 0x1bf: /* movswS Gv, Eb */
2012 /* d_ot is the size of destination */
2013 d_ot
= dflag
+ OT_WORD
;
2014 /* ot is the size of source */
2015 ot
= (b
& 1) + OT_BYTE
;
2016 modrm
= ldub(s
->pc
++);
2017 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2018 mod
= (modrm
>> 6) & 3;
2022 gen_op_mov_TN_reg
[ot
][0][rm
]();
2023 switch(ot
| (b
& 8)) {
2025 gen_op_movzbl_T0_T0();
2028 gen_op_movsbl_T0_T0();
2031 gen_op_movzwl_T0_T0();
2035 gen_op_movswl_T0_T0();
2038 gen_op_mov_reg_T0
[d_ot
][reg
]();
2040 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2042 gen_op_lds_T0_A0
[ot
]();
2044 gen_op_ldu_T0_A0
[ot
]();
2046 gen_op_mov_reg_T0
[d_ot
][reg
]();
2051 case 0x8d: /* lea */
2052 ot
= dflag
? OT_LONG
: OT_WORD
;
2053 modrm
= ldub(s
->pc
++);
2054 reg
= (modrm
>> 3) & 7;
2055 /* we must ensure that no segment is added */
2059 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2061 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2064 case 0xa0: /* mov EAX, Ov */
2066 case 0xa2: /* mov Ov, EAX */
2071 ot
= dflag
? OT_LONG
: OT_WORD
;
2073 offset_addr
= insn_get(s
, OT_LONG
);
2075 offset_addr
= insn_get(s
, OT_WORD
);
2076 gen_op_movl_A0_im(offset_addr
);
2077 /* handle override */
2079 int override
, must_add_seg
;
2080 must_add_seg
= s
->addseg
;
2081 if (s
->override
>= 0) {
2082 override
= s
->override
;
2088 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2092 gen_op_ld_T0_A0
[ot
]();
2093 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2095 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2096 gen_op_st_T0_A0
[ot
]();
2099 case 0xd7: /* xlat */
2100 gen_op_movl_A0_reg
[R_EBX
]();
2101 gen_op_addl_A0_AL();
2103 gen_op_andl_A0_ffff();
2104 /* handle override */
2106 int override
, must_add_seg
;
2107 must_add_seg
= s
->addseg
;
2109 if (s
->override
>= 0) {
2110 override
= s
->override
;
2116 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2119 gen_op_ldub_T0_A0();
2120 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2122 case 0xb0 ... 0xb7: /* mov R, Ib */
2123 val
= insn_get(s
, OT_BYTE
);
2124 gen_op_movl_T0_im(val
);
2125 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2127 case 0xb8 ... 0xbf: /* mov R, Iv */
2128 ot
= dflag
? OT_LONG
: OT_WORD
;
2129 val
= insn_get(s
, ot
);
2130 reg
= OR_EAX
+ (b
& 7);
2131 gen_op_movl_T0_im(val
);
2132 gen_op_mov_reg_T0
[ot
][reg
]();
2135 case 0x91 ... 0x97: /* xchg R, EAX */
2136 ot
= dflag
? OT_LONG
: OT_WORD
;
2141 case 0x87: /* xchg Ev, Gv */
2145 ot
= dflag
? OT_LONG
: OT_WORD
;
2146 modrm
= ldub(s
->pc
++);
2147 reg
= (modrm
>> 3) & 7;
2148 mod
= (modrm
>> 6) & 3;
2152 gen_op_mov_TN_reg
[ot
][0][reg
]();
2153 gen_op_mov_TN_reg
[ot
][1][rm
]();
2154 gen_op_mov_reg_T0
[ot
][rm
]();
2155 gen_op_mov_reg_T1
[ot
][reg
]();
2157 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2158 gen_op_mov_TN_reg
[ot
][0][reg
]();
2159 /* for xchg, lock is implicit */
2160 if (!(prefixes
& PREFIX_LOCK
))
2162 gen_op_ld_T1_A0
[ot
]();
2163 gen_op_st_T0_A0
[ot
]();
2164 if (!(prefixes
& PREFIX_LOCK
))
2166 gen_op_mov_reg_T1
[ot
][reg
]();
2169 case 0xc4: /* les Gv */
2172 case 0xc5: /* lds Gv */
2175 case 0x1b2: /* lss Gv */
2178 case 0x1b4: /* lfs Gv */
2181 case 0x1b5: /* lgs Gv */
2184 ot
= dflag
? OT_LONG
: OT_WORD
;
2185 modrm
= ldub(s
->pc
++);
2186 reg
= (modrm
>> 3) & 7;
2187 mod
= (modrm
>> 6) & 3;
2190 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2191 gen_op_ld_T1_A0
[ot
]();
2192 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2193 /* load the segment first to handle exceptions properly */
2194 gen_op_lduw_T0_A0();
2195 gen_movl_seg_T0(s
, op
, pc_start
- s
->cs_base
);
2196 /* then put the data */
2197 gen_op_mov_reg_T1
[ot
][reg
]();
2200 /************************/
2211 ot
= dflag
? OT_LONG
: OT_WORD
;
2213 modrm
= ldub(s
->pc
++);
2214 mod
= (modrm
>> 6) & 3;
2216 op
= (modrm
>> 3) & 7;
2219 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2220 gen_op_ld_T0_A0
[ot
]();
2223 opreg
= rm
+ OR_EAX
;
2228 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2231 shift
= ldub(s
->pc
++);
2233 gen_shifti(s
, op
, ot
, opreg
, shift
);
2237 gen_op_st_T0_A0
[ot
]();
2252 case 0x1a4: /* shld imm */
2256 case 0x1a5: /* shld cl */
2260 case 0x1ac: /* shrd imm */
2264 case 0x1ad: /* shrd cl */
2268 ot
= dflag
? OT_LONG
: OT_WORD
;
2269 modrm
= ldub(s
->pc
++);
2270 mod
= (modrm
>> 6) & 3;
2272 reg
= (modrm
>> 3) & 7;
2275 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2276 gen_op_ld_T0_A0
[ot
]();
2278 gen_op_mov_TN_reg
[ot
][0][rm
]();
2280 gen_op_mov_TN_reg
[ot
][1][reg
]();
2283 val
= ldub(s
->pc
++);
2286 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2287 if (op
== 0 && ot
!= OT_WORD
)
2288 s
->cc_op
= CC_OP_SHLB
+ ot
;
2290 s
->cc_op
= CC_OP_SARB
+ ot
;
2293 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2294 gen_op_set_cc_op(s
->cc_op
);
2295 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2296 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2299 gen_op_st_T0_A0
[ot
]();
2301 gen_op_mov_reg_T0
[ot
][rm
]();
2305 /************************/
2308 modrm
= ldub(s
->pc
++);
2309 mod
= (modrm
>> 6) & 3;
2311 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2315 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2317 case 0x00 ... 0x07: /* fxxxs */
2318 case 0x10 ... 0x17: /* fixxxl */
2319 case 0x20 ... 0x27: /* fxxxl */
2320 case 0x30 ... 0x37: /* fixxx */
2327 gen_op_flds_FT0_A0();
2330 gen_op_fildl_FT0_A0();
2333 gen_op_fldl_FT0_A0();
2337 gen_op_fild_FT0_A0();
2341 gen_op_fp_arith_ST0_FT0
[op1
]();
2343 /* fcomp needs pop */
2348 case 0x08: /* flds */
2349 case 0x0a: /* fsts */
2350 case 0x0b: /* fstps */
2351 case 0x18: /* fildl */
2352 case 0x1a: /* fistl */
2353 case 0x1b: /* fistpl */
2354 case 0x28: /* fldl */
2355 case 0x2a: /* fstl */
2356 case 0x2b: /* fstpl */
2357 case 0x38: /* filds */
2358 case 0x3a: /* fists */
2359 case 0x3b: /* fistps */
2366 gen_op_flds_ST0_A0();
2369 gen_op_fildl_ST0_A0();
2372 gen_op_fldl_ST0_A0();
2376 gen_op_fild_ST0_A0();
2383 gen_op_fsts_ST0_A0();
2386 gen_op_fistl_ST0_A0();
2389 gen_op_fstl_ST0_A0();
2393 gen_op_fist_ST0_A0();
2401 case 0x0c: /* fldenv mem */
2402 gen_op_fldenv_A0(s
->dflag
);
2404 case 0x0d: /* fldcw mem */
2407 case 0x0e: /* fnstenv mem */
2408 gen_op_fnstenv_A0(s
->dflag
);
2410 case 0x0f: /* fnstcw mem */
2413 case 0x1d: /* fldt mem */
2415 gen_op_fldt_ST0_A0();
2417 case 0x1f: /* fstpt mem */
2418 gen_op_fstt_ST0_A0();
2421 case 0x2c: /* frstor mem */
2422 gen_op_frstor_A0(s
->dflag
);
2424 case 0x2e: /* fnsave mem */
2425 gen_op_fnsave_A0(s
->dflag
);
2427 case 0x2f: /* fnstsw mem */
2430 case 0x3c: /* fbld */
2432 gen_op_fbld_ST0_A0();
2434 case 0x3e: /* fbstp */
2435 gen_op_fbst_ST0_A0();
2438 case 0x3d: /* fildll */
2440 gen_op_fildll_ST0_A0();
2442 case 0x3f: /* fistpll */
2443 gen_op_fistll_ST0_A0();
2450 /* register float ops */
2454 case 0x08: /* fld sti */
2456 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2458 case 0x09: /* fxchg sti */
2459 gen_op_fxchg_ST0_STN(opreg
);
2461 case 0x0a: /* grp d9/2 */
2469 case 0x0c: /* grp d9/4 */
2479 gen_op_fcom_ST0_FT0();
2488 case 0x0d: /* grp d9/5 */
2497 gen_op_fldl2t_ST0();
2501 gen_op_fldl2e_ST0();
2509 gen_op_fldlg2_ST0();
2513 gen_op_fldln2_ST0();
2524 case 0x0e: /* grp d9/6 */
2535 case 3: /* fpatan */
2538 case 4: /* fxtract */
2541 case 5: /* fprem1 */
2544 case 6: /* fdecstp */
2548 case 7: /* fincstp */
2553 case 0x0f: /* grp d9/7 */
2558 case 1: /* fyl2xp1 */
2564 case 3: /* fsincos */
2567 case 5: /* fscale */
2570 case 4: /* frndint */
2582 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2583 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2584 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2590 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2594 gen_op_fmov_FT0_STN(opreg
);
2595 gen_op_fp_arith_ST0_FT0
[op1
]();
2599 case 0x02: /* fcom */
2600 gen_op_fmov_FT0_STN(opreg
);
2601 gen_op_fcom_ST0_FT0();
2603 case 0x03: /* fcomp */
2604 gen_op_fmov_FT0_STN(opreg
);
2605 gen_op_fcom_ST0_FT0();
2608 case 0x15: /* da/5 */
2610 case 1: /* fucompp */
2611 gen_op_fmov_FT0_STN(1);
2612 gen_op_fucom_ST0_FT0();
2625 case 3: /* fninit */
2632 case 0x1d: /* fucomi */
2633 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2634 gen_op_set_cc_op(s
->cc_op
);
2635 gen_op_fmov_FT0_STN(opreg
);
2636 gen_op_fucomi_ST0_FT0();
2637 s
->cc_op
= CC_OP_EFLAGS
;
2639 case 0x1e: /* fcomi */
2640 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2641 gen_op_set_cc_op(s
->cc_op
);
2642 gen_op_fmov_FT0_STN(opreg
);
2643 gen_op_fcomi_ST0_FT0();
2644 s
->cc_op
= CC_OP_EFLAGS
;
2646 case 0x2a: /* fst sti */
2647 gen_op_fmov_STN_ST0(opreg
);
2649 case 0x2b: /* fstp sti */
2650 gen_op_fmov_STN_ST0(opreg
);
2653 case 0x2c: /* fucom st(i) */
2654 gen_op_fmov_FT0_STN(opreg
);
2655 gen_op_fucom_ST0_FT0();
2657 case 0x2d: /* fucomp st(i) */
2658 gen_op_fmov_FT0_STN(opreg
);
2659 gen_op_fucom_ST0_FT0();
2662 case 0x33: /* de/3 */
2664 case 1: /* fcompp */
2665 gen_op_fmov_FT0_STN(1);
2666 gen_op_fcom_ST0_FT0();
2674 case 0x3c: /* df/4 */
2677 gen_op_fnstsw_EAX();
2683 case 0x3d: /* fucomip */
2684 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2685 gen_op_set_cc_op(s
->cc_op
);
2686 gen_op_fmov_FT0_STN(opreg
);
2687 gen_op_fucomi_ST0_FT0();
2689 s
->cc_op
= CC_OP_EFLAGS
;
2691 case 0x3e: /* fcomip */
2692 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2693 gen_op_set_cc_op(s
->cc_op
);
2694 gen_op_fmov_FT0_STN(opreg
);
2695 gen_op_fcomi_ST0_FT0();
2697 s
->cc_op
= CC_OP_EFLAGS
;
2704 /************************/
2707 case 0xa4: /* movsS */
2712 ot
= dflag
? OT_LONG
: OT_WORD
;
2714 if (prefixes
& PREFIX_REPZ
) {
2715 gen_string_ds(s
, ot
, gen_op_movs
+ 9);
2717 gen_string_ds(s
, ot
, gen_op_movs
);
2721 case 0xaa: /* stosS */
2726 ot
= dflag
? OT_LONG
: OT_WORD
;
2728 if (prefixes
& PREFIX_REPZ
) {
2729 gen_string_es(s
, ot
, gen_op_stos
+ 9);
2731 gen_string_es(s
, ot
, gen_op_stos
);
2734 case 0xac: /* lodsS */
2739 ot
= dflag
? OT_LONG
: OT_WORD
;
2740 if (prefixes
& PREFIX_REPZ
) {
2741 gen_string_ds(s
, ot
, gen_op_lods
+ 9);
2743 gen_string_ds(s
, ot
, gen_op_lods
);
2746 case 0xae: /* scasS */
2751 ot
= dflag
? OT_LONG
: OT_WORD
;
2752 if (prefixes
& PREFIX_REPNZ
) {
2753 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2754 gen_op_set_cc_op(s
->cc_op
);
2755 gen_string_es(s
, ot
, gen_op_scas
+ 9 * 2);
2756 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2757 } else if (prefixes
& PREFIX_REPZ
) {
2758 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2759 gen_op_set_cc_op(s
->cc_op
);
2760 gen_string_es(s
, ot
, gen_op_scas
+ 9);
2761 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2763 gen_string_es(s
, ot
, gen_op_scas
);
2764 s
->cc_op
= CC_OP_SUBB
+ ot
;
2768 case 0xa6: /* cmpsS */
2773 ot
= dflag
? OT_LONG
: OT_WORD
;
2774 if (prefixes
& PREFIX_REPNZ
) {
2775 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2776 gen_op_set_cc_op(s
->cc_op
);
2777 gen_string_ds(s
, ot
, gen_op_cmps
+ 9 * 2);
2778 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2779 } else if (prefixes
& PREFIX_REPZ
) {
2780 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2781 gen_op_set_cc_op(s
->cc_op
);
2782 gen_string_ds(s
, ot
, gen_op_cmps
+ 9);
2783 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2785 gen_string_ds(s
, ot
, gen_op_cmps
);
2786 s
->cc_op
= CC_OP_SUBB
+ ot
;
2789 case 0x6c: /* insS */
2791 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2792 /* NOTE: even for (E)CX = 0 the exception is raised */
2793 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2798 ot
= dflag
? OT_LONG
: OT_WORD
;
2799 if (prefixes
& PREFIX_REPZ
) {
2800 gen_string_es(s
, ot
, gen_op_ins
+ 9);
2802 gen_string_es(s
, ot
, gen_op_ins
);
2806 case 0x6e: /* outsS */
2808 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2809 /* NOTE: even for (E)CX = 0 the exception is raised */
2810 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2815 ot
= dflag
? OT_LONG
: OT_WORD
;
2816 if (prefixes
& PREFIX_REPZ
) {
2817 gen_string_ds(s
, ot
, gen_op_outs
+ 9);
2819 gen_string_ds(s
, ot
, gen_op_outs
);
2824 /************************/
2828 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2829 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2834 ot
= dflag
? OT_LONG
: OT_WORD
;
2835 val
= ldub(s
->pc
++);
2836 gen_op_movl_T0_im(val
);
2838 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2843 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2844 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2849 ot
= dflag
? OT_LONG
: OT_WORD
;
2850 val
= ldub(s
->pc
++);
2851 gen_op_movl_T0_im(val
);
2852 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2858 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2859 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2864 ot
= dflag
? OT_LONG
: OT_WORD
;
2865 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2867 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2872 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2873 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2878 ot
= dflag
? OT_LONG
: OT_WORD
;
2879 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2880 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2885 /************************/
2887 case 0xc2: /* ret im */
2891 gen_stack_update(s
, val
+ (2 << s
->dflag
));
2893 gen_op_andl_T0_ffff();
2897 case 0xc3: /* ret */
2901 gen_op_andl_T0_ffff();
2905 case 0xca: /* lret im */
2911 gen_op_ld_T0_A0
[1 + s
->dflag
]();
2913 gen_op_andl_T0_ffff();
2914 /* NOTE: keeping EIP updated is not a problem in case of
2918 gen_op_addl_A0_im(2 << s
->dflag
);
2919 gen_op_ld_T0_A0
[1 + s
->dflag
]();
2920 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
2921 /* add stack offset */
2922 gen_stack_update(s
, val
+ (4 << s
->dflag
));
2925 case 0xcb: /* lret */
2928 case 0xcf: /* iret */
2929 if (s
->vm86
&& s
->iopl
!= 3) {
2930 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2932 /* XXX: not restartable */
2935 gen_op_ld_T0_A0
[1 + s
->dflag
]();
2937 gen_op_andl_T0_ffff();
2938 /* NOTE: keeping EIP updated is not a problem in case of
2942 gen_op_addl_A0_im(2 << s
->dflag
);
2943 gen_op_ld_T0_A0
[1 + s
->dflag
]();
2945 gen_op_addl_A0_im(2 << s
->dflag
);
2946 gen_op_ld_T1_A0
[1 + s
->dflag
]();
2947 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
2948 gen_op_movl_T0_T1();
2950 gen_op_movl_eflags_T0();
2952 gen_op_movw_eflags_T0();
2954 gen_stack_update(s
, (6 << s
->dflag
));
2955 s
->cc_op
= CC_OP_EFLAGS
;
2959 case 0xe8: /* call im */
2961 unsigned int next_eip
;
2962 ot
= dflag
? OT_LONG
: OT_WORD
;
2963 val
= insn_get(s
, ot
);
2964 next_eip
= s
->pc
- s
->cs_base
;
2968 gen_op_movl_T0_im(next_eip
);
2973 case 0x9a: /* lcall im */
2975 unsigned int selector
, offset
;
2976 /* XXX: not restartable */
2978 ot
= dflag
? OT_LONG
: OT_WORD
;
2979 offset
= insn_get(s
, ot
);
2980 selector
= insn_get(s
, OT_WORD
);
2982 /* push return segment + offset */
2983 gen_op_movl_T0_seg(R_CS
);
2985 next_eip
= s
->pc
- s
->cs_base
;
2986 gen_op_movl_T0_im(next_eip
);
2989 /* change cs and pc */
2990 gen_op_movl_T0_im(selector
);
2991 gen_movl_seg_T0(s
, R_CS
, pc_start
- s
->cs_base
);
2992 gen_op_jmp_im((unsigned long)offset
);
2996 case 0xe9: /* jmp */
2997 ot
= dflag
? OT_LONG
: OT_WORD
;
2998 val
= insn_get(s
, ot
);
2999 val
+= s
->pc
- s
->cs_base
;
3004 case 0xea: /* ljmp im */
3006 unsigned int selector
, offset
;
3008 ot
= dflag
? OT_LONG
: OT_WORD
;
3009 offset
= insn_get(s
, ot
);
3010 selector
= insn_get(s
, OT_WORD
);
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 0xeb: /* jmp Jb */
3020 val
= (int8_t)insn_get(s
, OT_BYTE
);
3021 val
+= s
->pc
- s
->cs_base
;
3026 case 0x70 ... 0x7f: /* jcc Jb */
3027 val
= (int8_t)insn_get(s
, OT_BYTE
);
3029 case 0x180 ... 0x18f: /* jcc Jv */
3031 val
= insn_get(s
, OT_LONG
);
3033 val
= (int16_t)insn_get(s
, OT_WORD
);
3036 next_eip
= s
->pc
- s
->cs_base
;
3040 gen_jcc(s
, b
, val
, next_eip
);
3043 case 0x190 ... 0x19f: /* setcc Gv */
3044 modrm
= ldub(s
->pc
++);
3046 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
3048 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3049 ot
= dflag
? OT_LONG
: OT_WORD
;
3050 modrm
= ldub(s
->pc
++);
3051 reg
= (modrm
>> 3) & 7;
3052 mod
= (modrm
>> 6) & 3;
3055 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3056 gen_op_ld_T1_A0
[ot
]();
3059 gen_op_mov_TN_reg
[ot
][1][rm
]();
3061 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
3064 /************************/
3066 case 0x9c: /* pushf */
3067 if (s
->vm86
&& s
->iopl
!= 3) {
3068 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3070 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3071 gen_op_set_cc_op(s
->cc_op
);
3072 gen_op_movl_T0_eflags();
3076 case 0x9d: /* popf */
3077 if (s
->vm86
&& s
->iopl
!= 3) {
3078 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3082 gen_op_movl_eflags_T0();
3084 gen_op_movw_eflags_T0();
3087 s
->cc_op
= CC_OP_EFLAGS
;
3088 s
->is_jmp
= 2; /* abort translation because TF flag may change */
3091 case 0x9e: /* sahf */
3092 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
3093 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3094 gen_op_set_cc_op(s
->cc_op
);
3095 gen_op_movb_eflags_T0();
3096 s
->cc_op
= CC_OP_EFLAGS
;
3098 case 0x9f: /* lahf */
3099 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3100 gen_op_set_cc_op(s
->cc_op
);
3101 gen_op_movl_T0_eflags();
3102 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
3104 case 0xf5: /* cmc */
3105 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3106 gen_op_set_cc_op(s
->cc_op
);
3108 s
->cc_op
= CC_OP_EFLAGS
;
3110 case 0xf8: /* clc */
3111 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3112 gen_op_set_cc_op(s
->cc_op
);
3114 s
->cc_op
= CC_OP_EFLAGS
;
3116 case 0xf9: /* stc */
3117 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3118 gen_op_set_cc_op(s
->cc_op
);
3120 s
->cc_op
= CC_OP_EFLAGS
;
3122 case 0xfc: /* cld */
3125 case 0xfd: /* std */
3129 /************************/
3130 /* bit operations */
3131 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3132 ot
= dflag
? OT_LONG
: OT_WORD
;
3133 modrm
= ldub(s
->pc
++);
3134 op
= (modrm
>> 3) & 7;
3135 mod
= (modrm
>> 6) & 3;
3138 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3139 gen_op_ld_T0_A0
[ot
]();
3141 gen_op_mov_TN_reg
[ot
][0][rm
]();
3144 val
= ldub(s
->pc
++);
3145 gen_op_movl_T1_im(val
);
3149 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3150 s
->cc_op
= CC_OP_SARB
+ ot
;
3153 gen_op_st_T0_A0
[ot
]();
3155 gen_op_mov_reg_T0
[ot
][rm
]();
3158 case 0x1a3: /* bt Gv, Ev */
3161 case 0x1ab: /* bts */
3164 case 0x1b3: /* btr */
3167 case 0x1bb: /* btc */
3170 ot
= dflag
? OT_LONG
: OT_WORD
;
3171 modrm
= ldub(s
->pc
++);
3172 reg
= (modrm
>> 3) & 7;
3173 mod
= (modrm
>> 6) & 3;
3175 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3177 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3178 /* specific case: we need to add a displacement */
3180 gen_op_add_bitw_A0_T1();
3182 gen_op_add_bitl_A0_T1();
3183 gen_op_ld_T0_A0
[ot
]();
3185 gen_op_mov_TN_reg
[ot
][0][rm
]();
3187 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3188 s
->cc_op
= CC_OP_SARB
+ ot
;
3191 gen_op_st_T0_A0
[ot
]();
3193 gen_op_mov_reg_T0
[ot
][rm
]();
3196 case 0x1bc: /* bsf */
3197 case 0x1bd: /* bsr */
3198 ot
= dflag
? OT_LONG
: OT_WORD
;
3199 modrm
= ldub(s
->pc
++);
3200 reg
= (modrm
>> 3) & 7;
3201 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3202 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3203 /* NOTE: we always write back the result. Intel doc says it is
3204 undefined if T0 == 0 */
3205 gen_op_mov_reg_T0
[ot
][reg
]();
3206 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3208 /************************/
3210 case 0x27: /* daa */
3211 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3212 gen_op_set_cc_op(s
->cc_op
);
3214 s
->cc_op
= CC_OP_EFLAGS
;
3216 case 0x2f: /* das */
3217 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3218 gen_op_set_cc_op(s
->cc_op
);
3220 s
->cc_op
= CC_OP_EFLAGS
;
3222 case 0x37: /* aaa */
3223 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3224 gen_op_set_cc_op(s
->cc_op
);
3226 s
->cc_op
= CC_OP_EFLAGS
;
3228 case 0x3f: /* aas */
3229 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3230 gen_op_set_cc_op(s
->cc_op
);
3232 s
->cc_op
= CC_OP_EFLAGS
;
3234 case 0xd4: /* aam */
3235 val
= ldub(s
->pc
++);
3237 s
->cc_op
= CC_OP_LOGICB
;
3239 case 0xd5: /* aad */
3240 val
= ldub(s
->pc
++);
3242 s
->cc_op
= CC_OP_LOGICB
;
3244 /************************/
3246 case 0x90: /* nop */
3248 case 0x9b: /* fwait */
3250 case 0xcc: /* int3 */
3251 gen_interrupt(s
, EXCP03_INT3
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3253 case 0xcd: /* int N */
3254 val
= ldub(s
->pc
++);
3255 /* XXX: add error code for vm86 GPF */
3257 gen_interrupt(s
, val
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3259 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3261 case 0xce: /* into */
3262 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3263 gen_op_set_cc_op(s
->cc_op
);
3264 gen_op_into(s
->pc
- s
->cs_base
);
3266 case 0xfa: /* cli */
3268 if (s
->cpl
<= s
->iopl
) {
3271 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3277 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3281 case 0xfb: /* sti */
3283 if (s
->cpl
<= s
->iopl
) {
3286 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3292 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3296 case 0x62: /* bound */
3297 ot
= dflag
? OT_LONG
: OT_WORD
;
3298 modrm
= ldub(s
->pc
++);
3299 reg
= (modrm
>> 3) & 7;
3300 mod
= (modrm
>> 6) & 3;
3303 gen_op_mov_reg_T0
[ot
][reg
]();
3304 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3306 gen_op_boundw(pc_start
- s
->cs_base
);
3308 gen_op_boundl(pc_start
- s
->cs_base
);
3310 case 0x1c8 ... 0x1cf: /* bswap reg */
3312 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3314 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3316 case 0xd6: /* salc */
3317 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3318 gen_op_set_cc_op(s
->cc_op
);
3321 case 0xe0: /* loopnz */
3322 case 0xe1: /* loopz */
3323 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3324 gen_op_set_cc_op(s
->cc_op
);
3326 case 0xe2: /* loop */
3327 case 0xe3: /* jecxz */
3328 val
= (int8_t)insn_get(s
, OT_BYTE
);
3329 next_eip
= s
->pc
- s
->cs_base
;
3333 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3336 case 0x131: /* rdtsc */
3339 case 0x1a2: /* cpuid */
3342 case 0xf4: /* hlt */
3343 /* XXX: if cpl == 0, then should do something else */
3344 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3346 case 0x102: /* lar */
3347 case 0x103: /* lsl */
3350 ot
= dflag
? OT_LONG
: OT_WORD
;
3351 modrm
= ldub(s
->pc
++);
3352 reg
= (modrm
>> 3) & 7;
3353 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3354 gen_op_mov_TN_reg
[ot
][1][reg
]();
3355 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3356 gen_op_set_cc_op(s
->cc_op
);
3361 s
->cc_op
= CC_OP_EFLAGS
;
3362 gen_op_mov_reg_T1
[ot
][reg
]();
3367 /* lock generation */
3368 if (s
->prefix
& PREFIX_LOCK
)
3372 /* XXX: ensure that no lock was generated */
3376 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3377 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3379 /* flags read by an operation */
3380 static uint16_t opc_read_flags
[NB_OPS
] = {
3381 [INDEX_op_aas
] = CC_A
,
3382 [INDEX_op_aaa
] = CC_A
,
3383 [INDEX_op_das
] = CC_A
| CC_C
,
3384 [INDEX_op_daa
] = CC_A
| CC_C
,
3386 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3387 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3388 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3389 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3390 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3391 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3393 /* subtle: due to the incl/decl implementation, C is used */
3394 [INDEX_op_incl_T0_cc
] = CC_C
,
3395 [INDEX_op_decl_T0_cc
] = CC_C
,
3397 [INDEX_op_into
] = CC_O
,
3399 [INDEX_op_jb_subb
] = CC_C
,
3400 [INDEX_op_jb_subw
] = CC_C
,
3401 [INDEX_op_jb_subl
] = CC_C
,
3403 [INDEX_op_jz_subb
] = CC_Z
,
3404 [INDEX_op_jz_subw
] = CC_Z
,
3405 [INDEX_op_jz_subl
] = CC_Z
,
3407 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3408 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3409 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3411 [INDEX_op_js_subb
] = CC_S
,
3412 [INDEX_op_js_subw
] = CC_S
,
3413 [INDEX_op_js_subl
] = CC_S
,
3415 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3416 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3417 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3419 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3420 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3421 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3423 [INDEX_op_loopnzw
] = CC_Z
,
3424 [INDEX_op_loopnzl
] = CC_Z
,
3425 [INDEX_op_loopzw
] = CC_Z
,
3426 [INDEX_op_loopzl
] = CC_Z
,
3428 [INDEX_op_seto_T0_cc
] = CC_O
,
3429 [INDEX_op_setb_T0_cc
] = CC_C
,
3430 [INDEX_op_setz_T0_cc
] = CC_Z
,
3431 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3432 [INDEX_op_sets_T0_cc
] = CC_S
,
3433 [INDEX_op_setp_T0_cc
] = CC_P
,
3434 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3435 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3437 [INDEX_op_setb_T0_subb
] = CC_C
,
3438 [INDEX_op_setb_T0_subw
] = CC_C
,
3439 [INDEX_op_setb_T0_subl
] = CC_C
,
3441 [INDEX_op_setz_T0_subb
] = CC_Z
,
3442 [INDEX_op_setz_T0_subw
] = CC_Z
,
3443 [INDEX_op_setz_T0_subl
] = CC_Z
,
3445 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3446 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3447 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3449 [INDEX_op_sets_T0_subb
] = CC_S
,
3450 [INDEX_op_sets_T0_subw
] = CC_S
,
3451 [INDEX_op_sets_T0_subl
] = CC_S
,
3453 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3454 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3455 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3457 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3458 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3459 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3461 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3462 [INDEX_op_cmc
] = CC_C
,
3463 [INDEX_op_salc
] = CC_C
,
3465 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3466 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3467 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3468 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3469 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3470 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3473 /* flags written by an operation */
3474 static uint16_t opc_write_flags
[NB_OPS
] = {
3475 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3476 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3477 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3478 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3479 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3480 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3481 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3482 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3483 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3484 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3485 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3486 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3487 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3488 /* subtle: due to the incl/decl implementation, C is used */
3489 [INDEX_op_incl_T0_cc
] = CC_OSZAPC
,
3490 [INDEX_op_decl_T0_cc
] = CC_OSZAPC
,
3491 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3493 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3494 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3495 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3496 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3497 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3498 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3499 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3500 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3503 [INDEX_op_aam
] = CC_OSZAPC
,
3504 [INDEX_op_aad
] = CC_OSZAPC
,
3505 [INDEX_op_aas
] = CC_OSZAPC
,
3506 [INDEX_op_aaa
] = CC_OSZAPC
,
3507 [INDEX_op_das
] = CC_OSZAPC
,
3508 [INDEX_op_daa
] = CC_OSZAPC
,
3510 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3511 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
3512 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3513 [INDEX_op_clc
] = CC_C
,
3514 [INDEX_op_stc
] = CC_C
,
3515 [INDEX_op_cmc
] = CC_C
,
3517 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3518 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3519 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3520 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3521 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3522 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3524 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3525 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3526 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3527 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3528 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3529 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3531 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3532 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3533 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3535 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3536 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3537 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3539 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3540 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3541 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3543 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3544 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3545 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3546 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3548 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3549 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3550 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3551 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3553 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3554 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3555 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3556 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3557 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3558 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3559 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3560 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3562 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3563 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3564 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3565 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3568 #define STRINGOP(x) \
3569 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3570 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3571 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3572 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3573 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3574 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3575 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3576 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3577 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3581 STRINGOP(repnz_scas
)
3584 STRINGOP(repnz_cmps
)
3586 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
3587 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3588 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3590 [INDEX_op_cmpxchg8b
] = CC_Z
,
3591 [INDEX_op_lar
] = CC_Z
,
3592 [INDEX_op_lsl
] = CC_Z
,
3593 [INDEX_op_fcomi_ST0_FT0
] = CC_Z
| CC_P
| CC_C
,
3594 [INDEX_op_fucomi_ST0_FT0
] = CC_Z
| CC_P
| CC_C
,
3597 /* simpler form of an operation if no flags need to be generated */
3598 static uint16_t opc_simpler
[NB_OPS
] = {
3599 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3600 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3601 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3602 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3603 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3604 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3605 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3606 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3608 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3609 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3610 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3612 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3613 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3614 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3616 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3617 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3618 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3620 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3621 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3622 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3624 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3625 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3626 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3629 static void optimize_flags_init(void)
3632 /* put default values in arrays */
3633 for(i
= 0; i
< NB_OPS
; i
++) {
3634 if (opc_simpler
[i
] == 0)
3639 /* CPU flags computation optimization: we move backward thru the
3640 generated code to see which flags are needed. The operation is
3641 modified if suitable */
3642 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3645 int live_flags
, write_flags
, op
;
3647 opc_ptr
= opc_buf
+ opc_buf_len
;
3648 /* live_flags contains the flags needed by the next instructions
3649 in the code. At the end of the bloc, we consider that all the
3651 live_flags
= CC_OSZAPC
;
3652 while (opc_ptr
> opc_buf
) {
3654 /* if none of the flags written by the instruction is used,
3655 then we can try to find a simpler instruction */
3656 write_flags
= opc_write_flags
[op
];
3657 if ((live_flags
& write_flags
) == 0) {
3658 *opc_ptr
= opc_simpler
[op
];
3660 /* compute the live flags before the instruction */
3661 live_flags
&= ~write_flags
;
3662 live_flags
|= opc_read_flags
[op
];
3666 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3667 basic block 'tb'. If search_pc is TRUE, also generate PC
3668 information for each intermediate instruction. */
3669 int gen_intermediate_code(TranslationBlock
*tb
, int search_pc
)
3671 DisasContext dc1
, *dc
= &dc1
;
3673 uint16_t *gen_opc_end
;
3679 /* generate intermediate code */
3680 pc_start
= (uint8_t *)tb
->pc
;
3681 cs_base
= (uint8_t *)tb
->cs_base
;
3684 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3685 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3686 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3687 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3688 dc
->vm86
= (flags
>> GEN_FLAG_VM_SHIFT
) & 1;
3689 dc
->cpl
= (flags
>> GEN_FLAG_CPL_SHIFT
) & 3;
3690 dc
->iopl
= (flags
>> GEN_FLAG_IOPL_SHIFT
) & 3;
3691 dc
->tf
= (flags
>> GEN_FLAG_TF_SHIFT
) & 1;
3692 dc
->cc_op
= CC_OP_DYNAMIC
;
3693 dc
->cs_base
= cs_base
;
3696 gen_opc_ptr
= gen_opc_buf
;
3697 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3698 gen_opparam_ptr
= gen_opparam_buf
;
3700 dc
->is_jmp
= DISAS_NEXT
;
3705 j
= gen_opc_ptr
- gen_opc_buf
;
3709 gen_opc_instr_start
[lj
++] = 0;
3710 gen_opc_pc
[lj
] = (uint32_t)pc_ptr
;
3711 gen_opc_instr_start
[lj
] = 1;
3714 ret
= disas_insn(dc
, pc_ptr
);
3716 /* we trigger an illegal instruction operation only if it
3717 is the first instruction. Otherwise, we simply stop
3718 generating the code just before it */
3719 if (pc_ptr
== pc_start
)
3724 pc_ptr
= (void *)ret
;
3725 /* if single step mode, we generate only one instruction and
3726 generate an exception */
3729 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
3730 (pc_ptr
- pc_start
) < (TARGET_PAGE_SIZE
- 32));
3731 /* we must store the eflags state if it is not already done */
3732 if (dc
->is_jmp
!= DISAS_TB_JUMP
) {
3733 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3734 gen_op_set_cc_op(dc
->cc_op
);
3735 if (dc
->is_jmp
!= DISAS_JUMP
) {
3736 /* we add an additionnal jmp to update the simulated PC */
3737 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3741 gen_op_raise_exception(EXCP01_SSTP
);
3743 if (dc
->is_jmp
!= 3) {
3744 /* indicate that the hash table must be used to find the next TB */
3747 *gen_opc_ptr
= INDEX_op_end
;
3751 fprintf(logfile
, "----------------\n");
3752 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
3753 disas(logfile
, pc_start
, pc_ptr
- pc_start
, 0, !dc
->code32
);
3754 fprintf(logfile
, "\n");
3756 fprintf(logfile
, "OP:\n");
3757 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3758 fprintf(logfile
, "\n");
3762 /* optimize flag computations */
3763 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3767 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3768 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3769 fprintf(logfile
, "\n");
3773 tb
->size
= pc_ptr
- pc_start
;
3777 CPUX86State
*cpu_x86_init(void)
3785 env
= malloc(sizeof(CPUX86State
));
3788 memset(env
, 0, sizeof(CPUX86State
));
3789 /* basic FPU init */
3790 for(i
= 0;i
< 8; i
++)
3793 /* flags setup : we activate the IRQs by default as in user mode */
3794 env
->eflags
= 0x2 | IF_MASK
;
3796 /* init various static tables */
3799 optimize_flags_init();
3804 void cpu_x86_close(CPUX86State
*env
)
3809 static const char *cc_op_str
[] = {
3842 void cpu_x86_dump_state(CPUX86State
*env
, FILE *f
, int flags
)
3845 char cc_op_name
[32];
3847 eflags
= env
->eflags
;
3848 fprintf(f
, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3849 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3850 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3851 env
->regs
[R_EAX
], env
->regs
[R_EBX
], env
->regs
[R_ECX
], env
->regs
[R_EDX
],
3852 env
->regs
[R_ESI
], env
->regs
[R_EDI
], env
->regs
[R_EBP
], env
->regs
[R_ESP
],
3854 eflags
& DF_MASK
? 'D' : '-',
3855 eflags
& CC_O
? 'O' : '-',
3856 eflags
& CC_S
? 'S' : '-',
3857 eflags
& CC_Z
? 'Z' : '-',
3858 eflags
& CC_A
? 'A' : '-',
3859 eflags
& CC_P
? 'P' : '-',
3860 eflags
& CC_C
? 'C' : '-');
3861 fprintf(f
, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3868 if (flags
& X86_DUMP_CCOP
) {
3869 if ((unsigned)env
->cc_op
< CC_OP_NB
)
3870 strcpy(cc_op_name
, cc_op_str
[env
->cc_op
]);
3872 snprintf(cc_op_name
, sizeof(cc_op_name
), "[%d]", env
->cc_op
);
3873 fprintf(f
, "CCS=%08x CCD=%08x CCO=%-8s\n",
3874 env
->cc_src
, env
->cc_dst
, cc_op_name
);
3876 if (flags
& X86_DUMP_FPU
) {
3877 fprintf(f
, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
3878 (double)env
->fpregs
[0],
3879 (double)env
->fpregs
[1],
3880 (double)env
->fpregs
[2],
3881 (double)env
->fpregs
[3]);
3882 fprintf(f
, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
3883 (double)env
->fpregs
[4],
3884 (double)env
->fpregs
[5],
3885 (double)env
->fpregs
[7],
3886 (double)env
->fpregs
[8]);