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
115 #define PREFIX_FWAIT 0x20
117 typedef struct DisasContext
{
118 /* current insn context */
119 int override
; /* -1 if no override */
122 uint8_t *pc
; /* pc = eip + cs_base */
123 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
124 static state change (stop translation) */
125 /* current block context */
126 uint8_t *cs_base
; /* base of CS segment */
127 int code32
; /* 32 bit code segment */
128 int ss32
; /* 32 bit stack segment */
129 int cc_op
; /* current CC operation */
130 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
131 int f_st
; /* currently unused */
132 int vm86
; /* vm86 mode */
135 int tf
; /* TF cpu flag */
136 TranslationBlock
*tb
;
139 /* i386 arith/logic operations */
159 OP_SHL1
, /* undocumented */
164 #define DEF(s, n) INDEX_op_ ## s,
165 #include "opc-i386.h"
181 /* I386 int registers */
182 OR_EAX
, /* MUST be even numbered */
190 OR_TMP0
, /* temporary operand register */
192 OR_A0
, /* temporary register used when doing address evaluation */
193 OR_ZERO
, /* fixed zero register */
197 typedef void (GenOpFunc
)(void);
198 typedef void (GenOpFunc1
)(long);
199 typedef void (GenOpFunc2
)(long, long);
200 typedef void (GenOpFunc3
)(long, long, long);
202 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
235 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
268 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
291 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
361 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
372 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
384 gen_op_addl_A0_EAX_s1
,
385 gen_op_addl_A0_ECX_s1
,
386 gen_op_addl_A0_EDX_s1
,
387 gen_op_addl_A0_EBX_s1
,
388 gen_op_addl_A0_ESP_s1
,
389 gen_op_addl_A0_EBP_s1
,
390 gen_op_addl_A0_ESI_s1
,
391 gen_op_addl_A0_EDI_s1
,
394 gen_op_addl_A0_EAX_s2
,
395 gen_op_addl_A0_ECX_s2
,
396 gen_op_addl_A0_EDX_s2
,
397 gen_op_addl_A0_EBX_s2
,
398 gen_op_addl_A0_ESP_s2
,
399 gen_op_addl_A0_EBP_s2
,
400 gen_op_addl_A0_ESI_s2
,
401 gen_op_addl_A0_EDI_s2
,
404 gen_op_addl_A0_EAX_s3
,
405 gen_op_addl_A0_ECX_s3
,
406 gen_op_addl_A0_EDX_s3
,
407 gen_op_addl_A0_EBX_s3
,
408 gen_op_addl_A0_ESP_s3
,
409 gen_op_addl_A0_EBP_s3
,
410 gen_op_addl_A0_ESI_s3
,
411 gen_op_addl_A0_EDI_s3
,
415 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
417 gen_op_cmovw_EAX_T1_T0
,
418 gen_op_cmovw_ECX_T1_T0
,
419 gen_op_cmovw_EDX_T1_T0
,
420 gen_op_cmovw_EBX_T1_T0
,
421 gen_op_cmovw_ESP_T1_T0
,
422 gen_op_cmovw_EBP_T1_T0
,
423 gen_op_cmovw_ESI_T1_T0
,
424 gen_op_cmovw_EDI_T1_T0
,
427 gen_op_cmovl_EAX_T1_T0
,
428 gen_op_cmovl_ECX_T1_T0
,
429 gen_op_cmovl_EDX_T1_T0
,
430 gen_op_cmovl_EBX_T1_T0
,
431 gen_op_cmovl_ESP_T1_T0
,
432 gen_op_cmovl_EBP_T1_T0
,
433 gen_op_cmovl_ESI_T1_T0
,
434 gen_op_cmovl_EDI_T1_T0
,
438 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
439 gen_op_addl_T0_T1_cc
,
443 gen_op_andl_T0_T1_cc
,
444 gen_op_subl_T0_T1_cc
,
445 gen_op_xorl_T0_T1_cc
,
446 gen_op_cmpl_T0_T1_cc
,
449 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
451 gen_op_adcb_T0_T1_cc
,
452 gen_op_sbbb_T0_T1_cc
,
455 gen_op_adcw_T0_T1_cc
,
456 gen_op_sbbw_T0_T1_cc
,
459 gen_op_adcl_T0_T1_cc
,
460 gen_op_sbbl_T0_T1_cc
,
464 static const int cc_op_arithb
[8] = {
475 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
476 gen_op_cmpxchgb_T0_T1_EAX_cc
,
477 gen_op_cmpxchgw_T0_T1_EAX_cc
,
478 gen_op_cmpxchgl_T0_T1_EAX_cc
,
481 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
483 gen_op_rolb_T0_T1_cc
,
484 gen_op_rorb_T0_T1_cc
,
485 gen_op_rclb_T0_T1_cc
,
486 gen_op_rcrb_T0_T1_cc
,
487 gen_op_shlb_T0_T1_cc
,
488 gen_op_shrb_T0_T1_cc
,
489 gen_op_shlb_T0_T1_cc
,
490 gen_op_sarb_T0_T1_cc
,
493 gen_op_rolw_T0_T1_cc
,
494 gen_op_rorw_T0_T1_cc
,
495 gen_op_rclw_T0_T1_cc
,
496 gen_op_rcrw_T0_T1_cc
,
497 gen_op_shlw_T0_T1_cc
,
498 gen_op_shrw_T0_T1_cc
,
499 gen_op_shlw_T0_T1_cc
,
500 gen_op_sarw_T0_T1_cc
,
503 gen_op_roll_T0_T1_cc
,
504 gen_op_rorl_T0_T1_cc
,
505 gen_op_rcll_T0_T1_cc
,
506 gen_op_rcrl_T0_T1_cc
,
507 gen_op_shll_T0_T1_cc
,
508 gen_op_shrl_T0_T1_cc
,
509 gen_op_shll_T0_T1_cc
,
510 gen_op_sarl_T0_T1_cc
,
514 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
516 gen_op_shldw_T0_T1_im_cc
,
517 gen_op_shrdw_T0_T1_im_cc
,
520 gen_op_shldl_T0_T1_im_cc
,
521 gen_op_shrdl_T0_T1_im_cc
,
525 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
527 gen_op_shldw_T0_T1_ECX_cc
,
528 gen_op_shrdw_T0_T1_ECX_cc
,
531 gen_op_shldl_T0_T1_ECX_cc
,
532 gen_op_shrdl_T0_T1_ECX_cc
,
536 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
539 gen_op_btsw_T0_T1_cc
,
540 gen_op_btrw_T0_T1_cc
,
541 gen_op_btcw_T0_T1_cc
,
545 gen_op_btsl_T0_T1_cc
,
546 gen_op_btrl_T0_T1_cc
,
547 gen_op_btcl_T0_T1_cc
,
551 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
562 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
567 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
572 /* sign does not matter */
573 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
579 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
585 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
591 /* the _a32 and _a16 string operations use A0 as the base register. */
593 #define STRINGOP(x) \
594 gen_op_ ## x ## b_fast, \
595 gen_op_ ## x ## w_fast, \
596 gen_op_ ## x ## l_fast, \
597 gen_op_ ## x ## b_a32, \
598 gen_op_ ## x ## w_a32, \
599 gen_op_ ## x ## l_a32, \
600 gen_op_ ## x ## b_a16, \
601 gen_op_ ## x ## w_a16, \
602 gen_op_ ## x ## l_a16,
604 static GenOpFunc
*gen_op_movs
[9 * 2] = {
609 static GenOpFunc
*gen_op_stos
[9 * 2] = {
614 static GenOpFunc
*gen_op_lods
[9 * 2] = {
619 static GenOpFunc
*gen_op_scas
[9 * 3] = {
625 static GenOpFunc
*gen_op_cmps
[9 * 3] = {
631 static GenOpFunc
*gen_op_ins
[9 * 2] = {
637 static GenOpFunc
*gen_op_outs
[9 * 2] = {
643 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
647 override
= s
->override
;
650 if (s
->addseg
&& override
< 0)
653 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
661 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
662 /* 16 address, always override */
668 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
685 static GenOpFunc
*gen_op_in
[3] = {
691 static GenOpFunc
*gen_op_out
[3] = {
708 static GenOpFunc3
*gen_jcc_sub
[3][8] = {
740 static GenOpFunc2
*gen_op_loop
[2][4] = {
755 static GenOpFunc
*gen_setcc_slow
[8] = {
766 static GenOpFunc
*gen_setcc_sub
[3][8] = {
771 gen_op_setbe_T0_subb
,
775 gen_op_setle_T0_subb
,
781 gen_op_setbe_T0_subw
,
785 gen_op_setle_T0_subw
,
791 gen_op_setbe_T0_subl
,
795 gen_op_setle_T0_subl
,
799 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
805 gen_op_fsubr_ST0_FT0
,
807 gen_op_fdivr_ST0_FT0
,
810 /* NOTE the exception in "r" op ordering */
811 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
816 gen_op_fsubr_STN_ST0
,
818 gen_op_fdivr_STN_ST0
,
822 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
825 gen_op_mov_TN_reg
[ot
][0][d
]();
827 gen_op_mov_TN_reg
[ot
][1][s
]();
828 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
829 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
830 gen_op_set_cc_op(s1
->cc_op
);
831 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
832 s1
->cc_op
= CC_OP_DYNAMIC
;
834 gen_op_arith_T0_T1_cc
[op
]();
835 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
837 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
838 gen_op_mov_reg_T0
[ot
][d
]();
841 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
843 gen_op_movl_T1_im(c
);
844 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
847 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
850 gen_op_mov_TN_reg
[ot
][0][d
]();
851 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
852 gen_op_set_cc_op(s1
->cc_op
);
855 s1
->cc_op
= CC_OP_INCB
+ ot
;
858 s1
->cc_op
= CC_OP_DECB
+ ot
;
861 gen_op_mov_reg_T0
[ot
][d
]();
864 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
867 gen_op_mov_TN_reg
[ot
][0][d
]();
869 gen_op_mov_TN_reg
[ot
][1][s
]();
870 /* for zero counts, flags are not updated, so must do it dynamically */
871 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
872 gen_op_set_cc_op(s1
->cc_op
);
874 gen_op_shift_T0_T1_cc
[ot
][op
]();
877 gen_op_mov_reg_T0
[ot
][d
]();
878 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
881 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
883 /* currently not optimized */
884 gen_op_movl_T1_im(c
);
885 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
888 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
895 int mod
, rm
, code
, override
, must_add_seg
;
897 override
= s
->override
;
898 must_add_seg
= s
->addseg
;
901 mod
= (modrm
>> 6) & 3;
913 code
= ldub(s
->pc
++);
914 scale
= (code
>> 6) & 3;
915 index
= (code
>> 3) & 7;
930 disp
= (int8_t)ldub(s
->pc
++);
940 gen_op_movl_A0_reg
[base
]();
942 gen_op_addl_A0_im(disp
);
944 gen_op_movl_A0_im(disp
);
946 if (havesib
&& (index
!= 4 || scale
!= 0)) {
947 gen_op_addl_A0_reg_sN
[scale
][index
]();
951 if (base
== R_EBP
|| base
== R_ESP
)
956 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
964 gen_op_movl_A0_im(disp
);
965 rm
= 0; /* avoid SS override */
972 disp
= (int8_t)ldub(s
->pc
++);
982 gen_op_movl_A0_reg
[R_EBX
]();
983 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
986 gen_op_movl_A0_reg
[R_EBX
]();
987 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
990 gen_op_movl_A0_reg
[R_EBP
]();
991 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
994 gen_op_movl_A0_reg
[R_EBP
]();
995 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
998 gen_op_movl_A0_reg
[R_ESI
]();
1001 gen_op_movl_A0_reg
[R_EDI
]();
1004 gen_op_movl_A0_reg
[R_EBP
]();
1008 gen_op_movl_A0_reg
[R_EBX
]();
1012 gen_op_addl_A0_im(disp
);
1013 gen_op_andl_A0_ffff();
1017 if (rm
== 2 || rm
== 3 || rm
== 6)
1022 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
1032 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1034 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1036 int mod
, rm
, opreg
, disp
;
1038 mod
= (modrm
>> 6) & 3;
1043 gen_op_mov_TN_reg
[ot
][0][reg
]();
1044 gen_op_mov_reg_T0
[ot
][rm
]();
1046 gen_op_mov_TN_reg
[ot
][0][rm
]();
1048 gen_op_mov_reg_T0
[ot
][reg
]();
1051 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1054 gen_op_mov_TN_reg
[ot
][0][reg
]();
1055 gen_op_st_T0_A0
[ot
]();
1057 gen_op_ld_T0_A0
[ot
]();
1059 gen_op_mov_reg_T0
[ot
][reg
]();
1064 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1086 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1088 TranslationBlock
*tb
;
1093 jcc_op
= (b
>> 1) & 7;
1095 /* we optimize the cmp/jcc case */
1099 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1102 /* some jumps are easy to compute */
1129 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1132 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1144 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1145 gen_op_set_cc_op(s
->cc_op
);
1148 gen_setcc_slow
[jcc_op
]();
1154 func((long)tb
, val
, next_eip
);
1156 func((long)tb
, next_eip
, val
);
1161 static void gen_setcc(DisasContext
*s
, int b
)
1167 jcc_op
= (b
>> 1) & 7;
1169 /* we optimize the cmp/jcc case */
1173 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1178 /* some jumps are easy to compute */
1196 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1199 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1207 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1208 gen_op_set_cc_op(s
->cc_op
);
1209 func
= gen_setcc_slow
[jcc_op
];
1218 /* move T0 to seg_reg and compute if the CPU state may change */
1219 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
)
1221 gen_op_movl_seg_T0(seg_reg
);
1222 if (!s
->addseg
&& seg_reg
< R_FS
)
1223 s
->is_jmp
= 2; /* abort translation because the register may
1224 have a non zero base */
1227 /* generate a push. It depends on ss32, addseg and dflag */
1228 static void gen_push_T0(DisasContext
*s
)
1238 gen_op_pushl_ss32_T0();
1240 gen_op_pushw_ss32_T0();
1244 gen_op_pushl_ss16_T0();
1246 gen_op_pushw_ss16_T0();
1250 /* two step pop is necessary for precise exceptions */
1251 static void gen_pop_T0(DisasContext
*s
)
1261 gen_op_popl_ss32_T0();
1263 gen_op_popw_ss32_T0();
1267 gen_op_popl_ss16_T0();
1269 gen_op_popw_ss16_T0();
1273 static void gen_pop_update(DisasContext
*s
)
1277 gen_op_addl_ESP_4();
1279 gen_op_addl_ESP_2();
1282 gen_op_addw_ESP_4();
1284 gen_op_addw_ESP_2();
1288 /* NOTE: wrap around in 16 bit not fully handled */
1289 static void gen_pusha(DisasContext
*s
)
1292 gen_op_movl_A0_ESP();
1293 gen_op_addl_A0_im(-16 << s
->dflag
);
1295 gen_op_andl_A0_ffff();
1296 gen_op_movl_T1_A0();
1298 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1299 for(i
= 0;i
< 8; i
++) {
1300 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1301 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1302 gen_op_addl_A0_im(2 << s
->dflag
);
1304 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1307 /* NOTE: wrap around in 16 bit not fully handled */
1308 static void gen_popa(DisasContext
*s
)
1311 gen_op_movl_A0_ESP();
1313 gen_op_andl_A0_ffff();
1314 gen_op_movl_T1_A0();
1315 gen_op_addl_T1_im(16 << s
->dflag
);
1317 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1318 for(i
= 0;i
< 8; i
++) {
1319 /* ESP is not reloaded */
1321 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1322 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1324 gen_op_addl_A0_im(2 << s
->dflag
);
1326 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1329 /* NOTE: wrap around in 16 bit not fully handled */
1330 /* XXX: check this */
1331 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1333 int ot
, level1
, addend
, opsize
;
1335 ot
= s
->dflag
+ OT_WORD
;
1338 opsize
= 2 << s
->dflag
;
1340 gen_op_movl_A0_ESP();
1341 gen_op_addl_A0_im(-opsize
);
1343 gen_op_andl_A0_ffff();
1344 gen_op_movl_T1_A0();
1346 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1348 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1349 gen_op_st_T0_A0
[ot
]();
1352 gen_op_addl_A0_im(-opsize
);
1353 gen_op_addl_T0_im(-opsize
);
1354 gen_op_st_T0_A0
[ot
]();
1356 gen_op_addl_A0_im(-opsize
);
1357 /* XXX: add st_T1_A0 ? */
1358 gen_op_movl_T0_T1();
1359 gen_op_st_T0_A0
[ot
]();
1361 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1362 addend
= -esp_addend
;
1364 addend
-= opsize
* (level1
+ 1);
1365 gen_op_addl_T1_im(addend
);
1366 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1369 static void gen_exception(DisasContext
*s
, int trapno
, unsigned int cur_eip
)
1371 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1372 gen_op_set_cc_op(s
->cc_op
);
1373 gen_op_jmp_im(cur_eip
);
1374 gen_op_raise_exception(trapno
);
1378 /* generate a jump to eip. No segment change must happen before as a
1379 direct call to the next block may occur */
1380 static void gen_jmp(DisasContext
*s
, unsigned int eip
)
1382 TranslationBlock
*tb
= s
->tb
;
1384 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1385 gen_op_set_cc_op(s
->cc_op
);
1386 gen_op_jmp_tb_next((long)tb
, eip
);
1390 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1391 is set to true if the instruction sets the PC (last instruction of
1393 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1395 int b
, prefixes
, aflag
, dflag
;
1397 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1398 unsigned int next_eip
;
1408 /* check prefixes */
1411 prefixes
|= PREFIX_REPZ
;
1414 prefixes
|= PREFIX_REPNZ
;
1417 prefixes
|= PREFIX_LOCK
;
1438 prefixes
|= PREFIX_DATA
;
1441 prefixes
|= PREFIX_ADR
;
1444 prefixes
|= PREFIX_FWAIT
;
1448 if (prefixes
& PREFIX_DATA
)
1450 if (prefixes
& PREFIX_ADR
)
1453 s
->prefix
= prefixes
;
1457 /* lock generation */
1458 if (prefixes
& PREFIX_LOCK
)
1461 /* now check op code */
1465 /**************************/
1466 /* extended op code */
1467 b
= ldub(s
->pc
++) | 0x100;
1470 /**************************/
1488 ot
= dflag
? OT_LONG
: OT_WORD
;
1491 case 0: /* OP Ev, Gv */
1492 modrm
= ldub(s
->pc
++);
1493 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1494 mod
= (modrm
>> 6) & 3;
1497 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1498 gen_op_ld_T0_A0
[ot
]();
1501 opreg
= OR_EAX
+ rm
;
1503 gen_op(s
, op
, ot
, opreg
, reg
);
1504 if (mod
!= 3 && op
!= 7) {
1505 gen_op_st_T0_A0
[ot
]();
1508 case 1: /* OP Gv, Ev */
1509 modrm
= ldub(s
->pc
++);
1510 mod
= (modrm
>> 6) & 3;
1511 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1514 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1515 gen_op_ld_T1_A0
[ot
]();
1518 opreg
= OR_EAX
+ rm
;
1520 gen_op(s
, op
, ot
, reg
, opreg
);
1522 case 2: /* OP A, Iv */
1523 val
= insn_get(s
, ot
);
1524 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1530 case 0x80: /* GRP1 */
1539 ot
= dflag
? OT_LONG
: OT_WORD
;
1541 modrm
= ldub(s
->pc
++);
1542 mod
= (modrm
>> 6) & 3;
1544 op
= (modrm
>> 3) & 7;
1547 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1548 gen_op_ld_T0_A0
[ot
]();
1551 opreg
= rm
+ OR_EAX
;
1558 val
= insn_get(s
, ot
);
1561 val
= (int8_t)insn_get(s
, OT_BYTE
);
1565 gen_opi(s
, op
, ot
, opreg
, val
);
1566 if (op
!= 7 && mod
!= 3) {
1567 gen_op_st_T0_A0
[ot
]();
1572 /**************************/
1573 /* inc, dec, and other misc arith */
1574 case 0x40 ... 0x47: /* inc Gv */
1575 ot
= dflag
? OT_LONG
: OT_WORD
;
1576 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1578 case 0x48 ... 0x4f: /* dec Gv */
1579 ot
= dflag
? OT_LONG
: OT_WORD
;
1580 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1582 case 0xf6: /* GRP3 */
1587 ot
= dflag
? OT_LONG
: OT_WORD
;
1589 modrm
= ldub(s
->pc
++);
1590 mod
= (modrm
>> 6) & 3;
1592 op
= (modrm
>> 3) & 7;
1594 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1595 gen_op_ld_T0_A0
[ot
]();
1597 gen_op_mov_TN_reg
[ot
][0][rm
]();
1602 val
= insn_get(s
, ot
);
1603 gen_op_movl_T1_im(val
);
1604 gen_op_testl_T0_T1_cc();
1605 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1610 gen_op_st_T0_A0
[ot
]();
1612 gen_op_mov_reg_T0
[ot
][rm
]();
1616 gen_op_negl_T0_cc();
1618 gen_op_st_T0_A0
[ot
]();
1620 gen_op_mov_reg_T0
[ot
][rm
]();
1622 s
->cc_op
= CC_OP_SUBB
+ ot
;
1627 gen_op_mulb_AL_T0();
1630 gen_op_mulw_AX_T0();
1634 gen_op_mull_EAX_T0();
1637 s
->cc_op
= CC_OP_MUL
;
1642 gen_op_imulb_AL_T0();
1645 gen_op_imulw_AX_T0();
1649 gen_op_imull_EAX_T0();
1652 s
->cc_op
= CC_OP_MUL
;
1657 gen_op_divb_AL_T0();
1660 gen_op_divw_AX_T0();
1664 gen_op_divl_EAX_T0();
1671 gen_op_idivb_AL_T0();
1674 gen_op_idivw_AX_T0();
1678 gen_op_idivl_EAX_T0();
1687 case 0xfe: /* GRP4 */
1688 case 0xff: /* GRP5 */
1692 ot
= dflag
? OT_LONG
: OT_WORD
;
1694 modrm
= ldub(s
->pc
++);
1695 mod
= (modrm
>> 6) & 3;
1697 op
= (modrm
>> 3) & 7;
1698 if (op
>= 2 && b
== 0xfe) {
1702 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1703 if (op
!= 3 && op
!= 5)
1704 gen_op_ld_T0_A0
[ot
]();
1706 gen_op_mov_TN_reg
[ot
][0][rm
]();
1710 case 0: /* inc Ev */
1711 gen_inc(s
, ot
, OR_TMP0
, 1);
1713 gen_op_st_T0_A0
[ot
]();
1715 gen_op_mov_reg_T0
[ot
][rm
]();
1717 case 1: /* dec Ev */
1718 gen_inc(s
, ot
, OR_TMP0
, -1);
1720 gen_op_st_T0_A0
[ot
]();
1722 gen_op_mov_reg_T0
[ot
][rm
]();
1724 case 2: /* call Ev */
1725 /* XXX: optimize if memory (no and is necessary) */
1727 gen_op_andl_T0_ffff();
1729 next_eip
= s
->pc
- s
->cs_base
;
1730 gen_op_movl_T0_im(next_eip
);
1734 case 3: /* lcall Ev */
1735 /* push return segment + offset */
1736 gen_op_movl_T0_seg(R_CS
);
1738 next_eip
= s
->pc
- s
->cs_base
;
1739 gen_op_movl_T0_im(next_eip
);
1742 gen_op_ld_T1_A0
[ot
]();
1743 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1744 gen_op_lduw_T0_A0();
1745 gen_movl_seg_T0(s
, R_CS
);
1746 gen_op_movl_T0_T1();
1750 case 4: /* jmp Ev */
1752 gen_op_andl_T0_ffff();
1756 case 5: /* ljmp Ev */
1757 gen_op_ld_T1_A0
[ot
]();
1758 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1759 gen_op_lduw_T0_A0();
1760 gen_movl_seg_T0(s
, R_CS
);
1761 gen_op_movl_T0_T1();
1765 case 6: /* push Ev */
1773 case 0x84: /* test Ev, Gv */
1778 ot
= dflag
? OT_LONG
: OT_WORD
;
1780 modrm
= ldub(s
->pc
++);
1781 mod
= (modrm
>> 6) & 3;
1783 reg
= (modrm
>> 3) & 7;
1785 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1786 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1787 gen_op_testl_T0_T1_cc();
1788 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1791 case 0xa8: /* test eAX, Iv */
1796 ot
= dflag
? OT_LONG
: OT_WORD
;
1797 val
= insn_get(s
, ot
);
1799 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1800 gen_op_movl_T1_im(val
);
1801 gen_op_testl_T0_T1_cc();
1802 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1805 case 0x98: /* CWDE/CBW */
1807 gen_op_movswl_EAX_AX();
1809 gen_op_movsbw_AX_AL();
1811 case 0x99: /* CDQ/CWD */
1813 gen_op_movslq_EDX_EAX();
1815 gen_op_movswl_DX_AX();
1817 case 0x1af: /* imul Gv, Ev */
1818 case 0x69: /* imul Gv, Ev, I */
1820 ot
= dflag
? OT_LONG
: OT_WORD
;
1821 modrm
= ldub(s
->pc
++);
1822 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1823 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1825 val
= insn_get(s
, ot
);
1826 gen_op_movl_T1_im(val
);
1827 } else if (b
== 0x6b) {
1828 val
= insn_get(s
, OT_BYTE
);
1829 gen_op_movl_T1_im(val
);
1831 gen_op_mov_TN_reg
[ot
][1][reg
]();
1834 if (ot
== OT_LONG
) {
1835 gen_op_imull_T0_T1();
1837 gen_op_imulw_T0_T1();
1839 gen_op_mov_reg_T0
[ot
][reg
]();
1840 s
->cc_op
= CC_OP_MUL
;
1843 case 0x1c1: /* xadd Ev, Gv */
1847 ot
= dflag
? OT_LONG
: OT_WORD
;
1848 modrm
= ldub(s
->pc
++);
1849 reg
= (modrm
>> 3) & 7;
1850 mod
= (modrm
>> 6) & 3;
1853 gen_op_mov_TN_reg
[ot
][0][reg
]();
1854 gen_op_mov_TN_reg
[ot
][1][rm
]();
1855 gen_op_addl_T0_T1_cc();
1856 gen_op_mov_reg_T0
[ot
][rm
]();
1857 gen_op_mov_reg_T1
[ot
][reg
]();
1859 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1860 gen_op_mov_TN_reg
[ot
][0][reg
]();
1861 gen_op_ld_T1_A0
[ot
]();
1862 gen_op_addl_T0_T1_cc();
1863 gen_op_st_T0_A0
[ot
]();
1864 gen_op_mov_reg_T1
[ot
][reg
]();
1866 s
->cc_op
= CC_OP_ADDB
+ ot
;
1869 case 0x1b1: /* cmpxchg Ev, Gv */
1873 ot
= dflag
? OT_LONG
: OT_WORD
;
1874 modrm
= ldub(s
->pc
++);
1875 reg
= (modrm
>> 3) & 7;
1876 mod
= (modrm
>> 6) & 3;
1877 gen_op_mov_TN_reg
[ot
][1][reg
]();
1880 gen_op_mov_TN_reg
[ot
][0][rm
]();
1881 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1882 gen_op_mov_reg_T0
[ot
][rm
]();
1884 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1885 gen_op_ld_T0_A0
[ot
]();
1886 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1887 gen_op_st_T0_A0
[ot
]();
1889 s
->cc_op
= CC_OP_SUBB
+ ot
;
1891 case 0x1c7: /* cmpxchg8b */
1892 modrm
= ldub(s
->pc
++);
1893 mod
= (modrm
>> 6) & 3;
1896 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1897 gen_op_set_cc_op(s
->cc_op
);
1898 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1900 s
->cc_op
= CC_OP_EFLAGS
;
1903 /**************************/
1905 case 0x50 ... 0x57: /* push */
1906 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1909 case 0x58 ... 0x5f: /* pop */
1910 ot
= dflag
? OT_LONG
: OT_WORD
;
1912 gen_op_mov_reg_T0
[ot
][b
& 7]();
1915 case 0x60: /* pusha */
1918 case 0x61: /* popa */
1921 case 0x68: /* push Iv */
1923 ot
= dflag
? OT_LONG
: OT_WORD
;
1925 val
= insn_get(s
, ot
);
1927 val
= (int8_t)insn_get(s
, OT_BYTE
);
1928 gen_op_movl_T0_im(val
);
1931 case 0x8f: /* pop Ev */
1932 ot
= dflag
? OT_LONG
: OT_WORD
;
1933 modrm
= ldub(s
->pc
++);
1935 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1938 case 0xc8: /* enter */
1943 level
= ldub(s
->pc
++);
1944 gen_enter(s
, val
, level
);
1947 case 0xc9: /* leave */
1948 /* XXX: exception not precise (ESP is update before potential exception) */
1950 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1951 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1953 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1954 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1957 ot
= dflag
? OT_LONG
: OT_WORD
;
1958 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1961 case 0x06: /* push es */
1962 case 0x0e: /* push cs */
1963 case 0x16: /* push ss */
1964 case 0x1e: /* push ds */
1965 gen_op_movl_T0_seg(b
>> 3);
1968 case 0x1a0: /* push fs */
1969 case 0x1a8: /* push gs */
1970 gen_op_movl_T0_seg((b
>> 3) & 7);
1973 case 0x07: /* pop es */
1974 case 0x17: /* pop ss */
1975 case 0x1f: /* pop ds */
1977 gen_movl_seg_T0(s
, b
>> 3);
1980 case 0x1a1: /* pop fs */
1981 case 0x1a9: /* pop gs */
1983 gen_movl_seg_T0(s
, (b
>> 3) & 7);
1987 /**************************/
1990 case 0x89: /* mov Gv, Ev */
1994 ot
= dflag
? OT_LONG
: OT_WORD
;
1995 modrm
= ldub(s
->pc
++);
1996 reg
= (modrm
>> 3) & 7;
1998 /* generate a generic store */
1999 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
2002 case 0xc7: /* mov Ev, Iv */
2006 ot
= dflag
? OT_LONG
: OT_WORD
;
2007 modrm
= ldub(s
->pc
++);
2008 mod
= (modrm
>> 6) & 3;
2010 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2011 val
= insn_get(s
, ot
);
2012 gen_op_movl_T0_im(val
);
2014 gen_op_st_T0_A0
[ot
]();
2016 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
2019 case 0x8b: /* mov Ev, Gv */
2023 ot
= dflag
? OT_LONG
: OT_WORD
;
2024 modrm
= ldub(s
->pc
++);
2025 reg
= (modrm
>> 3) & 7;
2027 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2028 gen_op_mov_reg_T0
[ot
][reg
]();
2030 case 0x8e: /* mov seg, Gv */
2031 ot
= dflag
? OT_LONG
: OT_WORD
;
2032 modrm
= ldub(s
->pc
++);
2033 reg
= (modrm
>> 3) & 7;
2034 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2035 if (reg
>= 6 || reg
== R_CS
)
2037 gen_movl_seg_T0(s
, reg
);
2039 case 0x8c: /* mov Gv, seg */
2040 ot
= dflag
? OT_LONG
: OT_WORD
;
2041 modrm
= ldub(s
->pc
++);
2042 reg
= (modrm
>> 3) & 7;
2045 gen_op_movl_T0_seg(reg
);
2046 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2049 case 0x1b6: /* movzbS Gv, Eb */
2050 case 0x1b7: /* movzwS Gv, Eb */
2051 case 0x1be: /* movsbS Gv, Eb */
2052 case 0x1bf: /* movswS Gv, Eb */
2055 /* d_ot is the size of destination */
2056 d_ot
= dflag
+ OT_WORD
;
2057 /* ot is the size of source */
2058 ot
= (b
& 1) + OT_BYTE
;
2059 modrm
= ldub(s
->pc
++);
2060 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2061 mod
= (modrm
>> 6) & 3;
2065 gen_op_mov_TN_reg
[ot
][0][rm
]();
2066 switch(ot
| (b
& 8)) {
2068 gen_op_movzbl_T0_T0();
2071 gen_op_movsbl_T0_T0();
2074 gen_op_movzwl_T0_T0();
2078 gen_op_movswl_T0_T0();
2081 gen_op_mov_reg_T0
[d_ot
][reg
]();
2083 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2085 gen_op_lds_T0_A0
[ot
]();
2087 gen_op_ldu_T0_A0
[ot
]();
2089 gen_op_mov_reg_T0
[d_ot
][reg
]();
2094 case 0x8d: /* lea */
2095 ot
= dflag
? OT_LONG
: OT_WORD
;
2096 modrm
= ldub(s
->pc
++);
2097 reg
= (modrm
>> 3) & 7;
2098 /* we must ensure that no segment is added */
2102 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2104 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2107 case 0xa0: /* mov EAX, Ov */
2109 case 0xa2: /* mov Ov, EAX */
2114 ot
= dflag
? OT_LONG
: OT_WORD
;
2116 offset_addr
= insn_get(s
, OT_LONG
);
2118 offset_addr
= insn_get(s
, OT_WORD
);
2119 gen_op_movl_A0_im(offset_addr
);
2120 /* handle override */
2122 int override
, must_add_seg
;
2123 must_add_seg
= s
->addseg
;
2124 if (s
->override
>= 0) {
2125 override
= s
->override
;
2131 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2135 gen_op_ld_T0_A0
[ot
]();
2136 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2138 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2139 gen_op_st_T0_A0
[ot
]();
2142 case 0xd7: /* xlat */
2143 gen_op_movl_A0_reg
[R_EBX
]();
2144 gen_op_addl_A0_AL();
2146 gen_op_andl_A0_ffff();
2147 /* handle override */
2149 int override
, must_add_seg
;
2150 must_add_seg
= s
->addseg
;
2152 if (s
->override
>= 0) {
2153 override
= s
->override
;
2159 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2162 gen_op_ldub_T0_A0();
2163 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2165 case 0xb0 ... 0xb7: /* mov R, Ib */
2166 val
= insn_get(s
, OT_BYTE
);
2167 gen_op_movl_T0_im(val
);
2168 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2170 case 0xb8 ... 0xbf: /* mov R, Iv */
2171 ot
= dflag
? OT_LONG
: OT_WORD
;
2172 val
= insn_get(s
, ot
);
2173 reg
= OR_EAX
+ (b
& 7);
2174 gen_op_movl_T0_im(val
);
2175 gen_op_mov_reg_T0
[ot
][reg
]();
2178 case 0x91 ... 0x97: /* xchg R, EAX */
2179 ot
= dflag
? OT_LONG
: OT_WORD
;
2184 case 0x87: /* xchg Ev, Gv */
2188 ot
= dflag
? OT_LONG
: OT_WORD
;
2189 modrm
= ldub(s
->pc
++);
2190 reg
= (modrm
>> 3) & 7;
2191 mod
= (modrm
>> 6) & 3;
2195 gen_op_mov_TN_reg
[ot
][0][reg
]();
2196 gen_op_mov_TN_reg
[ot
][1][rm
]();
2197 gen_op_mov_reg_T0
[ot
][rm
]();
2198 gen_op_mov_reg_T1
[ot
][reg
]();
2200 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2201 gen_op_mov_TN_reg
[ot
][0][reg
]();
2202 /* for xchg, lock is implicit */
2203 if (!(prefixes
& PREFIX_LOCK
))
2205 gen_op_ld_T1_A0
[ot
]();
2206 gen_op_st_T0_A0
[ot
]();
2207 if (!(prefixes
& PREFIX_LOCK
))
2209 gen_op_mov_reg_T1
[ot
][reg
]();
2212 case 0xc4: /* les Gv */
2215 case 0xc5: /* lds Gv */
2218 case 0x1b2: /* lss Gv */
2221 case 0x1b4: /* lfs Gv */
2224 case 0x1b5: /* lgs Gv */
2227 ot
= dflag
? OT_LONG
: OT_WORD
;
2228 modrm
= ldub(s
->pc
++);
2229 reg
= (modrm
>> 3) & 7;
2230 mod
= (modrm
>> 6) & 3;
2233 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2234 gen_op_ld_T1_A0
[ot
]();
2235 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2236 /* load the segment first to handle exceptions properly */
2237 gen_op_lduw_T0_A0();
2238 gen_movl_seg_T0(s
, op
);
2239 /* then put the data */
2240 gen_op_mov_reg_T1
[ot
][reg
]();
2243 /************************/
2254 ot
= dflag
? OT_LONG
: OT_WORD
;
2256 modrm
= ldub(s
->pc
++);
2257 mod
= (modrm
>> 6) & 3;
2259 op
= (modrm
>> 3) & 7;
2262 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2263 gen_op_ld_T0_A0
[ot
]();
2266 opreg
= rm
+ OR_EAX
;
2271 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2274 shift
= ldub(s
->pc
++);
2276 gen_shifti(s
, op
, ot
, opreg
, shift
);
2280 gen_op_st_T0_A0
[ot
]();
2295 case 0x1a4: /* shld imm */
2299 case 0x1a5: /* shld cl */
2303 case 0x1ac: /* shrd imm */
2307 case 0x1ad: /* shrd cl */
2311 ot
= dflag
? OT_LONG
: OT_WORD
;
2312 modrm
= ldub(s
->pc
++);
2313 mod
= (modrm
>> 6) & 3;
2315 reg
= (modrm
>> 3) & 7;
2318 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2319 gen_op_ld_T0_A0
[ot
]();
2321 gen_op_mov_TN_reg
[ot
][0][rm
]();
2323 gen_op_mov_TN_reg
[ot
][1][reg
]();
2326 val
= ldub(s
->pc
++);
2329 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2330 if (op
== 0 && ot
!= OT_WORD
)
2331 s
->cc_op
= CC_OP_SHLB
+ ot
;
2333 s
->cc_op
= CC_OP_SARB
+ ot
;
2336 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2337 gen_op_set_cc_op(s
->cc_op
);
2338 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2339 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2342 gen_op_st_T0_A0
[ot
]();
2344 gen_op_mov_reg_T0
[ot
][rm
]();
2348 /************************/
2351 modrm
= ldub(s
->pc
++);
2352 mod
= (modrm
>> 6) & 3;
2354 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2358 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2360 case 0x00 ... 0x07: /* fxxxs */
2361 case 0x10 ... 0x17: /* fixxxl */
2362 case 0x20 ... 0x27: /* fxxxl */
2363 case 0x30 ... 0x37: /* fixxx */
2370 gen_op_flds_FT0_A0();
2373 gen_op_fildl_FT0_A0();
2376 gen_op_fldl_FT0_A0();
2380 gen_op_fild_FT0_A0();
2384 gen_op_fp_arith_ST0_FT0
[op1
]();
2386 /* fcomp needs pop */
2391 case 0x08: /* flds */
2392 case 0x0a: /* fsts */
2393 case 0x0b: /* fstps */
2394 case 0x18: /* fildl */
2395 case 0x1a: /* fistl */
2396 case 0x1b: /* fistpl */
2397 case 0x28: /* fldl */
2398 case 0x2a: /* fstl */
2399 case 0x2b: /* fstpl */
2400 case 0x38: /* filds */
2401 case 0x3a: /* fists */
2402 case 0x3b: /* fistps */
2409 gen_op_flds_ST0_A0();
2412 gen_op_fildl_ST0_A0();
2415 gen_op_fldl_ST0_A0();
2419 gen_op_fild_ST0_A0();
2426 gen_op_fsts_ST0_A0();
2429 gen_op_fistl_ST0_A0();
2432 gen_op_fstl_ST0_A0();
2436 gen_op_fist_ST0_A0();
2444 case 0x0d: /* fldcw mem */
2447 case 0x0f: /* fnstcw mem */
2450 case 0x1d: /* fldt mem */
2452 gen_op_fldt_ST0_A0();
2454 case 0x1f: /* fstpt mem */
2455 gen_op_fstt_ST0_A0();
2458 case 0x2f: /* fnstsw mem */
2461 case 0x3c: /* fbld */
2463 gen_op_fbld_ST0_A0();
2465 case 0x3e: /* fbstp */
2466 gen_op_fbst_ST0_A0();
2469 case 0x3d: /* fildll */
2471 gen_op_fildll_ST0_A0();
2473 case 0x3f: /* fistpll */
2474 gen_op_fistll_ST0_A0();
2481 /* register float ops */
2485 case 0x08: /* fld sti */
2487 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2489 case 0x09: /* fxchg sti */
2490 gen_op_fxchg_ST0_STN(opreg
);
2492 case 0x0a: /* grp d9/2 */
2500 case 0x0c: /* grp d9/4 */
2510 gen_op_fcom_ST0_FT0();
2519 case 0x0d: /* grp d9/5 */
2528 gen_op_fldl2t_ST0();
2532 gen_op_fldl2e_ST0();
2540 gen_op_fldlg2_ST0();
2544 gen_op_fldln2_ST0();
2555 case 0x0e: /* grp d9/6 */
2566 case 3: /* fpatan */
2569 case 4: /* fxtract */
2572 case 5: /* fprem1 */
2575 case 6: /* fdecstp */
2579 case 7: /* fincstp */
2584 case 0x0f: /* grp d9/7 */
2589 case 1: /* fyl2xp1 */
2595 case 3: /* fsincos */
2598 case 5: /* fscale */
2601 case 4: /* frndint */
2613 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2614 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2615 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2621 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2625 gen_op_fmov_FT0_STN(opreg
);
2626 gen_op_fp_arith_ST0_FT0
[op1
]();
2630 case 0x02: /* fcom */
2631 gen_op_fmov_FT0_STN(opreg
);
2632 gen_op_fcom_ST0_FT0();
2634 case 0x03: /* fcomp */
2635 gen_op_fmov_FT0_STN(opreg
);
2636 gen_op_fcom_ST0_FT0();
2639 case 0x15: /* da/5 */
2641 case 1: /* fucompp */
2642 gen_op_fmov_FT0_STN(1);
2643 gen_op_fucom_ST0_FT0();
2656 case 3: /* fninit */
2663 case 0x2a: /* fst sti */
2664 gen_op_fmov_STN_ST0(opreg
);
2666 case 0x2b: /* fstp sti */
2667 gen_op_fmov_STN_ST0(opreg
);
2670 case 0x2c: /* fucom st(i) */
2671 gen_op_fmov_FT0_STN(opreg
);
2672 gen_op_fucom_ST0_FT0();
2674 case 0x2d: /* fucomp st(i) */
2675 gen_op_fmov_FT0_STN(opreg
);
2676 gen_op_fucom_ST0_FT0();
2679 case 0x33: /* de/3 */
2681 case 1: /* fcompp */
2682 gen_op_fmov_FT0_STN(1);
2683 gen_op_fcom_ST0_FT0();
2691 case 0x3c: /* df/4 */
2694 gen_op_fnstsw_EAX();
2705 /************************/
2708 case 0xa4: /* movsS */
2713 ot
= dflag
? OT_LONG
: OT_WORD
;
2715 if (prefixes
& PREFIX_REPZ
) {
2716 gen_string_ds(s
, ot
, gen_op_movs
+ 9);
2718 gen_string_ds(s
, ot
, gen_op_movs
);
2722 case 0xaa: /* stosS */
2727 ot
= dflag
? OT_LONG
: OT_WORD
;
2729 if (prefixes
& PREFIX_REPZ
) {
2730 gen_string_es(s
, ot
, gen_op_stos
+ 9);
2732 gen_string_es(s
, ot
, gen_op_stos
);
2735 case 0xac: /* lodsS */
2740 ot
= dflag
? OT_LONG
: OT_WORD
;
2741 if (prefixes
& PREFIX_REPZ
) {
2742 gen_string_ds(s
, ot
, gen_op_lods
+ 9);
2744 gen_string_ds(s
, ot
, gen_op_lods
);
2747 case 0xae: /* scasS */
2752 ot
= dflag
? OT_LONG
: OT_WORD
;
2753 if (prefixes
& PREFIX_REPNZ
) {
2754 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2755 gen_op_set_cc_op(s
->cc_op
);
2756 gen_string_es(s
, ot
, gen_op_scas
+ 9 * 2);
2757 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2758 } else if (prefixes
& PREFIX_REPZ
) {
2759 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2760 gen_op_set_cc_op(s
->cc_op
);
2761 gen_string_es(s
, ot
, gen_op_scas
+ 9);
2762 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2764 gen_string_es(s
, ot
, gen_op_scas
);
2765 s
->cc_op
= CC_OP_SUBB
+ ot
;
2769 case 0xa6: /* cmpsS */
2774 ot
= dflag
? OT_LONG
: OT_WORD
;
2775 if (prefixes
& PREFIX_REPNZ
) {
2776 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2777 gen_op_set_cc_op(s
->cc_op
);
2778 gen_string_ds(s
, ot
, gen_op_cmps
+ 9 * 2);
2779 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2780 } else if (prefixes
& PREFIX_REPZ
) {
2781 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2782 gen_op_set_cc_op(s
->cc_op
);
2783 gen_string_ds(s
, ot
, gen_op_cmps
+ 9);
2784 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2786 gen_string_ds(s
, ot
, gen_op_cmps
);
2787 s
->cc_op
= CC_OP_SUBB
+ ot
;
2790 case 0x6c: /* insS */
2792 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2793 /* NOTE: even for (E)CX = 0 the exception is raised */
2794 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2799 ot
= dflag
? OT_LONG
: OT_WORD
;
2800 if (prefixes
& PREFIX_REPZ
) {
2801 gen_string_es(s
, ot
, gen_op_ins
+ 9);
2803 gen_string_es(s
, ot
, gen_op_ins
);
2807 case 0x6e: /* outsS */
2809 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2810 /* NOTE: even for (E)CX = 0 the exception is raised */
2811 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2816 ot
= dflag
? OT_LONG
: OT_WORD
;
2817 if (prefixes
& PREFIX_REPZ
) {
2818 gen_string_ds(s
, ot
, gen_op_outs
+ 9);
2820 gen_string_ds(s
, ot
, gen_op_outs
);
2825 /************************/
2829 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2830 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2835 ot
= dflag
? OT_LONG
: OT_WORD
;
2836 val
= ldub(s
->pc
++);
2837 gen_op_movl_T0_im(val
);
2839 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2844 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2845 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2850 ot
= dflag
? OT_LONG
: OT_WORD
;
2851 val
= ldub(s
->pc
++);
2852 gen_op_movl_T0_im(val
);
2853 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2859 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2860 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2865 ot
= dflag
? OT_LONG
: OT_WORD
;
2866 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2868 gen_op_mov_reg_T1
[ot
][R_EAX
]();
2873 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2874 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2879 ot
= dflag
? OT_LONG
: OT_WORD
;
2880 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2881 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2886 /************************/
2888 case 0xc2: /* ret im */
2893 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2895 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2897 gen_op_andl_T0_ffff();
2901 case 0xc3: /* ret */
2905 gen_op_andl_T0_ffff();
2909 case 0xca: /* lret im */
2910 /* XXX: not restartable */
2916 gen_op_andl_T0_ffff();
2921 gen_movl_seg_T0(s
, R_CS
);
2923 /* add stack offset */
2925 gen_op_addl_ESP_im(val
);
2927 gen_op_addw_ESP_im(val
);
2930 case 0xcb: /* lret */
2931 /* XXX: not restartable */
2935 gen_op_andl_T0_ffff();
2940 gen_movl_seg_T0(s
, R_CS
);
2944 case 0xcf: /* iret */
2945 if (s
->vm86
&& s
->iopl
!= 3) {
2946 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2948 /* XXX: not restartable */
2952 gen_op_andl_T0_ffff();
2957 gen_movl_seg_T0(s
, R_CS
);
2962 gen_op_movl_eflags_T0();
2964 gen_op_movw_eflags_T0();
2967 s
->cc_op
= CC_OP_EFLAGS
;
2971 case 0xe8: /* call im */
2973 unsigned int next_eip
;
2974 ot
= dflag
? OT_LONG
: OT_WORD
;
2975 val
= insn_get(s
, ot
);
2976 next_eip
= s
->pc
- s
->cs_base
;
2980 gen_op_movl_T0_im(next_eip
);
2985 case 0x9a: /* lcall im */
2987 unsigned int selector
, offset
;
2989 ot
= dflag
? OT_LONG
: OT_WORD
;
2990 offset
= insn_get(s
, ot
);
2991 selector
= insn_get(s
, OT_WORD
);
2993 /* push return segment + offset */
2994 gen_op_movl_T0_seg(R_CS
);
2996 next_eip
= s
->pc
- s
->cs_base
;
2997 gen_op_movl_T0_im(next_eip
);
3000 /* change cs and pc */
3001 gen_op_movl_T0_im(selector
);
3002 gen_movl_seg_T0(s
, R_CS
);
3003 gen_op_jmp_im((unsigned long)offset
);
3007 case 0xe9: /* jmp */
3008 ot
= dflag
? OT_LONG
: OT_WORD
;
3009 val
= insn_get(s
, ot
);
3010 val
+= s
->pc
- s
->cs_base
;
3015 case 0xea: /* ljmp im */
3017 unsigned int selector
, offset
;
3019 ot
= dflag
? OT_LONG
: OT_WORD
;
3020 offset
= insn_get(s
, ot
);
3021 selector
= insn_get(s
, OT_WORD
);
3023 /* change cs and pc */
3024 gen_op_movl_T0_im(selector
);
3025 gen_movl_seg_T0(s
, R_CS
);
3026 gen_op_jmp_im((unsigned long)offset
);
3030 case 0xeb: /* jmp Jb */
3031 val
= (int8_t)insn_get(s
, OT_BYTE
);
3032 val
+= s
->pc
- s
->cs_base
;
3037 case 0x70 ... 0x7f: /* jcc Jb */
3038 val
= (int8_t)insn_get(s
, OT_BYTE
);
3040 case 0x180 ... 0x18f: /* jcc Jv */
3042 val
= insn_get(s
, OT_LONG
);
3044 val
= (int16_t)insn_get(s
, OT_WORD
);
3047 next_eip
= s
->pc
- s
->cs_base
;
3051 gen_jcc(s
, b
, val
, next_eip
);
3054 case 0x190 ... 0x19f: /* setcc Gv */
3055 modrm
= ldub(s
->pc
++);
3057 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
3059 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3060 ot
= dflag
? OT_LONG
: OT_WORD
;
3061 modrm
= ldub(s
->pc
++);
3062 reg
= (modrm
>> 3) & 7;
3063 mod
= (modrm
>> 6) & 3;
3066 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3067 gen_op_ld_T1_A0
[ot
]();
3070 gen_op_mov_TN_reg
[ot
][1][rm
]();
3072 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
3075 /************************/
3077 case 0x9c: /* pushf */
3078 if (s
->vm86
&& s
->iopl
!= 3) {
3079 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3081 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3082 gen_op_set_cc_op(s
->cc_op
);
3083 gen_op_movl_T0_eflags();
3087 case 0x9d: /* popf */
3088 if (s
->vm86
&& s
->iopl
!= 3) {
3089 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3093 gen_op_movl_eflags_T0();
3095 gen_op_movw_eflags_T0();
3098 s
->cc_op
= CC_OP_EFLAGS
;
3099 s
->is_jmp
= 2; /* abort translation because TF flag may change */
3102 case 0x9e: /* sahf */
3103 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
3104 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3105 gen_op_set_cc_op(s
->cc_op
);
3106 gen_op_movb_eflags_T0();
3107 s
->cc_op
= CC_OP_EFLAGS
;
3109 case 0x9f: /* lahf */
3110 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3111 gen_op_set_cc_op(s
->cc_op
);
3112 gen_op_movl_T0_eflags();
3113 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
3115 case 0xf5: /* cmc */
3116 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3117 gen_op_set_cc_op(s
->cc_op
);
3119 s
->cc_op
= CC_OP_EFLAGS
;
3121 case 0xf8: /* clc */
3122 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3123 gen_op_set_cc_op(s
->cc_op
);
3125 s
->cc_op
= CC_OP_EFLAGS
;
3127 case 0xf9: /* stc */
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 0xfc: /* cld */
3136 case 0xfd: /* std */
3140 /************************/
3141 /* bit operations */
3142 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3143 ot
= dflag
? OT_LONG
: OT_WORD
;
3144 modrm
= ldub(s
->pc
++);
3145 op
= (modrm
>> 3) & 7;
3146 mod
= (modrm
>> 6) & 3;
3149 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3150 gen_op_ld_T0_A0
[ot
]();
3152 gen_op_mov_TN_reg
[ot
][0][rm
]();
3155 val
= ldub(s
->pc
++);
3156 gen_op_movl_T1_im(val
);
3160 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3161 s
->cc_op
= CC_OP_SARB
+ ot
;
3164 gen_op_st_T0_A0
[ot
]();
3166 gen_op_mov_reg_T0
[ot
][rm
]();
3169 case 0x1a3: /* bt Gv, Ev */
3172 case 0x1ab: /* bts */
3175 case 0x1b3: /* btr */
3178 case 0x1bb: /* btc */
3181 ot
= dflag
? OT_LONG
: OT_WORD
;
3182 modrm
= ldub(s
->pc
++);
3183 reg
= (modrm
>> 3) & 7;
3184 mod
= (modrm
>> 6) & 3;
3186 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3188 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3189 /* specific case: we need to add a displacement */
3191 gen_op_add_bitw_A0_T1();
3193 gen_op_add_bitl_A0_T1();
3194 gen_op_ld_T0_A0
[ot
]();
3196 gen_op_mov_TN_reg
[ot
][0][rm
]();
3198 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3199 s
->cc_op
= CC_OP_SARB
+ ot
;
3202 gen_op_st_T0_A0
[ot
]();
3204 gen_op_mov_reg_T0
[ot
][rm
]();
3207 case 0x1bc: /* bsf */
3208 case 0x1bd: /* bsr */
3209 ot
= dflag
? OT_LONG
: OT_WORD
;
3210 modrm
= ldub(s
->pc
++);
3211 reg
= (modrm
>> 3) & 7;
3212 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3213 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3214 /* NOTE: we always write back the result. Intel doc says it is
3215 undefined if T0 == 0 */
3216 gen_op_mov_reg_T0
[ot
][reg
]();
3217 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3219 /************************/
3221 case 0x27: /* daa */
3222 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3223 gen_op_set_cc_op(s
->cc_op
);
3225 s
->cc_op
= CC_OP_EFLAGS
;
3227 case 0x2f: /* das */
3228 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3229 gen_op_set_cc_op(s
->cc_op
);
3231 s
->cc_op
= CC_OP_EFLAGS
;
3233 case 0x37: /* aaa */
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 0x3f: /* aas */
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 0xd4: /* aam */
3246 val
= ldub(s
->pc
++);
3248 s
->cc_op
= CC_OP_LOGICB
;
3250 case 0xd5: /* aad */
3251 val
= ldub(s
->pc
++);
3253 s
->cc_op
= CC_OP_LOGICB
;
3255 /************************/
3257 case 0x90: /* nop */
3259 case 0xcc: /* int3 */
3260 gen_exception(s
, EXCP03_INT3
, s
->pc
- s
->cs_base
);
3262 case 0xcd: /* int N */
3263 val
= ldub(s
->pc
++);
3264 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3265 gen_op_set_cc_op(s
->cc_op
);
3266 gen_op_int_im(val
, pc_start
- s
->cs_base
);
3269 case 0xce: /* into */
3270 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3271 gen_op_set_cc_op(s
->cc_op
);
3272 gen_op_into(s
->pc
- s
->cs_base
);
3274 case 0xfa: /* cli */
3276 if (s
->cpl
<= s
->iopl
) {
3279 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3285 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3289 case 0xfb: /* sti */
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 0x62: /* bound */
3305 ot
= dflag
? OT_LONG
: OT_WORD
;
3306 modrm
= ldub(s
->pc
++);
3307 reg
= (modrm
>> 3) & 7;
3308 mod
= (modrm
>> 6) & 3;
3311 gen_op_mov_reg_T0
[ot
][reg
]();
3312 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3318 case 0x1c8 ... 0x1cf: /* bswap reg */
3320 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3322 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3324 case 0xd6: /* salc */
3325 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3326 gen_op_set_cc_op(s
->cc_op
);
3329 case 0xe0: /* loopnz */
3330 case 0xe1: /* loopz */
3331 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3332 gen_op_set_cc_op(s
->cc_op
);
3334 case 0xe2: /* loop */
3335 case 0xe3: /* jecxz */
3336 val
= (int8_t)insn_get(s
, OT_BYTE
);
3337 next_eip
= s
->pc
- s
->cs_base
;
3341 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3344 case 0x131: /* rdtsc */
3347 case 0x1a2: /* cpuid */
3350 case 0xf4: /* hlt */
3351 /* XXX: if cpl == 0, then should do something else */
3352 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3354 case 0x102: /* lar */
3355 case 0x103: /* lsl */
3358 ot
= dflag
? OT_LONG
: OT_WORD
;
3359 modrm
= ldub(s
->pc
++);
3360 reg
= (modrm
>> 3) & 7;
3361 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3362 gen_op_mov_TN_reg
[ot
][1][reg
]();
3363 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3364 gen_op_set_cc_op(s
->cc_op
);
3369 s
->cc_op
= CC_OP_EFLAGS
;
3370 gen_op_mov_reg_T1
[ot
][reg
]();
3375 /* lock generation */
3376 if (s
->prefix
& PREFIX_LOCK
)
3380 /* XXX: ensure that no lock was generated */
3384 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3385 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3387 /* flags read by an operation */
3388 static uint16_t opc_read_flags
[NB_OPS
] = {
3389 [INDEX_op_aas
] = CC_A
,
3390 [INDEX_op_aaa
] = CC_A
,
3391 [INDEX_op_das
] = CC_A
| CC_C
,
3392 [INDEX_op_daa
] = CC_A
| CC_C
,
3394 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3395 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3396 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3397 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3398 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3399 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3401 /* subtle: due to the incl/decl implementation, C is used */
3402 [INDEX_op_incl_T0_cc
] = CC_C
,
3403 [INDEX_op_decl_T0_cc
] = CC_C
,
3405 [INDEX_op_into
] = CC_O
,
3407 [INDEX_op_jb_subb
] = CC_C
,
3408 [INDEX_op_jb_subw
] = CC_C
,
3409 [INDEX_op_jb_subl
] = CC_C
,
3411 [INDEX_op_jz_subb
] = CC_Z
,
3412 [INDEX_op_jz_subw
] = CC_Z
,
3413 [INDEX_op_jz_subl
] = CC_Z
,
3415 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3416 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3417 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3419 [INDEX_op_js_subb
] = CC_S
,
3420 [INDEX_op_js_subw
] = CC_S
,
3421 [INDEX_op_js_subl
] = CC_S
,
3423 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3424 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3425 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3427 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3428 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3429 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3431 [INDEX_op_loopnzw
] = CC_Z
,
3432 [INDEX_op_loopnzl
] = CC_Z
,
3433 [INDEX_op_loopzw
] = CC_Z
,
3434 [INDEX_op_loopzl
] = CC_Z
,
3436 [INDEX_op_seto_T0_cc
] = CC_O
,
3437 [INDEX_op_setb_T0_cc
] = CC_C
,
3438 [INDEX_op_setz_T0_cc
] = CC_Z
,
3439 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3440 [INDEX_op_sets_T0_cc
] = CC_S
,
3441 [INDEX_op_setp_T0_cc
] = CC_P
,
3442 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3443 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3445 [INDEX_op_setb_T0_subb
] = CC_C
,
3446 [INDEX_op_setb_T0_subw
] = CC_C
,
3447 [INDEX_op_setb_T0_subl
] = CC_C
,
3449 [INDEX_op_setz_T0_subb
] = CC_Z
,
3450 [INDEX_op_setz_T0_subw
] = CC_Z
,
3451 [INDEX_op_setz_T0_subl
] = CC_Z
,
3453 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3454 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3455 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3457 [INDEX_op_sets_T0_subb
] = CC_S
,
3458 [INDEX_op_sets_T0_subw
] = CC_S
,
3459 [INDEX_op_sets_T0_subl
] = CC_S
,
3461 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3462 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3463 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3465 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3466 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3467 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3469 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3470 [INDEX_op_cmc
] = CC_C
,
3471 [INDEX_op_salc
] = CC_C
,
3473 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3474 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3475 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3476 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3477 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3478 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3481 /* flags written by an operation */
3482 static uint16_t opc_write_flags
[NB_OPS
] = {
3483 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3484 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3485 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3486 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3487 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3488 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3489 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3490 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3491 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3492 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3493 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3494 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3495 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3496 /* subtle: due to the incl/decl implementation, C is used */
3497 [INDEX_op_incl_T0_cc
] = CC_OSZAPC
,
3498 [INDEX_op_decl_T0_cc
] = CC_OSZAPC
,
3499 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3501 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3502 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3503 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3504 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3505 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3506 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3507 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3508 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3511 [INDEX_op_aam
] = CC_OSZAPC
,
3512 [INDEX_op_aad
] = CC_OSZAPC
,
3513 [INDEX_op_aas
] = CC_OSZAPC
,
3514 [INDEX_op_aaa
] = CC_OSZAPC
,
3515 [INDEX_op_das
] = CC_OSZAPC
,
3516 [INDEX_op_daa
] = CC_OSZAPC
,
3518 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3519 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
3520 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3521 [INDEX_op_clc
] = CC_C
,
3522 [INDEX_op_stc
] = CC_C
,
3523 [INDEX_op_cmc
] = CC_C
,
3525 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3526 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3527 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3528 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3529 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3530 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3532 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3533 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3534 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3535 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3536 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3537 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3539 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3540 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3541 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3543 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3544 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3545 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3547 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3548 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3549 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3551 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3552 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3553 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3554 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3556 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3557 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3558 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3559 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3561 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3562 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3563 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3564 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3565 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3566 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3567 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3568 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3570 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3571 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3572 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3573 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3576 #define STRINGOP(x) \
3577 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3578 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3579 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3580 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3581 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3582 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3583 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3584 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3585 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3589 STRINGOP(repnz_scas
)
3592 STRINGOP(repnz_cmps
)
3594 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
3595 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3596 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3598 [INDEX_op_cmpxchg8b
] = CC_Z
,
3599 [INDEX_op_lar
] = CC_Z
,
3600 [INDEX_op_lsl
] = CC_Z
,
3603 /* simpler form of an operation if no flags need to be generated */
3604 static uint16_t opc_simpler
[NB_OPS
] = {
3605 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3606 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3607 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3608 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3609 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3610 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3611 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3612 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3614 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3615 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3616 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3618 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3619 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3620 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3622 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3623 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3624 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3626 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3627 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3628 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3630 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3631 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3632 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3635 static void optimize_flags_init(void)
3638 /* put default values in arrays */
3639 for(i
= 0; i
< NB_OPS
; i
++) {
3640 if (opc_simpler
[i
] == 0)
3645 /* CPU flags computation optimization: we move backward thru the
3646 generated code to see which flags are needed. The operation is
3647 modified if suitable */
3648 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3651 int live_flags
, write_flags
, op
;
3653 opc_ptr
= opc_buf
+ opc_buf_len
;
3654 /* live_flags contains the flags needed by the next instructions
3655 in the code. At the end of the bloc, we consider that all the
3657 live_flags
= CC_OSZAPC
;
3658 while (opc_ptr
> opc_buf
) {
3660 /* if none of the flags written by the instruction is used,
3661 then we can try to find a simpler instruction */
3662 write_flags
= opc_write_flags
[op
];
3663 if ((live_flags
& write_flags
) == 0) {
3664 *opc_ptr
= opc_simpler
[op
];
3666 /* compute the live flags before the instruction */
3667 live_flags
&= ~write_flags
;
3668 live_flags
|= opc_read_flags
[op
];
3674 static const char *op_str
[] = {
3675 #define DEF(s, n) #s,
3676 #include "opc-i386.h"
3680 static uint8_t op_nb_args
[] = {
3681 #define DEF(s, n) n,
3682 #include "opc-i386.h"
3686 static void dump_ops(const uint16_t *opc_buf
, const uint32_t *opparam_buf
)
3688 const uint16_t *opc_ptr
;
3689 const uint32_t *opparam_ptr
;
3693 opparam_ptr
= opparam_buf
;
3697 fprintf(logfile
, "0x%04x: %s",
3698 (int)(opc_ptr
- opc_buf
- 1), op_str
[c
]);
3699 for(i
= 0; i
< n
; i
++) {
3700 fprintf(logfile
, " 0x%x", opparam_ptr
[i
]);
3702 fprintf(logfile
, "\n");
3703 if (c
== INDEX_op_end
)
3711 /* XXX: make this buffer thread safe */
3712 /* XXX: make safe guess about sizes */
3713 #define MAX_OP_PER_INSTR 32
3714 #define OPC_BUF_SIZE 512
3715 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3717 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3719 static uint16_t gen_opc_buf
[OPC_BUF_SIZE
];
3720 static uint32_t gen_opparam_buf
[OPPARAM_BUF_SIZE
];
3722 /* return non zero if the very first instruction is invalid so that
3723 the virtual CPU can trigger an exception.
3725 '*code_size_ptr' contains the target code size including the
3726 instruction which triggered an exception, except in case of invalid
3727 illegal opcode. It must never exceed one target page.
3729 '*gen_code_size_ptr' contains the size of the generated code (host
3732 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
3733 int *gen_code_size_ptr
,
3734 uint8_t *pc_start
, uint8_t *cs_base
, int flags
,
3735 int *code_size_ptr
, TranslationBlock
*tb
)
3737 DisasContext dc1
, *dc
= &dc1
;
3739 uint16_t *gen_opc_end
;
3743 /* generate intermediate code */
3745 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3746 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3747 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3748 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3749 dc
->vm86
= (flags
>> GEN_FLAG_VM_SHIFT
) & 1;
3750 dc
->cpl
= (flags
>> GEN_FLAG_CPL_SHIFT
) & 3;
3751 dc
->iopl
= (flags
>> GEN_FLAG_IOPL_SHIFT
) & 3;
3752 dc
->tf
= (flags
>> GEN_FLAG_TF_SHIFT
) & 1;
3753 dc
->cc_op
= CC_OP_DYNAMIC
;
3754 dc
->cs_base
= cs_base
;
3757 gen_opc_ptr
= gen_opc_buf
;
3758 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3759 gen_opparam_ptr
= gen_opparam_buf
;
3764 ret
= disas_insn(dc
, pc_ptr
);
3766 /* we trigger an illegal instruction operation only if it
3767 is the first instruction. Otherwise, we simply stop
3768 generating the code just before it */
3769 if (pc_ptr
== pc_start
)
3774 pc_ptr
= (void *)ret
;
3775 /* if single step mode, we generate only one instruction and
3776 generate an exception */
3779 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
3780 (pc_ptr
- pc_start
) < (TARGET_PAGE_SIZE
- 32));
3781 /* we must store the eflags state if it is not already done */
3782 if (dc
->is_jmp
!= 3) {
3783 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3784 gen_op_set_cc_op(dc
->cc_op
);
3785 if (dc
->is_jmp
!= 1) {
3786 /* we add an additionnal jmp to update the simulated PC */
3787 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3791 gen_op_raise_exception(EXCP01_SSTP
);
3793 if (dc
->is_jmp
!= 3) {
3794 /* indicate that the hash table must be used to find the next TB */
3798 *gen_opc_ptr
= INDEX_op_end
;
3802 fprintf(logfile
, "----------------\n");
3803 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
3804 disas(logfile
, pc_start
, pc_ptr
- pc_start
,
3805 dc
->code32
? DISAS_I386_I386
: DISAS_I386_I8086
);
3806 fprintf(logfile
, "\n");
3808 fprintf(logfile
, "OP:\n");
3809 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3810 fprintf(logfile
, "\n");
3814 /* optimize flag computations */
3815 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3819 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3820 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3821 fprintf(logfile
, "\n");
3825 /* generate machine code */
3826 tb
->tb_next_offset
[0] = 0xffff;
3827 tb
->tb_next_offset
[1] = 0xffff;
3828 gen_code_size
= dyngen_code(gen_code_buf
, tb
->tb_next_offset
,
3829 #ifdef USE_DIRECT_JUMP
3834 gen_opc_buf
, gen_opparam_buf
);
3835 flush_icache_range((unsigned long)gen_code_buf
, (unsigned long)(gen_code_buf
+ gen_code_size
));
3837 *gen_code_size_ptr
= gen_code_size
;
3838 *code_size_ptr
= pc_ptr
- pc_start
;
3841 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
3842 disas(logfile
, gen_code_buf
, *gen_code_size_ptr
, DISAS_TARGET
);
3843 fprintf(logfile
, "\n");
3850 CPUX86State
*cpu_x86_init(void)
3856 cpu_x86_tblocks_init();
3858 env
= malloc(sizeof(CPUX86State
));
3861 memset(env
, 0, sizeof(CPUX86State
));
3862 /* basic FPU init */
3863 for(i
= 0;i
< 8; i
++)
3866 /* flags setup : we activate the IRQs by default as in user mode */
3867 env
->eflags
= 0x2 | IF_MASK
;
3869 /* init various static tables */
3872 optimize_flags_init();
3878 void cpu_x86_close(CPUX86State
*env
)
3883 static const char *cc_op_str
[] = {
3916 void cpu_x86_dump_state(CPUX86State
*env
, FILE *f
, int flags
)
3919 char cc_op_name
[32];
3921 eflags
= env
->eflags
;
3922 fprintf(f
, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3923 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3924 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3925 env
->regs
[R_EAX
], env
->regs
[R_EBX
], env
->regs
[R_ECX
], env
->regs
[R_EDX
],
3926 env
->regs
[R_ESI
], env
->regs
[R_EDI
], env
->regs
[R_EBP
], env
->regs
[R_ESP
],
3928 eflags
& DF_MASK
? 'D' : '-',
3929 eflags
& CC_O
? 'O' : '-',
3930 eflags
& CC_S
? 'S' : '-',
3931 eflags
& CC_Z
? 'Z' : '-',
3932 eflags
& CC_A
? 'A' : '-',
3933 eflags
& CC_P
? 'P' : '-',
3934 eflags
& CC_C
? 'C' : '-');
3935 fprintf(f
, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3942 if (flags
& X86_DUMP_CCOP
) {
3943 if ((unsigned)env
->cc_op
< CC_OP_NB
)
3944 strcpy(cc_op_name
, cc_op_str
[env
->cc_op
]);
3946 snprintf(cc_op_name
, sizeof(cc_op_name
), "[%d]", env
->cc_op
);
3947 fprintf(f
, "CCS=%08x CCD=%08x CCO=%-8s\n",
3948 env
->cc_src
, env
->cc_dst
, cc_op_name
);
3950 if (flags
& X86_DUMP_FPU
) {
3951 fprintf(f
, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
3952 (double)env
->fpregs
[0],
3953 (double)env
->fpregs
[1],
3954 (double)env
->fpregs
[2],
3955 (double)env
->fpregs
[3]);
3956 fprintf(f
, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
3957 (double)env
->fpregs
[4],
3958 (double)env
->fpregs
[5],
3959 (double)env
->fpregs
[7],
3960 (double)env
->fpregs
[8]);