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;
3090 case 0x9e: /* sahf */
3091 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3092 if (s->cc_op != CC_OP_DYNAMIC)
3093 gen_op_set_cc_op(s->cc_op);
3094 gen_op_movb_eflags_T0();
3095 s->cc_op = CC_OP_EFLAGS;
3097 case 0x9f: /* lahf */
3098 if (s->cc_op != CC_OP_DYNAMIC)
3099 gen_op_set_cc_op(s->cc_op);
3100 gen_op_movl_T0_eflags();
3101 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3103 case 0xf5: /* cmc */
3104 if (s->cc_op != CC_OP_DYNAMIC)
3105 gen_op_set_cc_op(s->cc_op);
3107 s->cc_op = CC_OP_EFLAGS;
3109 case 0xf8: /* clc */
3110 if (s->cc_op != CC_OP_DYNAMIC)
3111 gen_op_set_cc_op(s->cc_op);
3113 s->cc_op = CC_OP_EFLAGS;
3115 case 0xf9: /* stc */
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 0xfc: /* cld */
3124 case 0xfd: /* std */
3128 /************************/
3129 /* bit operations */
3130 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3131 ot = dflag ? OT_LONG : OT_WORD;
3132 modrm = ldub(s->pc++);
3133 op = (modrm >> 3) & 7;
3134 mod = (modrm >> 6) & 3;
3137 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3138 gen_op_ld_T0_A0[ot]();
3140 gen_op_mov_TN_reg[ot][0][rm]();
3143 val = ldub(s->pc++);
3144 gen_op_movl_T1_im(val);
3148 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3149 s->cc_op = CC_OP_SARB + ot;
3152 gen_op_st_T0_A0[ot]();
3154 gen_op_mov_reg_T0[ot][rm]();
3157 case 0x1a3: /* bt Gv, Ev */
3160 case 0x1ab: /* bts */
3163 case 0x1b3: /* btr */
3166 case 0x1bb: /* btc */
3169 ot = dflag ? OT_LONG : OT_WORD;
3170 modrm = ldub(s->pc++);
3171 reg = (modrm >> 3) & 7;
3172 mod = (modrm >> 6) & 3;
3174 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3176 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3177 /* specific case: we need to add a displacement */
3179 gen_op_add_bitw_A0_T1();
3181 gen_op_add_bitl_A0_T1();
3182 gen_op_ld_T0_A0[ot]();
3184 gen_op_mov_TN_reg[ot][0][rm]();
3186 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3187 s->cc_op = CC_OP_SARB + ot;
3190 gen_op_st_T0_A0[ot]();
3192 gen_op_mov_reg_T0[ot][rm]();
3195 case 0x1bc: /* bsf */
3196 case 0x1bd: /* bsr */
3197 ot = dflag ? OT_LONG : OT_WORD;
3198 modrm = ldub(s->pc++);
3199 reg = (modrm >> 3) & 7;
3200 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3201 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3202 /* NOTE: we always write back the result. Intel doc says it is
3203 undefined if T0 == 0 */
3204 gen_op_mov_reg_T0[ot][reg]();
3205 s->cc_op = CC_OP_LOGICB + ot;
3207 /************************/
3209 case 0x27: /* daa */
3210 if (s->cc_op != CC_OP_DYNAMIC)
3211 gen_op_set_cc_op(s->cc_op);
3213 s->cc_op = CC_OP_EFLAGS;
3215 case 0x2f: /* das */
3216 if (s->cc_op != CC_OP_DYNAMIC)
3217 gen_op_set_cc_op(s->cc_op);
3219 s->cc_op = CC_OP_EFLAGS;
3221 case 0x37: /* aaa */
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 0x3f: /* aas */
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 0xd4: /* aam */
3234 val = ldub(s->pc++);
3236 s->cc_op = CC_OP_LOGICB;
3238 case 0xd5: /* aad */
3239 val = ldub(s->pc++);
3241 s->cc_op = CC_OP_LOGICB;
3243 /************************/
3245 case 0x90: /* nop */
3247 case 0xcc: /* int3 */
3248 gen_exception(s, EXCP03_INT3, s->pc - s->cs_base);
3250 case 0xcd: /* int N */
3251 val = ldub(s->pc++);
3252 if (s->cc_op != CC_OP_DYNAMIC)
3253 gen_op_set_cc_op(s->cc_op);
3254 gen_op_int_im(val, pc_start - s->cs_base);
3257 case 0xce: /* into */
3258 if (s->cc_op != CC_OP_DYNAMIC)
3259 gen_op_set_cc_op(s->cc_op);
3260 gen_op_into(s->pc - s->cs_base);
3262 case 0xfa: /* cli */
3264 if (s->cpl <= s->iopl) {
3267 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3273 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3277 case 0xfb: /* sti */
3279 if (s->cpl <= s->iopl) {
3282 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3288 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3292 case 0x62: /* bound */
3293 ot = dflag ? OT_LONG : OT_WORD;
3294 modrm = ldub(s->pc++);
3295 reg = (modrm >> 3) & 7;
3296 mod = (modrm >> 6) & 3;
3299 gen_op_mov_reg_T0[ot][reg]();
3300 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3306 case 0x1c8 ... 0x1cf: /* bswap reg */
3308 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3310 gen_op_mov_reg_T0[OT_LONG][reg]();
3312 case 0xd6: /* salc */
3313 if (s->cc_op != CC_OP_DYNAMIC)
3314 gen_op_set_cc_op(s->cc_op);
3317 case 0xe0: /* loopnz */
3318 case 0xe1: /* loopz */
3319 if (s->cc_op != CC_OP_DYNAMIC)
3320 gen_op_set_cc_op(s->cc_op);
3322 case 0xe2: /* loop */
3323 case 0xe3: /* jecxz */
3324 val = (int8_t)insn_get(s, OT_BYTE);
3325 next_eip = s->pc - s->cs_base;
3329 gen_op_loop[s->aflag][b & 3](val, next_eip);
3332 case 0x131: /* rdtsc */
3335 case 0x1a2: /* cpuid */
3338 case 0xf4: /* hlt */
3339 /* XXX: if cpl == 0, then should do something else */
3340 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3342 case 0x102: /* lar */
3343 case 0x103: /* lsl */
3346 ot = dflag ? OT_LONG : OT_WORD;
3347 modrm = ldub(s->pc++);
3348 reg = (modrm >> 3) & 7;
3349 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3350 gen_op_mov_TN_reg[ot][1][reg]();
3351 if (s->cc_op != CC_OP_DYNAMIC)
3352 gen_op_set_cc_op(s->cc_op);
3357 s->cc_op = CC_OP_EFLAGS;
3358 gen_op_mov_reg_T1[ot][reg]();
3363 /* lock generation */
3364 if (s->prefix & PREFIX_LOCK)
3368 /* XXX: ensure that no lock was generated */
3372 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3373 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3375 /* flags read by an operation */
3376 static uint16_t opc_read_flags[NB_OPS] = {
3377 [INDEX_op_aas] = CC_A,
3378 [INDEX_op_aaa] = CC_A,
3379 [INDEX_op_das] = CC_A | CC_C,
3380 [INDEX_op_daa] = CC_A | CC_C,
3382 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3383 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3384 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3385 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3386 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3387 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3389 /* subtle: due to the incl/decl implementation, C is used */
3390 [INDEX_op_incl_T0_cc] = CC_C,
3391 [INDEX_op_decl_T0_cc] = CC_C,
3393 [INDEX_op_into] = CC_O,
3395 [INDEX_op_jo_cc] = CC_O,
3396 [INDEX_op_jb_cc] = CC_C,
3397 [INDEX_op_jz_cc] = CC_Z,
3398 [INDEX_op_jbe_cc] = CC_Z | CC_C,
3399 [INDEX_op_js_cc] = CC_S,
3400 [INDEX_op_jp_cc] = CC_P,
3401 [INDEX_op_jl_cc] = CC_O | CC_S,
3402 [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3404 [INDEX_op_jb_subb] = CC_C,
3405 [INDEX_op_jb_subw] = CC_C,
3406 [INDEX_op_jb_subl] = CC_C,
3408 [INDEX_op_jz_subb] = CC_Z,
3409 [INDEX_op_jz_subw] = CC_Z,
3410 [INDEX_op_jz_subl] = CC_Z,
3412 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3413 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3414 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3416 [INDEX_op_js_subb] = CC_S,
3417 [INDEX_op_js_subw] = CC_S,
3418 [INDEX_op_js_subl] = CC_S,
3420 [INDEX_op_jl_subb] = CC_O | CC_S,
3421 [INDEX_op_jl_subw] = CC_O | CC_S,
3422 [INDEX_op_jl_subl] = CC_O | CC_S,
3424 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3425 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3426 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3428 [INDEX_op_loopnzw] = CC_Z,
3429 [INDEX_op_loopnzl] = CC_Z,
3430 [INDEX_op_loopzw] = CC_Z,
3431 [INDEX_op_loopzl] = CC_Z,
3433 [INDEX_op_seto_T0_cc] = CC_O,
3434 [INDEX_op_setb_T0_cc] = CC_C,
3435 [INDEX_op_setz_T0_cc] = CC_Z,
3436 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3437 [INDEX_op_sets_T0_cc] = CC_S,
3438 [INDEX_op_setp_T0_cc] = CC_P,
3439 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3440 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3442 [INDEX_op_setb_T0_subb] = CC_C,
3443 [INDEX_op_setb_T0_subw] = CC_C,
3444 [INDEX_op_setb_T0_subl] = CC_C,
3446 [INDEX_op_setz_T0_subb] = CC_Z,
3447 [INDEX_op_setz_T0_subw] = CC_Z,
3448 [INDEX_op_setz_T0_subl] = CC_Z,
3450 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3451 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3452 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3454 [INDEX_op_sets_T0_subb] = CC_S,
3455 [INDEX_op_sets_T0_subw] = CC_S,
3456 [INDEX_op_sets_T0_subl] = CC_S,
3458 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3459 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3460 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3462 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3463 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3464 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3466 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3467 [INDEX_op_cmc] = CC_C,
3468 [INDEX_op_salc] = CC_C,
3470 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3471 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3472 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3473 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3474 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3475 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3478 /* flags written by an operation */
3479 static uint16_t opc_write_flags[NB_OPS] = {
3480 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3481 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3482 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3483 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3484 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3485 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3486 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3487 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3488 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3489 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3490 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3491 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3492 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3493 /* subtle: due to the incl/decl implementation, C is used */
3494 [INDEX_op_incl_T0_cc] = CC_OSZAPC,
3495 [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3496 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3498 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3499 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3500 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3501 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3502 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3503 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3504 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3505 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3508 [INDEX_op_aam] = CC_OSZAPC,
3509 [INDEX_op_aad] = CC_OSZAPC,
3510 [INDEX_op_aas] = CC_OSZAPC,
3511 [INDEX_op_aaa] = CC_OSZAPC,
3512 [INDEX_op_das] = CC_OSZAPC,
3513 [INDEX_op_daa] = CC_OSZAPC,
3515 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3516 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3517 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3518 [INDEX_op_clc] = CC_C,
3519 [INDEX_op_stc] = CC_C,
3520 [INDEX_op_cmc] = CC_C,
3522 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3523 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3524 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3525 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3526 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3527 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3529 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3530 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3531 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3532 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3533 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3534 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3536 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3537 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3538 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3540 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3541 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3542 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3544 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3545 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3546 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3548 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3549 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3550 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3551 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3553 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3554 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3555 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3556 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3558 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3559 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3560 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3561 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3562 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3563 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3564 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3565 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3567 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3568 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3569 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3570 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3573 #define STRINGOP(x) \
3574 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3575 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3576 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3577 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3578 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3579 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3580 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3581 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3582 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3586 STRINGOP(repnz_scas)
3589 STRINGOP(repnz_cmps)
3591 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3592 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3593 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3595 [INDEX_op_cmpxchg8b] = CC_Z,
3596 [INDEX_op_lar] = CC_Z,
3597 [INDEX_op_lsl] = CC_Z,
3600 /* simpler form of an operation if no flags need to be generated */
3601 static uint16_t opc_simpler[NB_OPS] = {
3602 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3603 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3604 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3605 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3606 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3607 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3608 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3609 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3611 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3612 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3613 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3615 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3616 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3617 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3619 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3620 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3621 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3623 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3624 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3625 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3627 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3628 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3629 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3632 static void optimize_flags_init(void)
3635 /* put default values in arrays */
3636 for(i = 0; i < NB_OPS; i++) {
3637 if (opc_simpler[i] == 0)
3642 /* CPU flags computation optimization: we move backward thru the
3643 generated code to see which flags are needed. The operation is
3644 modified if suitable */
3645 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3648 int live_flags, write_flags, op;
3650 opc_ptr = opc_buf + opc_buf_len;
3651 /* live_flags contains the flags needed by the next instructions
3652 in the code. At the end of the bloc, we consider that all the
3654 live_flags = CC_OSZAPC;
3655 while (opc_ptr > opc_buf) {
3657 /* if none of the flags written by the instruction is used,
3658 then we can try to find a simpler instruction */
3659 write_flags = opc_write_flags[op];
3660 if ((live_flags & write_flags) == 0) {
3661 *opc_ptr = opc_simpler[op];
3663 /* compute the live flags before the instruction */
3664 live_flags &= ~write_flags;
3665 live_flags |= opc_read_flags[op];
3671 static const char *op_str[] = {
3672 #define DEF(s, n) #s,
3673 #include "opc-i386.h"
3677 static uint8_t op_nb_args[] = {
3678 #define DEF(s, n) n,
3679 #include "opc-i386.h"
3683 static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3685 const uint16_t *opc_ptr;
3686 const uint32_t *opparam_ptr;
3690 opparam_ptr = opparam_buf;
3694 fprintf(logfile, "0x%04x: %s",
3695 (int)(opc_ptr - opc_buf - 1), op_str[c]);
3696 for(i = 0; i < n; i++) {
3697 fprintf(logfile, " 0x%x", opparam_ptr[i]);
3699 fprintf(logfile, "\n");
3700 if (c == INDEX_op_end)
3708 /* XXX: make this buffer thread safe */
3709 /* XXX: make safe guess about sizes */
3710 #define MAX_OP_PER_INSTR 32
3711 #define OPC_BUF_SIZE 512
3712 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3714 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3716 static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3717 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3719 /* return non zero if the very first instruction is invalid so that
3720 the virtual CPU can trigger an exception.
3722 '*code_size_ptr' contains the target code size including the
3723 instruction which triggered an exception, except in case of invalid
3724 illegal opcode. It must never exceed one target page.
3726 '*gen_code_size_ptr' contains the size of the generated code (host
3729 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3730 int *gen_code_size_ptr,
3731 uint8_t *pc_start, uint8_t *cs_base, int flags,
3734 DisasContext dc1, *dc = &dc1;
3736 uint16_t *gen_opc_end;
3740 /* generate intermediate code */
3742 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3743 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3744 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3745 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3746 dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3747 dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3748 dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3749 dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3750 dc->cc_op = CC_OP_DYNAMIC;
3751 dc->cs_base = cs_base;
3753 gen_opc_ptr = gen_opc_buf;
3754 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3755 gen_opparam_ptr = gen_opparam_buf;
3760 ret = disas_insn(dc, pc_ptr);
3762 /* we trigger an illegal instruction operation only if it
3763 is the first instruction. Otherwise, we simply stop
3764 generating the code just before it */
3765 if (pc_ptr == pc_start)
3770 pc_ptr = (void *)ret;
3771 /* if single step mode, we generate only one instruction and
3772 generate an exception */
3775 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3776 (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3777 /* we must store the eflags state if it is not already done */
3778 if (dc->cc_op != CC_OP_DYNAMIC)
3779 gen_op_set_cc_op(dc->cc_op);
3780 if (dc->is_jmp != 1) {
3781 /* we add an additionnal jmp to update the simulated PC */
3782 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3785 gen_op_raise_exception(EXCP01_SSTP);
3788 *gen_opc_ptr = INDEX_op_end;
3792 fprintf(logfile, "----------------\n");
3793 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3794 disas(logfile, pc_start, pc_ptr - pc_start,
3795 dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3796 fprintf(logfile, "\n");
3798 fprintf(logfile, "OP:\n");
3799 dump_ops(gen_opc_buf, gen_opparam_buf);
3800 fprintf(logfile, "\n");
3804 /* optimize flag computations */
3805 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3809 fprintf(logfile, "AFTER FLAGS OPT:\n");
3810 dump_ops(gen_opc_buf, gen_opparam_buf);
3811 fprintf(logfile, "\n");
3815 /* generate machine code */
3816 gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3817 flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3818 *gen_code_size_ptr = gen_code_size;
3819 *code_size_ptr = pc_ptr - pc_start;
3822 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3823 disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3824 fprintf(logfile, "\n");
3831 CPUX86State *cpu_x86_init(void)
3837 cpu_x86_tblocks_init();
3839 env = malloc(sizeof(CPUX86State));
3842 memset(env, 0, sizeof(CPUX86State));
3843 /* basic FPU init */
3844 for(i = 0;i < 8; i++)
3847 /* flags setup : we activate the IRQs by default as in user mode */
3848 env->eflags = 0x2 | IF_MASK;
3850 /* init various static tables */
3853 optimize_flags_init();
3859 void cpu_x86_close(CPUX86State *env)
3864 static const char *cc_op_str[] = {
3897 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3900 char cc_op_name[32];
3902 eflags = env->eflags;
3903 fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
3904 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
3905 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
3906 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
3907 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
3909 eflags & DF_MASK ? 'D' : '-',
3910 eflags & CC_O ? 'O' : '-',
3911 eflags & CC_S ? 'S' : '-',
3912 eflags & CC_Z ? 'Z' : '-',
3913 eflags & CC_A ? 'A' : '-',
3914 eflags & CC_P ? 'P' : '-',
3915 eflags & CC_C ? 'C' : '-');
3916 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3923 if (flags & X86_DUMP_CCOP) {
3924 if ((unsigned)env->cc_op < CC_OP_NB)
3925 strcpy(cc_op_name, cc_op_str[env->cc_op]);
3927 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
3928 fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
3929 env->cc_src, env->cc_dst, cc_op_name);
3931 if (flags & X86_DUMP_FPU) {
3932 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
3933 (double)env->fpregs[0],
3934 (double)env->fpregs[1],
3935 (double)env->fpregs[2],
3936 (double)env->fpregs[3]);
3937 fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
3938 (double)env->fpregs[4],
3939 (double)env->fpregs[5],
3940 (double)env->fpregs[7],
3941 (double)env->fpregs[8]);