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
35 /* XXX: move that elsewhere */
36 static uint16_t *gen_opc_ptr
;
37 static uint32_t *gen_opparam_ptr
;
38 int __op_param1
, __op_param2
, __op_param3
;
41 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
47 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
53 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
60 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
62 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
66 p
= start
& ~(MIN_CACHE_LINE_SIZE
- 1);
67 stop
= (stop
+ MIN_CACHE_LINE_SIZE
- 1) & ~(MIN_CACHE_LINE_SIZE
- 1);
69 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
70 asm ("dcbst 0,%0;" : : "r"(p
) : "memory");
73 for (p
= start
; p
< stop
; p
+= MIN_CACHE_LINE_SIZE
) {
74 asm ("icbi 0,%0; sync;" : : "r"(p
) : "memory");
82 static inline void flush_icache_range(unsigned long start
, unsigned long stop
)
90 static void inline flush_icache_range(unsigned long start
, unsigned long stop
)
94 p
= start
& ~(8UL - 1UL);
95 stop
= (stop
+ (8UL - 1UL)) & ~(8UL - 1UL);
97 for (; p
< stop
; p
+= 8)
98 __asm__
__volatile__("flush\t%0" : : "r" (p
));
103 extern FILE *logfile
;
106 #define PREFIX_REPZ 0x01
107 #define PREFIX_REPNZ 0x02
108 #define PREFIX_LOCK 0x04
109 #define PREFIX_DATA 0x08
110 #define PREFIX_ADR 0x10
111 #define PREFIX_FWAIT 0x20
113 typedef struct DisasContext
{
114 /* current insn context */
115 int override
; /* -1 if no override */
118 uint8_t *pc
; /* pc = eip + cs_base */
119 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
120 static state change (stop translation) */
121 /* current block context */
122 uint8_t *cs_base
; /* base of CS segment */
123 int code32
; /* 32 bit code segment */
124 int ss32
; /* 32 bit stack segment */
125 int cc_op
; /* current CC operation */
126 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
127 int f_st
; /* currently unused */
128 int vm86
; /* vm86 mode */
131 int tf
; /* TF cpu flag */
134 /* i386 arith/logic operations */
154 OP_SHL1
, /* undocumented */
159 #define DEF(s, n) INDEX_op_ ## s,
160 #include "opc-i386.h"
176 /* I386 int registers */
177 OR_EAX
, /* MUST be even numbered */
185 OR_TMP0
, /* temporary operand register */
187 OR_A0
, /* temporary register used when doing address evaluation */
188 OR_ZERO
, /* fixed zero register */
192 typedef void (GenOpFunc
)(void);
193 typedef void (GenOpFunc1
)(long);
194 typedef void (GenOpFunc2
)(long, long);
196 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
229 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
262 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
285 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
355 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
366 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
378 gen_op_addl_A0_EAX_s1
,
379 gen_op_addl_A0_ECX_s1
,
380 gen_op_addl_A0_EDX_s1
,
381 gen_op_addl_A0_EBX_s1
,
382 gen_op_addl_A0_ESP_s1
,
383 gen_op_addl_A0_EBP_s1
,
384 gen_op_addl_A0_ESI_s1
,
385 gen_op_addl_A0_EDI_s1
,
388 gen_op_addl_A0_EAX_s2
,
389 gen_op_addl_A0_ECX_s2
,
390 gen_op_addl_A0_EDX_s2
,
391 gen_op_addl_A0_EBX_s2
,
392 gen_op_addl_A0_ESP_s2
,
393 gen_op_addl_A0_EBP_s2
,
394 gen_op_addl_A0_ESI_s2
,
395 gen_op_addl_A0_EDI_s2
,
398 gen_op_addl_A0_EAX_s3
,
399 gen_op_addl_A0_ECX_s3
,
400 gen_op_addl_A0_EDX_s3
,
401 gen_op_addl_A0_EBX_s3
,
402 gen_op_addl_A0_ESP_s3
,
403 gen_op_addl_A0_EBP_s3
,
404 gen_op_addl_A0_ESI_s3
,
405 gen_op_addl_A0_EDI_s3
,
409 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
411 gen_op_cmovw_EAX_T1_T0
,
412 gen_op_cmovw_ECX_T1_T0
,
413 gen_op_cmovw_EDX_T1_T0
,
414 gen_op_cmovw_EBX_T1_T0
,
415 gen_op_cmovw_ESP_T1_T0
,
416 gen_op_cmovw_EBP_T1_T0
,
417 gen_op_cmovw_ESI_T1_T0
,
418 gen_op_cmovw_EDI_T1_T0
,
421 gen_op_cmovl_EAX_T1_T0
,
422 gen_op_cmovl_ECX_T1_T0
,
423 gen_op_cmovl_EDX_T1_T0
,
424 gen_op_cmovl_EBX_T1_T0
,
425 gen_op_cmovl_ESP_T1_T0
,
426 gen_op_cmovl_EBP_T1_T0
,
427 gen_op_cmovl_ESI_T1_T0
,
428 gen_op_cmovl_EDI_T1_T0
,
432 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
433 gen_op_addl_T0_T1_cc
,
437 gen_op_andl_T0_T1_cc
,
438 gen_op_subl_T0_T1_cc
,
439 gen_op_xorl_T0_T1_cc
,
440 gen_op_cmpl_T0_T1_cc
,
443 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
445 gen_op_adcb_T0_T1_cc
,
446 gen_op_sbbb_T0_T1_cc
,
449 gen_op_adcw_T0_T1_cc
,
450 gen_op_sbbw_T0_T1_cc
,
453 gen_op_adcl_T0_T1_cc
,
454 gen_op_sbbl_T0_T1_cc
,
458 static const int cc_op_arithb
[8] = {
469 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
470 gen_op_cmpxchgb_T0_T1_EAX_cc
,
471 gen_op_cmpxchgw_T0_T1_EAX_cc
,
472 gen_op_cmpxchgl_T0_T1_EAX_cc
,
475 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
477 gen_op_rolb_T0_T1_cc
,
478 gen_op_rorb_T0_T1_cc
,
479 gen_op_rclb_T0_T1_cc
,
480 gen_op_rcrb_T0_T1_cc
,
481 gen_op_shlb_T0_T1_cc
,
482 gen_op_shrb_T0_T1_cc
,
483 gen_op_shlb_T0_T1_cc
,
484 gen_op_sarb_T0_T1_cc
,
487 gen_op_rolw_T0_T1_cc
,
488 gen_op_rorw_T0_T1_cc
,
489 gen_op_rclw_T0_T1_cc
,
490 gen_op_rcrw_T0_T1_cc
,
491 gen_op_shlw_T0_T1_cc
,
492 gen_op_shrw_T0_T1_cc
,
493 gen_op_shlw_T0_T1_cc
,
494 gen_op_sarw_T0_T1_cc
,
497 gen_op_roll_T0_T1_cc
,
498 gen_op_rorl_T0_T1_cc
,
499 gen_op_rcll_T0_T1_cc
,
500 gen_op_rcrl_T0_T1_cc
,
501 gen_op_shll_T0_T1_cc
,
502 gen_op_shrl_T0_T1_cc
,
503 gen_op_shll_T0_T1_cc
,
504 gen_op_sarl_T0_T1_cc
,
508 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
510 gen_op_shldw_T0_T1_im_cc
,
511 gen_op_shrdw_T0_T1_im_cc
,
514 gen_op_shldl_T0_T1_im_cc
,
515 gen_op_shrdl_T0_T1_im_cc
,
519 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
521 gen_op_shldw_T0_T1_ECX_cc
,
522 gen_op_shrdw_T0_T1_ECX_cc
,
525 gen_op_shldl_T0_T1_ECX_cc
,
526 gen_op_shrdl_T0_T1_ECX_cc
,
530 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
533 gen_op_btsw_T0_T1_cc
,
534 gen_op_btrw_T0_T1_cc
,
535 gen_op_btcw_T0_T1_cc
,
539 gen_op_btsl_T0_T1_cc
,
540 gen_op_btrl_T0_T1_cc
,
541 gen_op_btcl_T0_T1_cc
,
545 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
556 static GenOpFunc
*gen_op_lds_T0_A0
[3] = {
561 static GenOpFunc
*gen_op_ldu_T0_A0
[3] = {
566 /* sign does not matter */
567 static GenOpFunc
*gen_op_ld_T0_A0
[3] = {
573 static GenOpFunc
*gen_op_ld_T1_A0
[3] = {
579 static GenOpFunc
*gen_op_st_T0_A0
[3] = {
585 /* the _a32 and _a16 string operations use A0 as the base register. */
587 #define STRINGOP(x) \
588 gen_op_ ## x ## b_fast, \
589 gen_op_ ## x ## w_fast, \
590 gen_op_ ## x ## l_fast, \
591 gen_op_ ## x ## b_a32, \
592 gen_op_ ## x ## w_a32, \
593 gen_op_ ## x ## l_a32, \
594 gen_op_ ## x ## b_a16, \
595 gen_op_ ## x ## w_a16, \
596 gen_op_ ## x ## l_a16,
598 static GenOpFunc
*gen_op_movs
[9 * 2] = {
603 static GenOpFunc
*gen_op_stos
[9 * 2] = {
608 static GenOpFunc
*gen_op_lods
[9 * 2] = {
613 static GenOpFunc
*gen_op_scas
[9 * 3] = {
619 static GenOpFunc
*gen_op_cmps
[9 * 3] = {
625 static GenOpFunc
*gen_op_ins
[9 * 2] = {
631 static GenOpFunc
*gen_op_outs
[9 * 2] = {
637 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
641 override
= s
->override
;
644 if (s
->addseg
&& override
< 0)
647 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
655 gen_op_movl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
656 /* 16 address, always override */
662 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
679 static GenOpFunc
*gen_op_in
[3] = {
685 static GenOpFunc
*gen_op_out
[3] = {
702 static GenOpFunc2
*gen_jcc_slow
[8] = {
713 static GenOpFunc2
*gen_jcc_sub
[3][8] = {
745 static GenOpFunc2
*gen_op_loop
[2][4] = {
760 static GenOpFunc
*gen_setcc_slow
[8] = {
771 static GenOpFunc
*gen_setcc_sub
[3][8] = {
776 gen_op_setbe_T0_subb
,
780 gen_op_setle_T0_subb
,
786 gen_op_setbe_T0_subw
,
790 gen_op_setle_T0_subw
,
796 gen_op_setbe_T0_subl
,
800 gen_op_setle_T0_subl
,
804 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
810 gen_op_fsubr_ST0_FT0
,
812 gen_op_fdivr_ST0_FT0
,
815 /* NOTE the exception in "r" op ordering */
816 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
821 gen_op_fsubr_STN_ST0
,
823 gen_op_fdivr_STN_ST0
,
827 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
830 gen_op_mov_TN_reg
[ot
][0][d
]();
832 gen_op_mov_TN_reg
[ot
][1][s
]();
833 if (op
== OP_ADCL
|| op
== OP_SBBL
) {
834 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
835 gen_op_set_cc_op(s1
->cc_op
);
836 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
837 s1
->cc_op
= CC_OP_DYNAMIC
;
839 gen_op_arith_T0_T1_cc
[op
]();
840 s1
->cc_op
= cc_op_arithb
[op
] + ot
;
842 if (d
!= OR_TMP0
&& op
!= OP_CMPL
)
843 gen_op_mov_reg_T0
[ot
][d
]();
846 static void gen_opi(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
848 gen_op_movl_T1_im(c
);
849 gen_op(s1
, op
, ot
, d
, OR_TMP1
);
852 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
855 gen_op_mov_TN_reg
[ot
][0][d
]();
856 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
857 gen_op_set_cc_op(s1
->cc_op
);
860 s1
->cc_op
= CC_OP_INCB
+ ot
;
863 s1
->cc_op
= CC_OP_DECB
+ ot
;
866 gen_op_mov_reg_T0
[ot
][d
]();
869 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
872 gen_op_mov_TN_reg
[ot
][0][d
]();
874 gen_op_mov_TN_reg
[ot
][1][s
]();
875 /* for zero counts, flags are not updated, so must do it dynamically */
876 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
877 gen_op_set_cc_op(s1
->cc_op
);
879 gen_op_shift_T0_T1_cc
[ot
][op
]();
882 gen_op_mov_reg_T0
[ot
][d
]();
883 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
886 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
888 /* currently not optimized */
889 gen_op_movl_T1_im(c
);
890 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
893 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
900 int mod
, rm
, code
, override
, must_add_seg
;
902 override
= s
->override
;
903 must_add_seg
= s
->addseg
;
906 mod
= (modrm
>> 6) & 3;
918 code
= ldub(s
->pc
++);
919 scale
= (code
>> 6) & 3;
920 index
= (code
>> 3) & 7;
935 disp
= (int8_t)ldub(s
->pc
++);
945 gen_op_movl_A0_reg
[base
]();
947 gen_op_addl_A0_im(disp
);
949 gen_op_movl_A0_im(disp
);
951 if (havesib
&& (index
!= 4 || scale
!= 0)) {
952 gen_op_addl_A0_reg_sN
[scale
][index
]();
956 if (base
== R_EBP
|| base
== R_ESP
)
961 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
969 gen_op_movl_A0_im(disp
);
970 rm
= 0; /* avoid SS override */
977 disp
= (int8_t)ldub(s
->pc
++);
987 gen_op_movl_A0_reg
[R_EBX
]();
988 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
991 gen_op_movl_A0_reg
[R_EBX
]();
992 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
995 gen_op_movl_A0_reg
[R_EBP
]();
996 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
999 gen_op_movl_A0_reg
[R_EBP
]();
1000 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
1003 gen_op_movl_A0_reg
[R_ESI
]();
1006 gen_op_movl_A0_reg
[R_EDI
]();
1009 gen_op_movl_A0_reg
[R_EBP
]();
1013 gen_op_movl_A0_reg
[R_EBX
]();
1017 gen_op_addl_A0_im(disp
);
1018 gen_op_andl_A0_ffff();
1022 if (rm
== 2 || rm
== 3 || rm
== 6)
1027 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
1037 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1039 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1041 int mod
, rm
, opreg
, disp
;
1043 mod
= (modrm
>> 6) & 3;
1048 gen_op_mov_TN_reg
[ot
][0][reg
]();
1049 gen_op_mov_reg_T0
[ot
][rm
]();
1051 gen_op_mov_TN_reg
[ot
][0][rm
]();
1053 gen_op_mov_reg_T0
[ot
][reg
]();
1056 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1059 gen_op_mov_TN_reg
[ot
][0][reg
]();
1060 gen_op_st_T0_A0
[ot
]();
1062 gen_op_ld_T0_A0
[ot
]();
1064 gen_op_mov_reg_T0
[ot
][reg
]();
1069 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1091 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1097 jcc_op
= (b
>> 1) & 7;
1099 /* we optimize the cmp/jcc case */
1103 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1108 /* some jumps are easy to compute */
1135 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1138 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1146 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1147 gen_op_set_cc_op(s
->cc_op
);
1148 func
= gen_jcc_slow
[jcc_op
];
1152 func(val
, next_eip
);
1154 func(next_eip
, val
);
1158 static void gen_setcc(DisasContext
*s
, int b
)
1164 jcc_op
= (b
>> 1) & 7;
1166 /* we optimize the cmp/jcc case */
1170 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1175 /* some jumps are easy to compute */
1193 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1196 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1204 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1205 gen_op_set_cc_op(s
->cc_op
);
1206 func
= gen_setcc_slow
[jcc_op
];
1215 /* move T0 to seg_reg and compute if the CPU state may change */
1216 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
)
1218 gen_op_movl_seg_T0(seg_reg
);
1219 if (!s
->addseg
&& seg_reg
< R_FS
)
1220 s
->is_jmp
= 2; /* abort translation because the register may
1221 have a non zero base */
1224 /* generate a push. It depends on ss32, addseg and dflag */
1225 static void gen_push_T0(DisasContext
*s
)
1235 gen_op_pushl_ss32_T0();
1237 gen_op_pushw_ss32_T0();
1241 gen_op_pushl_ss16_T0();
1243 gen_op_pushw_ss16_T0();
1247 /* two step pop is necessary for precise exceptions */
1248 static void gen_pop_T0(DisasContext
*s
)
1258 gen_op_popl_ss32_T0();
1260 gen_op_popw_ss32_T0();
1264 gen_op_popl_ss16_T0();
1266 gen_op_popw_ss16_T0();
1270 static void gen_pop_update(DisasContext
*s
)
1274 gen_op_addl_ESP_4();
1276 gen_op_addl_ESP_2();
1279 gen_op_addw_ESP_4();
1281 gen_op_addw_ESP_2();
1285 /* NOTE: wrap around in 16 bit not fully handled */
1286 static void gen_pusha(DisasContext
*s
)
1289 gen_op_movl_A0_ESP();
1290 gen_op_addl_A0_im(-16 << s
->dflag
);
1292 gen_op_andl_A0_ffff();
1293 gen_op_movl_T1_A0();
1295 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1296 for(i
= 0;i
< 8; i
++) {
1297 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1298 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
]();
1299 gen_op_addl_A0_im(2 << s
->dflag
);
1301 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1304 /* NOTE: wrap around in 16 bit not fully handled */
1305 static void gen_popa(DisasContext
*s
)
1308 gen_op_movl_A0_ESP();
1310 gen_op_andl_A0_ffff();
1311 gen_op_movl_T1_A0();
1312 gen_op_addl_T1_im(16 << s
->dflag
);
1314 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1315 for(i
= 0;i
< 8; i
++) {
1316 /* ESP is not reloaded */
1318 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
]();
1319 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1321 gen_op_addl_A0_im(2 << s
->dflag
);
1323 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1326 /* NOTE: wrap around in 16 bit not fully handled */
1327 /* XXX: check this */
1328 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1330 int ot
, level1
, addend
, opsize
;
1332 ot
= s
->dflag
+ OT_WORD
;
1335 opsize
= 2 << s
->dflag
;
1337 gen_op_movl_A0_ESP();
1338 gen_op_addl_A0_im(-opsize
);
1340 gen_op_andl_A0_ffff();
1341 gen_op_movl_T1_A0();
1343 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[R_SS
].base
));
1345 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1346 gen_op_st_T0_A0
[ot
]();
1349 gen_op_addl_A0_im(-opsize
);
1350 gen_op_addl_T0_im(-opsize
);
1351 gen_op_st_T0_A0
[ot
]();
1353 gen_op_addl_A0_im(-opsize
);
1354 /* XXX: add st_T1_A0 ? */
1355 gen_op_movl_T0_T1();
1356 gen_op_st_T0_A0
[ot
]();
1358 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1359 addend
= -esp_addend
;
1361 addend
-= opsize
* (level1
+ 1);
1362 gen_op_addl_T1_im(addend
);
1363 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1366 static void gen_exception(DisasContext
*s
, int trapno
, unsigned int cur_eip
)
1368 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1369 gen_op_set_cc_op(s
->cc_op
);
1370 gen_op_jmp_im(cur_eip
);
1371 gen_op_raise_exception(trapno
);
1375 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1376 is set to true if the instruction sets the PC (last instruction of
1378 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1380 int b
, prefixes
, aflag
, dflag
;
1382 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1383 unsigned int next_eip
;
1393 /* check prefixes */
1396 prefixes
|= PREFIX_REPZ
;
1399 prefixes
|= PREFIX_REPNZ
;
1402 prefixes
|= PREFIX_LOCK
;
1423 prefixes
|= PREFIX_DATA
;
1426 prefixes
|= PREFIX_ADR
;
1429 prefixes
|= PREFIX_FWAIT
;
1433 if (prefixes
& PREFIX_DATA
)
1435 if (prefixes
& PREFIX_ADR
)
1438 s
->prefix
= prefixes
;
1442 /* lock generation */
1443 if (prefixes
& PREFIX_LOCK
)
1446 /* now check op code */
1450 /**************************/
1451 /* extended op code */
1452 b
= ldub(s
->pc
++) | 0x100;
1455 /**************************/
1473 ot
= dflag
? OT_LONG
: OT_WORD
;
1476 case 0: /* OP Ev, Gv */
1477 modrm
= ldub(s
->pc
++);
1478 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1479 mod
= (modrm
>> 6) & 3;
1482 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1483 gen_op_ld_T0_A0
[ot
]();
1486 opreg
= OR_EAX
+ rm
;
1488 gen_op(s
, op
, ot
, opreg
, reg
);
1489 if (mod
!= 3 && op
!= 7) {
1490 gen_op_st_T0_A0
[ot
]();
1493 case 1: /* OP Gv, Ev */
1494 modrm
= ldub(s
->pc
++);
1495 mod
= (modrm
>> 6) & 3;
1496 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1499 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1500 gen_op_ld_T1_A0
[ot
]();
1503 opreg
= OR_EAX
+ rm
;
1505 gen_op(s
, op
, ot
, reg
, opreg
);
1507 case 2: /* OP A, Iv */
1508 val
= insn_get(s
, ot
);
1509 gen_opi(s
, op
, ot
, OR_EAX
, val
);
1515 case 0x80: /* GRP1 */
1524 ot
= dflag
? OT_LONG
: OT_WORD
;
1526 modrm
= ldub(s
->pc
++);
1527 mod
= (modrm
>> 6) & 3;
1529 op
= (modrm
>> 3) & 7;
1532 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1533 gen_op_ld_T0_A0
[ot
]();
1536 opreg
= rm
+ OR_EAX
;
1543 val
= insn_get(s
, ot
);
1546 val
= (int8_t)insn_get(s
, OT_BYTE
);
1550 gen_opi(s
, op
, ot
, opreg
, val
);
1551 if (op
!= 7 && mod
!= 3) {
1552 gen_op_st_T0_A0
[ot
]();
1557 /**************************/
1558 /* inc, dec, and other misc arith */
1559 case 0x40 ... 0x47: /* inc Gv */
1560 ot
= dflag
? OT_LONG
: OT_WORD
;
1561 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1563 case 0x48 ... 0x4f: /* dec Gv */
1564 ot
= dflag
? OT_LONG
: OT_WORD
;
1565 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1567 case 0xf6: /* GRP3 */
1572 ot
= dflag
? OT_LONG
: OT_WORD
;
1574 modrm
= ldub(s
->pc
++);
1575 mod
= (modrm
>> 6) & 3;
1577 op
= (modrm
>> 3) & 7;
1579 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1580 gen_op_ld_T0_A0
[ot
]();
1582 gen_op_mov_TN_reg
[ot
][0][rm
]();
1587 val
= insn_get(s
, ot
);
1588 gen_op_movl_T1_im(val
);
1589 gen_op_testl_T0_T1_cc();
1590 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1595 gen_op_st_T0_A0
[ot
]();
1597 gen_op_mov_reg_T0
[ot
][rm
]();
1601 gen_op_negl_T0_cc();
1603 gen_op_st_T0_A0
[ot
]();
1605 gen_op_mov_reg_T0
[ot
][rm
]();
1607 s
->cc_op
= CC_OP_SUBB
+ ot
;
1612 gen_op_mulb_AL_T0();
1615 gen_op_mulw_AX_T0();
1619 gen_op_mull_EAX_T0();
1622 s
->cc_op
= CC_OP_MUL
;
1627 gen_op_imulb_AL_T0();
1630 gen_op_imulw_AX_T0();
1634 gen_op_imull_EAX_T0();
1637 s
->cc_op
= CC_OP_MUL
;
1642 gen_op_divb_AL_T0();
1645 gen_op_divw_AX_T0();
1649 gen_op_divl_EAX_T0();
1656 gen_op_idivb_AL_T0();
1659 gen_op_idivw_AX_T0();
1663 gen_op_idivl_EAX_T0();
1672 case 0xfe: /* GRP4 */
1673 case 0xff: /* GRP5 */
1677 ot
= dflag
? OT_LONG
: OT_WORD
;
1679 modrm
= ldub(s
->pc
++);
1680 mod
= (modrm
>> 6) & 3;
1682 op
= (modrm
>> 3) & 7;
1683 if (op
>= 2 && b
== 0xfe) {
1687 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1688 if (op
!= 3 && op
!= 5)
1689 gen_op_ld_T0_A0
[ot
]();
1691 gen_op_mov_TN_reg
[ot
][0][rm
]();
1695 case 0: /* inc Ev */
1696 gen_inc(s
, ot
, OR_TMP0
, 1);
1698 gen_op_st_T0_A0
[ot
]();
1700 gen_op_mov_reg_T0
[ot
][rm
]();
1702 case 1: /* dec Ev */
1703 gen_inc(s
, ot
, OR_TMP0
, -1);
1705 gen_op_st_T0_A0
[ot
]();
1707 gen_op_mov_reg_T0
[ot
][rm
]();
1709 case 2: /* call Ev */
1710 /* XXX: optimize if memory (no and is necessary) */
1712 gen_op_andl_T0_ffff();
1714 next_eip
= s
->pc
- s
->cs_base
;
1715 gen_op_movl_T0_im(next_eip
);
1719 case 3: /* lcall Ev */
1720 /* push return segment + offset */
1721 gen_op_movl_T0_seg(R_CS
);
1723 next_eip
= s
->pc
- s
->cs_base
;
1724 gen_op_movl_T0_im(next_eip
);
1727 gen_op_ld_T1_A0
[ot
]();
1728 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
1729 gen_op_lduw_T0_A0();
1730 gen_movl_seg_T0(s
, R_CS
);
1731 gen_op_movl_T0_T1();
1735 case 4: /* jmp Ev */
1737 gen_op_andl_T0_ffff();
1741 case 5: /* ljmp Ev */
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 6: /* push Ev */
1758 case 0x84: /* test Ev, Gv */
1763 ot
= dflag
? OT_LONG
: OT_WORD
;
1765 modrm
= ldub(s
->pc
++);
1766 mod
= (modrm
>> 6) & 3;
1768 reg
= (modrm
>> 3) & 7;
1770 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1771 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
1772 gen_op_testl_T0_T1_cc();
1773 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1776 case 0xa8: /* test eAX, Iv */
1781 ot
= dflag
? OT_LONG
: OT_WORD
;
1782 val
= insn_get(s
, ot
);
1784 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
1785 gen_op_movl_T1_im(val
);
1786 gen_op_testl_T0_T1_cc();
1787 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1790 case 0x98: /* CWDE/CBW */
1792 gen_op_movswl_EAX_AX();
1794 gen_op_movsbw_AX_AL();
1796 case 0x99: /* CDQ/CWD */
1798 gen_op_movslq_EDX_EAX();
1800 gen_op_movswl_DX_AX();
1802 case 0x1af: /* imul Gv, Ev */
1803 case 0x69: /* imul Gv, Ev, I */
1805 ot
= dflag
? OT_LONG
: OT_WORD
;
1806 modrm
= ldub(s
->pc
++);
1807 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
1808 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
1810 val
= insn_get(s
, ot
);
1811 gen_op_movl_T1_im(val
);
1812 } else if (b
== 0x6b) {
1813 val
= insn_get(s
, OT_BYTE
);
1814 gen_op_movl_T1_im(val
);
1816 gen_op_mov_TN_reg
[ot
][1][reg
]();
1819 if (ot
== OT_LONG
) {
1820 gen_op_imull_T0_T1();
1822 gen_op_imulw_T0_T1();
1824 gen_op_mov_reg_T0
[ot
][reg
]();
1825 s
->cc_op
= CC_OP_MUL
;
1828 case 0x1c1: /* xadd Ev, Gv */
1832 ot
= dflag
? OT_LONG
: OT_WORD
;
1833 modrm
= ldub(s
->pc
++);
1834 reg
= (modrm
>> 3) & 7;
1835 mod
= (modrm
>> 6) & 3;
1838 gen_op_mov_TN_reg
[ot
][0][reg
]();
1839 gen_op_mov_TN_reg
[ot
][1][rm
]();
1840 gen_op_addl_T0_T1_cc();
1841 gen_op_mov_reg_T0
[ot
][rm
]();
1842 gen_op_mov_reg_T1
[ot
][reg
]();
1844 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1845 gen_op_mov_TN_reg
[ot
][0][reg
]();
1846 gen_op_ld_T1_A0
[ot
]();
1847 gen_op_addl_T0_T1_cc();
1848 gen_op_st_T0_A0
[ot
]();
1849 gen_op_mov_reg_T1
[ot
][reg
]();
1851 s
->cc_op
= CC_OP_ADDB
+ ot
;
1854 case 0x1b1: /* cmpxchg Ev, Gv */
1858 ot
= dflag
? OT_LONG
: OT_WORD
;
1859 modrm
= ldub(s
->pc
++);
1860 reg
= (modrm
>> 3) & 7;
1861 mod
= (modrm
>> 6) & 3;
1862 gen_op_mov_TN_reg
[ot
][1][reg
]();
1865 gen_op_mov_TN_reg
[ot
][0][rm
]();
1866 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1867 gen_op_mov_reg_T0
[ot
][rm
]();
1869 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1870 gen_op_ld_T0_A0
[ot
]();
1871 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
1872 gen_op_st_T0_A0
[ot
]();
1874 s
->cc_op
= CC_OP_SUBB
+ ot
;
1876 case 0x1c7: /* cmpxchg8b */
1877 modrm
= ldub(s
->pc
++);
1878 mod
= (modrm
>> 6) & 3;
1881 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1882 gen_op_set_cc_op(s
->cc_op
);
1883 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1885 s
->cc_op
= CC_OP_EFLAGS
;
1888 /**************************/
1890 case 0x50 ... 0x57: /* push */
1891 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
1894 case 0x58 ... 0x5f: /* pop */
1895 ot
= dflag
? OT_LONG
: OT_WORD
;
1897 gen_op_mov_reg_T0
[ot
][b
& 7]();
1900 case 0x60: /* pusha */
1903 case 0x61: /* popa */
1906 case 0x68: /* push Iv */
1908 ot
= dflag
? OT_LONG
: OT_WORD
;
1910 val
= insn_get(s
, ot
);
1912 val
= (int8_t)insn_get(s
, OT_BYTE
);
1913 gen_op_movl_T0_im(val
);
1916 case 0x8f: /* pop Ev */
1917 ot
= dflag
? OT_LONG
: OT_WORD
;
1918 modrm
= ldub(s
->pc
++);
1920 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
1923 case 0xc8: /* enter */
1928 level
= ldub(s
->pc
++);
1929 gen_enter(s
, val
, level
);
1932 case 0xc9: /* leave */
1933 /* XXX: exception not precise (ESP is update before potential exception) */
1935 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1936 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
1938 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
1939 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
1942 ot
= dflag
? OT_LONG
: OT_WORD
;
1943 gen_op_mov_reg_T0
[ot
][R_EBP
]();
1946 case 0x06: /* push es */
1947 case 0x0e: /* push cs */
1948 case 0x16: /* push ss */
1949 case 0x1e: /* push ds */
1950 gen_op_movl_T0_seg(b
>> 3);
1953 case 0x1a0: /* push fs */
1954 case 0x1a8: /* push gs */
1955 gen_op_movl_T0_seg((b
>> 3) & 7);
1958 case 0x07: /* pop es */
1959 case 0x17: /* pop ss */
1960 case 0x1f: /* pop ds */
1962 gen_movl_seg_T0(s
, b
>> 3);
1965 case 0x1a1: /* pop fs */
1966 case 0x1a9: /* pop gs */
1968 gen_movl_seg_T0(s
, (b
>> 3) & 7);
1972 /**************************/
1975 case 0x89: /* mov Gv, Ev */
1979 ot
= dflag
? OT_LONG
: OT_WORD
;
1980 modrm
= ldub(s
->pc
++);
1981 reg
= (modrm
>> 3) & 7;
1983 /* generate a generic store */
1984 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
1987 case 0xc7: /* mov Ev, Iv */
1991 ot
= dflag
? OT_LONG
: OT_WORD
;
1992 modrm
= ldub(s
->pc
++);
1993 mod
= (modrm
>> 6) & 3;
1995 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1996 val
= insn_get(s
, ot
);
1997 gen_op_movl_T0_im(val
);
1999 gen_op_st_T0_A0
[ot
]();
2001 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
2004 case 0x8b: /* mov Ev, Gv */
2008 ot
= dflag
? OT_LONG
: OT_WORD
;
2009 modrm
= ldub(s
->pc
++);
2010 reg
= (modrm
>> 3) & 7;
2012 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2013 gen_op_mov_reg_T0
[ot
][reg
]();
2015 case 0x8e: /* mov seg, Gv */
2016 ot
= dflag
? OT_LONG
: OT_WORD
;
2017 modrm
= ldub(s
->pc
++);
2018 reg
= (modrm
>> 3) & 7;
2019 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2020 if (reg
>= 6 || reg
== R_CS
)
2022 gen_movl_seg_T0(s
, reg
);
2024 case 0x8c: /* mov Gv, seg */
2025 ot
= dflag
? OT_LONG
: OT_WORD
;
2026 modrm
= ldub(s
->pc
++);
2027 reg
= (modrm
>> 3) & 7;
2030 gen_op_movl_T0_seg(reg
);
2031 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2034 case 0x1b6: /* movzbS Gv, Eb */
2035 case 0x1b7: /* movzwS Gv, Eb */
2036 case 0x1be: /* movsbS Gv, Eb */
2037 case 0x1bf: /* movswS Gv, Eb */
2040 /* d_ot is the size of destination */
2041 d_ot
= dflag
+ OT_WORD
;
2042 /* ot is the size of source */
2043 ot
= (b
& 1) + OT_BYTE
;
2044 modrm
= ldub(s
->pc
++);
2045 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2046 mod
= (modrm
>> 6) & 3;
2050 gen_op_mov_TN_reg
[ot
][0][rm
]();
2051 switch(ot
| (b
& 8)) {
2053 gen_op_movzbl_T0_T0();
2056 gen_op_movsbl_T0_T0();
2059 gen_op_movzwl_T0_T0();
2063 gen_op_movswl_T0_T0();
2066 gen_op_mov_reg_T0
[d_ot
][reg
]();
2068 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2070 gen_op_lds_T0_A0
[ot
]();
2072 gen_op_ldu_T0_A0
[ot
]();
2074 gen_op_mov_reg_T0
[d_ot
][reg
]();
2079 case 0x8d: /* lea */
2080 ot
= dflag
? OT_LONG
: OT_WORD
;
2081 modrm
= ldub(s
->pc
++);
2082 reg
= (modrm
>> 3) & 7;
2083 /* we must ensure that no segment is added */
2087 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2089 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2092 case 0xa0: /* mov EAX, Ov */
2094 case 0xa2: /* mov Ov, EAX */
2099 ot
= dflag
? OT_LONG
: OT_WORD
;
2101 offset_addr
= insn_get(s
, OT_LONG
);
2103 offset_addr
= insn_get(s
, OT_WORD
);
2104 gen_op_movl_A0_im(offset_addr
);
2105 /* handle override */
2107 int override
, must_add_seg
;
2108 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
));
2120 gen_op_ld_T0_A0
[ot
]();
2121 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2123 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2124 gen_op_st_T0_A0
[ot
]();
2127 case 0xd7: /* xlat */
2128 gen_op_movl_A0_reg
[R_EBX
]();
2129 gen_op_addl_A0_AL();
2131 gen_op_andl_A0_ffff();
2132 /* handle override */
2134 int override
, must_add_seg
;
2135 must_add_seg
= s
->addseg
;
2137 if (s
->override
>= 0) {
2138 override
= s
->override
;
2144 gen_op_addl_A0_seg(offsetof(CPUX86State
,seg_cache
[override
].base
));
2147 gen_op_ldub_T0_A0();
2148 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2150 case 0xb0 ... 0xb7: /* mov R, Ib */
2151 val
= insn_get(s
, OT_BYTE
);
2152 gen_op_movl_T0_im(val
);
2153 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2155 case 0xb8 ... 0xbf: /* mov R, Iv */
2156 ot
= dflag
? OT_LONG
: OT_WORD
;
2157 val
= insn_get(s
, ot
);
2158 reg
= OR_EAX
+ (b
& 7);
2159 gen_op_movl_T0_im(val
);
2160 gen_op_mov_reg_T0
[ot
][reg
]();
2163 case 0x91 ... 0x97: /* xchg R, EAX */
2164 ot
= dflag
? OT_LONG
: OT_WORD
;
2169 case 0x87: /* xchg Ev, Gv */
2173 ot
= dflag
? OT_LONG
: OT_WORD
;
2174 modrm
= ldub(s
->pc
++);
2175 reg
= (modrm
>> 3) & 7;
2176 mod
= (modrm
>> 6) & 3;
2180 gen_op_mov_TN_reg
[ot
][0][reg
]();
2181 gen_op_mov_TN_reg
[ot
][1][rm
]();
2182 gen_op_mov_reg_T0
[ot
][rm
]();
2183 gen_op_mov_reg_T1
[ot
][reg
]();
2185 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2186 gen_op_mov_TN_reg
[ot
][0][reg
]();
2187 /* for xchg, lock is implicit */
2188 if (!(prefixes
& PREFIX_LOCK
))
2190 gen_op_ld_T1_A0
[ot
]();
2191 gen_op_st_T0_A0
[ot
]();
2192 if (!(prefixes
& PREFIX_LOCK
))
2194 gen_op_mov_reg_T1
[ot
][reg
]();
2197 case 0xc4: /* les Gv */
2200 case 0xc5: /* lds Gv */
2203 case 0x1b2: /* lss Gv */
2206 case 0x1b4: /* lfs Gv */
2209 case 0x1b5: /* lgs Gv */
2212 ot
= dflag
? OT_LONG
: OT_WORD
;
2213 modrm
= ldub(s
->pc
++);
2214 reg
= (modrm
>> 3) & 7;
2215 mod
= (modrm
>> 6) & 3;
2218 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2219 gen_op_ld_T1_A0
[ot
]();
2220 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2221 /* load the segment first to handle exceptions properly */
2222 gen_op_lduw_T0_A0();
2223 gen_movl_seg_T0(s
, op
);
2224 /* then put the data */
2225 gen_op_mov_reg_T1
[ot
][reg
]();
2228 /************************/
2239 ot
= dflag
? OT_LONG
: OT_WORD
;
2241 modrm
= ldub(s
->pc
++);
2242 mod
= (modrm
>> 6) & 3;
2244 op
= (modrm
>> 3) & 7;
2247 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2248 gen_op_ld_T0_A0
[ot
]();
2251 opreg
= rm
+ OR_EAX
;
2256 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2259 shift
= ldub(s
->pc
++);
2261 gen_shifti(s
, op
, ot
, opreg
, shift
);
2265 gen_op_st_T0_A0
[ot
]();
2280 case 0x1a4: /* shld imm */
2284 case 0x1a5: /* shld cl */
2288 case 0x1ac: /* shrd imm */
2292 case 0x1ad: /* shrd cl */
2296 ot
= dflag
? OT_LONG
: OT_WORD
;
2297 modrm
= ldub(s
->pc
++);
2298 mod
= (modrm
>> 6) & 3;
2300 reg
= (modrm
>> 3) & 7;
2303 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2304 gen_op_ld_T0_A0
[ot
]();
2306 gen_op_mov_TN_reg
[ot
][0][rm
]();
2308 gen_op_mov_TN_reg
[ot
][1][reg
]();
2311 val
= ldub(s
->pc
++);
2314 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2315 if (op
== 0 && ot
!= OT_WORD
)
2316 s
->cc_op
= CC_OP_SHLB
+ ot
;
2318 s
->cc_op
= CC_OP_SARB
+ ot
;
2321 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2322 gen_op_set_cc_op(s
->cc_op
);
2323 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2324 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2327 gen_op_st_T0_A0
[ot
]();
2329 gen_op_mov_reg_T0
[ot
][rm
]();
2333 /************************/
2336 modrm
= ldub(s
->pc
++);
2337 mod
= (modrm
>> 6) & 3;
2339 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2343 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2345 case 0x00 ... 0x07: /* fxxxs */
2346 case 0x10 ... 0x17: /* fixxxl */
2347 case 0x20 ... 0x27: /* fxxxl */
2348 case 0x30 ... 0x37: /* fixxx */
2355 gen_op_flds_FT0_A0();
2358 gen_op_fildl_FT0_A0();
2361 gen_op_fldl_FT0_A0();
2365 gen_op_fild_FT0_A0();
2369 gen_op_fp_arith_ST0_FT0
[op1
]();
2371 /* fcomp needs pop */
2376 case 0x08: /* flds */
2377 case 0x0a: /* fsts */
2378 case 0x0b: /* fstps */
2379 case 0x18: /* fildl */
2380 case 0x1a: /* fistl */
2381 case 0x1b: /* fistpl */
2382 case 0x28: /* fldl */
2383 case 0x2a: /* fstl */
2384 case 0x2b: /* fstpl */
2385 case 0x38: /* filds */
2386 case 0x3a: /* fists */
2387 case 0x3b: /* fistps */
2394 gen_op_flds_ST0_A0();
2397 gen_op_fildl_ST0_A0();
2400 gen_op_fldl_ST0_A0();
2404 gen_op_fild_ST0_A0();
2411 gen_op_fsts_ST0_A0();
2414 gen_op_fistl_ST0_A0();
2417 gen_op_fstl_ST0_A0();
2421 gen_op_fist_ST0_A0();
2429 case 0x0d: /* fldcw mem */
2432 case 0x0f: /* fnstcw mem */
2435 case 0x1d: /* fldt mem */
2437 gen_op_fldt_ST0_A0();
2439 case 0x1f: /* fstpt mem */
2440 gen_op_fstt_ST0_A0();
2443 case 0x2f: /* fnstsw mem */
2446 case 0x3c: /* fbld */
2448 gen_op_fbld_ST0_A0();
2450 case 0x3e: /* fbstp */
2451 gen_op_fbst_ST0_A0();
2454 case 0x3d: /* fildll */
2456 gen_op_fildll_ST0_A0();
2458 case 0x3f: /* fistpll */
2459 gen_op_fistll_ST0_A0();
2466 /* register float ops */
2470 case 0x08: /* fld sti */
2472 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2474 case 0x09: /* fxchg sti */
2475 gen_op_fxchg_ST0_STN(opreg
);
2477 case 0x0a: /* grp d9/2 */
2485 case 0x0c: /* grp d9/4 */
2495 gen_op_fcom_ST0_FT0();
2504 case 0x0d: /* grp d9/5 */
2513 gen_op_fldl2t_ST0();
2517 gen_op_fldl2e_ST0();
2525 gen_op_fldlg2_ST0();
2529 gen_op_fldln2_ST0();
2540 case 0x0e: /* grp d9/6 */
2551 case 3: /* fpatan */
2554 case 4: /* fxtract */
2557 case 5: /* fprem1 */
2560 case 6: /* fdecstp */
2564 case 7: /* fincstp */
2569 case 0x0f: /* grp d9/7 */
2574 case 1: /* fyl2xp1 */
2580 case 3: /* fsincos */
2583 case 5: /* fscale */
2586 case 4: /* frndint */
2598 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2599 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2600 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2606 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
2610 gen_op_fmov_FT0_STN(opreg
);
2611 gen_op_fp_arith_ST0_FT0
[op1
]();
2615 case 0x02: /* fcom */
2616 gen_op_fmov_FT0_STN(opreg
);
2617 gen_op_fcom_ST0_FT0();
2619 case 0x03: /* fcomp */
2620 gen_op_fmov_FT0_STN(opreg
);
2621 gen_op_fcom_ST0_FT0();
2624 case 0x15: /* da/5 */
2626 case 1: /* fucompp */
2627 gen_op_fmov_FT0_STN(1);
2628 gen_op_fucom_ST0_FT0();
2641 case 3: /* fninit */
2648 case 0x2a: /* fst sti */
2649 gen_op_fmov_STN_ST0(opreg
);
2651 case 0x2b: /* fstp sti */
2652 gen_op_fmov_STN_ST0(opreg
);
2655 case 0x2c: /* fucom st(i) */
2656 gen_op_fmov_FT0_STN(opreg
);
2657 gen_op_fucom_ST0_FT0();
2659 case 0x2d: /* fucomp st(i) */
2660 gen_op_fmov_FT0_STN(opreg
);
2661 gen_op_fucom_ST0_FT0();
2664 case 0x33: /* de/3 */
2666 case 1: /* fcompp */
2667 gen_op_fmov_FT0_STN(1);
2668 gen_op_fcom_ST0_FT0();
2676 case 0x3c: /* df/4 */
2679 gen_op_fnstsw_EAX();
2690 /************************/
2693 case 0xa4: /* movsS */
2698 ot
= dflag
? OT_LONG
: OT_WORD
;
2700 if (prefixes
& PREFIX_REPZ
) {
2701 gen_string_ds(s
, ot
, gen_op_movs
+ 9);
2703 gen_string_ds(s
, ot
, gen_op_movs
);
2707 case 0xaa: /* stosS */
2712 ot
= dflag
? OT_LONG
: OT_WORD
;
2714 if (prefixes
& PREFIX_REPZ
) {
2715 gen_string_es(s
, ot
, gen_op_stos
+ 9);
2717 gen_string_es(s
, ot
, gen_op_stos
);
2720 case 0xac: /* lodsS */
2725 ot
= dflag
? OT_LONG
: OT_WORD
;
2726 if (prefixes
& PREFIX_REPZ
) {
2727 gen_string_ds(s
, ot
, gen_op_lods
+ 9);
2729 gen_string_ds(s
, ot
, gen_op_lods
);
2732 case 0xae: /* scasS */
2737 ot
= dflag
? OT_LONG
: OT_WORD
;
2738 if (prefixes
& PREFIX_REPNZ
) {
2739 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2740 gen_op_set_cc_op(s
->cc_op
);
2741 gen_string_es(s
, ot
, gen_op_scas
+ 9 * 2);
2742 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2743 } else if (prefixes
& PREFIX_REPZ
) {
2744 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2745 gen_op_set_cc_op(s
->cc_op
);
2746 gen_string_es(s
, ot
, gen_op_scas
+ 9);
2747 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2749 gen_string_es(s
, ot
, gen_op_scas
);
2750 s
->cc_op
= CC_OP_SUBB
+ ot
;
2754 case 0xa6: /* cmpsS */
2759 ot
= dflag
? OT_LONG
: OT_WORD
;
2760 if (prefixes
& PREFIX_REPNZ
) {
2761 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2762 gen_op_set_cc_op(s
->cc_op
);
2763 gen_string_ds(s
, ot
, gen_op_cmps
+ 9 * 2);
2764 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2765 } else if (prefixes
& PREFIX_REPZ
) {
2766 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2767 gen_op_set_cc_op(s
->cc_op
);
2768 gen_string_ds(s
, ot
, gen_op_cmps
+ 9);
2769 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2771 gen_string_ds(s
, ot
, gen_op_cmps
);
2772 s
->cc_op
= CC_OP_SUBB
+ ot
;
2775 case 0x6c: /* insS */
2777 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2778 /* NOTE: even for (E)CX = 0 the exception is raised */
2779 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2784 ot
= dflag
? OT_LONG
: OT_WORD
;
2785 if (prefixes
& PREFIX_REPZ
) {
2786 gen_string_es(s
, ot
, gen_op_ins
+ 9);
2788 gen_string_es(s
, ot
, gen_op_ins
);
2792 case 0x6e: /* outsS */
2794 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2795 /* NOTE: even for (E)CX = 0 the exception is raised */
2796 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2801 ot
= dflag
? OT_LONG
: OT_WORD
;
2802 if (prefixes
& PREFIX_REPZ
) {
2803 gen_string_ds(s
, ot
, gen_op_outs
+ 9);
2805 gen_string_ds(s
, ot
, gen_op_outs
);
2810 /************************/
2814 if (s
->cpl
> s
->iopl
|| s
->vm86
) {
2815 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2820 ot
= dflag
? OT_LONG
: OT_WORD
;
2821 val
= ldub(s
->pc
++);
2822 gen_op_movl_T0_im(val
);
2824 gen_op_mov_reg_T1
[ot
][R_EAX
]();
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
);
2838 gen_op_mov_TN_reg
[ot
][1][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 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
2853 gen_op_mov_reg_T1
[ot
][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
]();
2866 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
2871 /************************/
2873 case 0xc2: /* ret im */
2878 gen_op_addl_ESP_im(val
+ (2 << s
->dflag
));
2880 gen_op_addw_ESP_im(val
+ (2 << s
->dflag
));
2882 gen_op_andl_T0_ffff();
2886 case 0xc3: /* ret */
2890 gen_op_andl_T0_ffff();
2894 case 0xca: /* lret im */
2895 /* XXX: not restartable */
2901 gen_op_andl_T0_ffff();
2906 gen_movl_seg_T0(s
, R_CS
);
2908 /* add stack offset */
2910 gen_op_addl_ESP_im(val
);
2912 gen_op_addw_ESP_im(val
);
2915 case 0xcb: /* lret */
2916 /* XXX: not restartable */
2920 gen_op_andl_T0_ffff();
2925 gen_movl_seg_T0(s
, R_CS
);
2929 case 0xcf: /* iret */
2930 if (s
->vm86
&& s
->iopl
!= 3) {
2931 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
2933 /* XXX: not restartable */
2937 gen_op_andl_T0_ffff();
2942 gen_movl_seg_T0(s
, R_CS
);
2947 gen_op_movl_eflags_T0();
2949 gen_op_movw_eflags_T0();
2952 s
->cc_op
= CC_OP_EFLAGS
;
2956 case 0xe8: /* call im */
2958 unsigned int next_eip
;
2959 ot
= dflag
? OT_LONG
: OT_WORD
;
2960 val
= insn_get(s
, ot
);
2961 next_eip
= s
->pc
- s
->cs_base
;
2965 gen_op_movl_T0_im(next_eip
);
2971 case 0x9a: /* lcall im */
2973 unsigned int selector
, offset
;
2975 ot
= dflag
? OT_LONG
: OT_WORD
;
2976 offset
= insn_get(s
, ot
);
2977 selector
= insn_get(s
, OT_WORD
);
2979 /* push return segment + offset */
2980 gen_op_movl_T0_seg(R_CS
);
2982 next_eip
= s
->pc
- s
->cs_base
;
2983 gen_op_movl_T0_im(next_eip
);
2986 /* change cs and pc */
2987 gen_op_movl_T0_im(selector
);
2988 gen_movl_seg_T0(s
, R_CS
);
2989 gen_op_jmp_im((unsigned long)offset
);
2993 case 0xe9: /* jmp */
2994 ot
= dflag
? OT_LONG
: OT_WORD
;
2995 val
= insn_get(s
, ot
);
2996 val
+= s
->pc
- s
->cs_base
;
3002 case 0xea: /* ljmp im */
3004 unsigned int selector
, offset
;
3006 ot
= dflag
? OT_LONG
: OT_WORD
;
3007 offset
= insn_get(s
, ot
);
3008 selector
= insn_get(s
, OT_WORD
);
3010 /* change cs and pc */
3011 gen_op_movl_T0_im(selector
);
3012 gen_movl_seg_T0(s
, R_CS
);
3013 gen_op_jmp_im((unsigned long)offset
);
3017 case 0xeb: /* jmp Jb */
3018 val
= (int8_t)insn_get(s
, OT_BYTE
);
3019 val
+= s
->pc
- s
->cs_base
;
3025 case 0x70 ... 0x7f: /* jcc Jb */
3026 val
= (int8_t)insn_get(s
, OT_BYTE
);
3028 case 0x180 ... 0x18f: /* jcc Jv */
3030 val
= insn_get(s
, OT_LONG
);
3032 val
= (int16_t)insn_get(s
, OT_WORD
);
3035 next_eip
= s
->pc
- s
->cs_base
;
3039 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 0xcc: /* int3 */
3249 gen_exception(s
, EXCP03_INT3
, s
->pc
- s
->cs_base
);
3251 case 0xcd: /* int N */
3252 val
= ldub(s
->pc
++);
3253 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3254 gen_op_set_cc_op(s
->cc_op
);
3255 gen_op_int_im(val
, pc_start
- s
->cs_base
);
3258 case 0xce: /* into */
3259 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3260 gen_op_set_cc_op(s
->cc_op
);
3261 gen_op_into(s
->pc
- s
->cs_base
);
3263 case 0xfa: /* cli */
3265 if (s
->cpl
<= s
->iopl
) {
3268 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3274 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3278 case 0xfb: /* sti */
3280 if (s
->cpl
<= s
->iopl
) {
3283 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3289 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3293 case 0x62: /* bound */
3294 ot
= dflag
? OT_LONG
: OT_WORD
;
3295 modrm
= ldub(s
->pc
++);
3296 reg
= (modrm
>> 3) & 7;
3297 mod
= (modrm
>> 6) & 3;
3300 gen_op_mov_reg_T0
[ot
][reg
]();
3301 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3307 case 0x1c8 ... 0x1cf: /* bswap reg */
3309 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3311 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3313 case 0xd6: /* salc */
3314 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3315 gen_op_set_cc_op(s
->cc_op
);
3318 case 0xe0: /* loopnz */
3319 case 0xe1: /* loopz */
3320 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3321 gen_op_set_cc_op(s
->cc_op
);
3323 case 0xe2: /* loop */
3324 case 0xe3: /* jecxz */
3325 val
= (int8_t)insn_get(s
, OT_BYTE
);
3326 next_eip
= s
->pc
- s
->cs_base
;
3330 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3333 case 0x131: /* rdtsc */
3336 case 0x1a2: /* cpuid */
3339 case 0xf4: /* hlt */
3340 /* XXX: if cpl == 0, then should do something else */
3341 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3343 case 0x102: /* lar */
3344 case 0x103: /* lsl */
3347 ot
= dflag
? OT_LONG
: OT_WORD
;
3348 modrm
= ldub(s
->pc
++);
3349 reg
= (modrm
>> 3) & 7;
3350 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3351 gen_op_mov_TN_reg
[ot
][1][reg
]();
3352 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3353 gen_op_set_cc_op(s
->cc_op
);
3358 s
->cc_op
= CC_OP_EFLAGS
;
3359 gen_op_mov_reg_T1
[ot
][reg
]();
3364 /* lock generation */
3365 if (s
->prefix
& PREFIX_LOCK
)
3369 /* XXX: ensure that no lock was generated */
3373 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3374 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3376 /* flags read by an operation */
3377 static uint16_t opc_read_flags
[NB_OPS
] = {
3378 [INDEX_op_aas
] = CC_A
,
3379 [INDEX_op_aaa
] = CC_A
,
3380 [INDEX_op_das
] = CC_A
| CC_C
,
3381 [INDEX_op_daa
] = CC_A
| CC_C
,
3383 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
3384 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
3385 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
3386 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
3387 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
3388 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
3390 /* subtle: due to the incl/decl implementation, C is used */
3391 [INDEX_op_incl_T0_cc
] = CC_C
,
3392 [INDEX_op_decl_T0_cc
] = CC_C
,
3394 [INDEX_op_into
] = CC_O
,
3396 [INDEX_op_jo_cc
] = CC_O
,
3397 [INDEX_op_jb_cc
] = CC_C
,
3398 [INDEX_op_jz_cc
] = CC_Z
,
3399 [INDEX_op_jbe_cc
] = CC_Z
| CC_C
,
3400 [INDEX_op_js_cc
] = CC_S
,
3401 [INDEX_op_jp_cc
] = CC_P
,
3402 [INDEX_op_jl_cc
] = CC_O
| CC_S
,
3403 [INDEX_op_jle_cc
] = CC_O
| CC_S
| CC_Z
,
3405 [INDEX_op_jb_subb
] = CC_C
,
3406 [INDEX_op_jb_subw
] = CC_C
,
3407 [INDEX_op_jb_subl
] = CC_C
,
3409 [INDEX_op_jz_subb
] = CC_Z
,
3410 [INDEX_op_jz_subw
] = CC_Z
,
3411 [INDEX_op_jz_subl
] = CC_Z
,
3413 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
3414 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
3415 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
3417 [INDEX_op_js_subb
] = CC_S
,
3418 [INDEX_op_js_subw
] = CC_S
,
3419 [INDEX_op_js_subl
] = CC_S
,
3421 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
3422 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
3423 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
3425 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
3426 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
3427 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
3429 [INDEX_op_loopnzw
] = CC_Z
,
3430 [INDEX_op_loopnzl
] = CC_Z
,
3431 [INDEX_op_loopzw
] = CC_Z
,
3432 [INDEX_op_loopzl
] = CC_Z
,
3434 [INDEX_op_seto_T0_cc
] = CC_O
,
3435 [INDEX_op_setb_T0_cc
] = CC_C
,
3436 [INDEX_op_setz_T0_cc
] = CC_Z
,
3437 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
3438 [INDEX_op_sets_T0_cc
] = CC_S
,
3439 [INDEX_op_setp_T0_cc
] = CC_P
,
3440 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
3441 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
3443 [INDEX_op_setb_T0_subb
] = CC_C
,
3444 [INDEX_op_setb_T0_subw
] = CC_C
,
3445 [INDEX_op_setb_T0_subl
] = CC_C
,
3447 [INDEX_op_setz_T0_subb
] = CC_Z
,
3448 [INDEX_op_setz_T0_subw
] = CC_Z
,
3449 [INDEX_op_setz_T0_subl
] = CC_Z
,
3451 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
3452 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
3453 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
3455 [INDEX_op_sets_T0_subb
] = CC_S
,
3456 [INDEX_op_sets_T0_subw
] = CC_S
,
3457 [INDEX_op_sets_T0_subl
] = CC_S
,
3459 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
3460 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
3461 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
3463 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
3464 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
3465 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
3467 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
3468 [INDEX_op_cmc
] = CC_C
,
3469 [INDEX_op_salc
] = CC_C
,
3471 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
3472 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
3473 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
3474 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
3475 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
3476 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
3479 /* flags written by an operation */
3480 static uint16_t opc_write_flags
[NB_OPS
] = {
3481 [INDEX_op_addl_T0_T1_cc
] = CC_OSZAPC
,
3482 [INDEX_op_orl_T0_T1_cc
] = CC_OSZAPC
,
3483 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
3484 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
3485 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
3486 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
3487 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
3488 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
3489 [INDEX_op_andl_T0_T1_cc
] = CC_OSZAPC
,
3490 [INDEX_op_subl_T0_T1_cc
] = CC_OSZAPC
,
3491 [INDEX_op_xorl_T0_T1_cc
] = CC_OSZAPC
,
3492 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
3493 [INDEX_op_negl_T0_cc
] = CC_OSZAPC
,
3494 /* subtle: due to the incl/decl implementation, C is used */
3495 [INDEX_op_incl_T0_cc
] = CC_OSZAPC
,
3496 [INDEX_op_decl_T0_cc
] = CC_OSZAPC
,
3497 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
3499 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
3500 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
3501 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
3502 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
3503 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
3504 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
3505 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
3506 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
3509 [INDEX_op_aam
] = CC_OSZAPC
,
3510 [INDEX_op_aad
] = CC_OSZAPC
,
3511 [INDEX_op_aas
] = CC_OSZAPC
,
3512 [INDEX_op_aaa
] = CC_OSZAPC
,
3513 [INDEX_op_das
] = CC_OSZAPC
,
3514 [INDEX_op_daa
] = CC_OSZAPC
,
3516 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
3517 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
3518 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
3519 [INDEX_op_clc
] = CC_C
,
3520 [INDEX_op_stc
] = CC_C
,
3521 [INDEX_op_cmc
] = CC_C
,
3523 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
3524 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
3525 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
3526 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
3527 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
3528 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
3530 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
3531 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
3532 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
3533 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
3534 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
3535 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
3537 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
3538 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
3539 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
3541 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
3542 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
3543 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
3545 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
3546 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
3547 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
3549 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3550 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3551 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
3552 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
3554 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
3555 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
3556 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
3557 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
3559 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
3560 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
3561 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
3562 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
3563 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
3564 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
3565 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
3566 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
3568 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
3569 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
3570 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
3571 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
3574 #define STRINGOP(x) \
3575 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3576 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3577 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3578 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3579 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3580 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3581 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3582 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3583 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3587 STRINGOP(repnz_scas
)
3590 STRINGOP(repnz_cmps
)
3592 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
3593 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
3594 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
3596 [INDEX_op_cmpxchg8b
] = CC_Z
,
3597 [INDEX_op_lar
] = CC_Z
,
3598 [INDEX_op_lsl
] = CC_Z
,
3601 /* simpler form of an operation if no flags need to be generated */
3602 static uint16_t opc_simpler
[NB_OPS
] = {
3603 [INDEX_op_addl_T0_T1_cc
] = INDEX_op_addl_T0_T1
,
3604 [INDEX_op_orl_T0_T1_cc
] = INDEX_op_orl_T0_T1
,
3605 [INDEX_op_andl_T0_T1_cc
] = INDEX_op_andl_T0_T1
,
3606 [INDEX_op_subl_T0_T1_cc
] = INDEX_op_subl_T0_T1
,
3607 [INDEX_op_xorl_T0_T1_cc
] = INDEX_op_xorl_T0_T1
,
3608 [INDEX_op_negl_T0_cc
] = INDEX_op_negl_T0
,
3609 [INDEX_op_incl_T0_cc
] = INDEX_op_incl_T0
,
3610 [INDEX_op_decl_T0_cc
] = INDEX_op_decl_T0
,
3612 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
3613 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
3614 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
3616 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
3617 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
3618 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
3620 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
3621 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
3622 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
3624 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
3625 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
3626 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
3628 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
3629 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
3630 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
3633 static void optimize_flags_init(void)
3636 /* put default values in arrays */
3637 for(i
= 0; i
< NB_OPS
; i
++) {
3638 if (opc_simpler
[i
] == 0)
3643 /* CPU flags computation optimization: we move backward thru the
3644 generated code to see which flags are needed. The operation is
3645 modified if suitable */
3646 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
3649 int live_flags
, write_flags
, op
;
3651 opc_ptr
= opc_buf
+ opc_buf_len
;
3652 /* live_flags contains the flags needed by the next instructions
3653 in the code. At the end of the bloc, we consider that all the
3655 live_flags
= CC_OSZAPC
;
3656 while (opc_ptr
> opc_buf
) {
3658 /* if none of the flags written by the instruction is used,
3659 then we can try to find a simpler instruction */
3660 write_flags
= opc_write_flags
[op
];
3661 if ((live_flags
& write_flags
) == 0) {
3662 *opc_ptr
= opc_simpler
[op
];
3664 /* compute the live flags before the instruction */
3665 live_flags
&= ~write_flags
;
3666 live_flags
|= opc_read_flags
[op
];
3672 static const char *op_str
[] = {
3673 #define DEF(s, n) #s,
3674 #include "opc-i386.h"
3678 static uint8_t op_nb_args
[] = {
3679 #define DEF(s, n) n,
3680 #include "opc-i386.h"
3684 static void dump_ops(const uint16_t *opc_buf
, const uint32_t *opparam_buf
)
3686 const uint16_t *opc_ptr
;
3687 const uint32_t *opparam_ptr
;
3691 opparam_ptr
= opparam_buf
;
3695 fprintf(logfile
, "0x%04x: %s",
3696 (int)(opc_ptr
- opc_buf
- 1), op_str
[c
]);
3697 for(i
= 0; i
< n
; i
++) {
3698 fprintf(logfile
, " 0x%x", opparam_ptr
[i
]);
3700 fprintf(logfile
, "\n");
3701 if (c
== INDEX_op_end
)
3709 /* XXX: make this buffer thread safe */
3710 /* XXX: make safe guess about sizes */
3711 #define MAX_OP_PER_INSTR 32
3712 #define OPC_BUF_SIZE 512
3713 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3715 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3717 static uint16_t gen_opc_buf
[OPC_BUF_SIZE
];
3718 static uint32_t gen_opparam_buf
[OPPARAM_BUF_SIZE
];
3720 /* return non zero if the very first instruction is invalid so that
3721 the virtual CPU can trigger an exception.
3723 '*code_size_ptr' contains the target code size including the
3724 instruction which triggered an exception, except in case of invalid
3725 illegal opcode. It must never exceed one target page.
3727 '*gen_code_size_ptr' contains the size of the generated code (host
3730 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
3731 int *gen_code_size_ptr
,
3732 uint8_t *pc_start
, uint8_t *cs_base
, int flags
,
3735 DisasContext dc1
, *dc
= &dc1
;
3737 uint16_t *gen_opc_end
;
3741 /* generate intermediate code */
3743 dc
->code32
= (flags
>> GEN_FLAG_CODE32_SHIFT
) & 1;
3744 dc
->ss32
= (flags
>> GEN_FLAG_SS32_SHIFT
) & 1;
3745 dc
->addseg
= (flags
>> GEN_FLAG_ADDSEG_SHIFT
) & 1;
3746 dc
->f_st
= (flags
>> GEN_FLAG_ST_SHIFT
) & 7;
3747 dc
->vm86
= (flags
>> GEN_FLAG_VM_SHIFT
) & 1;
3748 dc
->cpl
= (flags
>> GEN_FLAG_CPL_SHIFT
) & 3;
3749 dc
->iopl
= (flags
>> GEN_FLAG_IOPL_SHIFT
) & 3;
3750 dc
->tf
= (flags
>> GEN_FLAG_TF_SHIFT
) & 1;
3751 dc
->cc_op
= CC_OP_DYNAMIC
;
3752 dc
->cs_base
= cs_base
;
3754 gen_opc_ptr
= gen_opc_buf
;
3755 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
3756 gen_opparam_ptr
= gen_opparam_buf
;
3761 ret
= disas_insn(dc
, pc_ptr
);
3763 /* we trigger an illegal instruction operation only if it
3764 is the first instruction. Otherwise, we simply stop
3765 generating the code just before it */
3766 if (pc_ptr
== pc_start
)
3771 pc_ptr
= (void *)ret
;
3772 /* if single step mode, we generate only one instruction and
3773 generate an exception */
3776 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
3777 (pc_ptr
- pc_start
) < (TARGET_PAGE_SIZE
- 32));
3778 /* we must store the eflags state if it is not already done */
3779 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
3780 gen_op_set_cc_op(dc
->cc_op
);
3781 if (dc
->is_jmp
!= 1) {
3782 /* we add an additionnal jmp to update the simulated PC */
3783 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
3786 gen_op_raise_exception(EXCP01_SSTP
);
3789 *gen_opc_ptr
= INDEX_op_end
;
3793 fprintf(logfile
, "----------------\n");
3794 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
3795 disas(logfile
, pc_start
, pc_ptr
- pc_start
,
3796 dc
->code32
? DISAS_I386_I386
: DISAS_I386_I8086
);
3797 fprintf(logfile
, "\n");
3799 fprintf(logfile
, "OP:\n");
3800 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3801 fprintf(logfile
, "\n");
3805 /* optimize flag computations */
3806 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
3810 fprintf(logfile
, "AFTER FLAGS OPT:\n");
3811 dump_ops(gen_opc_buf
, gen_opparam_buf
);
3812 fprintf(logfile
, "\n");
3816 /* generate machine code */
3817 gen_code_size
= dyngen_code(gen_code_buf
, gen_opc_buf
, gen_opparam_buf
);
3818 flush_icache_range((unsigned long)gen_code_buf
, (unsigned long)(gen_code_buf
+ gen_code_size
));
3819 *gen_code_size_ptr
= gen_code_size
;
3820 *code_size_ptr
= pc_ptr
- pc_start
;
3823 fprintf(logfile
, "OUT: [size=%d]\n", *gen_code_size_ptr
);
3824 disas(logfile
, gen_code_buf
, *gen_code_size_ptr
, DISAS_TARGET
);
3825 fprintf(logfile
, "\n");
3832 CPUX86State
*cpu_x86_init(void)
3838 cpu_x86_tblocks_init();
3840 env
= malloc(sizeof(CPUX86State
));
3843 memset(env
, 0, sizeof(CPUX86State
));
3844 /* basic FPU init */
3845 for(i
= 0;i
< 8; i
++)
3848 /* flags setup : we activate the IRQs by default as in user mode */
3849 env
->eflags
= 0x2 | IF_MASK
;
3851 /* init various static tables */
3854 optimize_flags_init();
3860 void cpu_x86_close(CPUX86State
*env
)
3865 static const char *cc_op_str
[] = {
3898 void cpu_x86_dump_state(CPUX86State
*env
, FILE *f
, int flags
)
3901 char cc_op_name
[32];
3903 eflags
= env
->eflags
;
3904 fprintf(f
, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3905 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3906 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3907 env
->regs
[R_EAX
], env
->regs
[R_EBX
], env
->regs
[R_ECX
], env
->regs
[R_EDX
],
3908 env
->regs
[R_ESI
], env
->regs
[R_EDI
], env
->regs
[R_EBP
], env
->regs
[R_ESP
],
3910 eflags
& DF_MASK
? 'D' : '-',
3911 eflags
& CC_O
? 'O' : '-',
3912 eflags
& CC_S
? 'S' : '-',
3913 eflags
& CC_Z
? 'Z' : '-',
3914 eflags
& CC_A
? 'A' : '-',
3915 eflags
& CC_P
? 'P' : '-',
3916 eflags
& CC_C
? 'C' : '-');
3917 fprintf(f
, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3924 if (flags
& X86_DUMP_CCOP
) {
3925 if ((unsigned)env
->cc_op
< CC_OP_NB
)
3926 strcpy(cc_op_name
, cc_op_str
[env
->cc_op
]);
3928 snprintf(cc_op_name
, sizeof(cc_op_name
), "[%d]", env
->cc_op
);
3929 fprintf(f
, "CCS=%08x CCD=%08x CCO=%-8s\n",
3930 env
->cc_src
, env
->cc_dst
, cc_op_name
);
3932 if (flags
& X86_DUMP_FPU
) {
3933 fprintf(f
, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
3934 (double)env
->fpregs
[0],
3935 (double)env
->fpregs
[1],
3936 (double)env
->fpregs
[2],
3937 (double)env
->fpregs
[3]);
3938 fprintf(f
, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
3939 (double)env
->fpregs
[4],
3940 (double)env
->fpregs
[5],
3941 (double)env
->fpregs
[7],
3942 (double)env
->fpregs
[8]);