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
39 #define offsetof(type, field) ((size_t) &((type *)0)->field)
42 /* XXX: move that elsewhere */
43 static uint16_t *gen_opc_ptr;
44 static uint32_t *gen_opparam_ptr;
45 int __op_param1, __op_param2, __op_param3;
48 static inline void flush_icache_range(unsigned long start, unsigned long stop)
55 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
57 static void inline flush_icache_range(unsigned long start, unsigned long stop)
61 p = start & ~(MIN_CACHE_LINE_SIZE - 1);
62 stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
64 for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
65 asm ("dcbst 0,%0;" : : "r"(p) : "memory");
68 for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
69 asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
80 #define PREFIX_REPNZ 2
83 #define PREFIX_SS 0x10
84 #define PREFIX_DS 0x20
85 #define PREFIX_ES 0x40
86 #define PREFIX_FS 0x80
87 #define PREFIX_GS 0x100
88 #define PREFIX_DATA 0x200
89 #define PREFIX_ADR 0x400
90 #define PREFIX_FWAIT 0x800
92 typedef struct DisasContext {
93 /* current insn context */
96 uint8_t *pc; /* pc = eip + cs_base */
97 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
98 static state change (stop translation) */
99 /* current block context */
100 uint8_t *cs_base; /* base of CS segment */
101 int code32; /* 32 bit code segment */
102 int ss32; /* 32 bit stack segment */
103 int cc_op; /* current CC operation */
104 int addseg; /* non zero if either DS/ES/SS have a non zero base */
105 int f_st; /* currently unused */
108 /* i386 arith/logic operations */
128 OP_SHL1, /* undocumented */
133 #define DEF(s) INDEX_op_ ## s,
134 #include "opc-i386.h"
150 /* I386 int registers */
151 OR_EAX, /* MUST be even numbered */
159 OR_TMP0, /* temporary operand register */
161 OR_A0, /* temporary register used when doing address evaluation */
162 OR_ZERO, /* fixed zero register */
166 typedef void (GenOpFunc)(void);
167 typedef void (GenOpFunc1)(long);
168 typedef void (GenOpFunc2)(long, long);
170 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
203 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
236 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
259 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
329 static GenOpFunc *gen_op_movl_A0_reg[8] = {
340 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
352 gen_op_addl_A0_EAX_s1,
353 gen_op_addl_A0_ECX_s1,
354 gen_op_addl_A0_EDX_s1,
355 gen_op_addl_A0_EBX_s1,
356 gen_op_addl_A0_ESP_s1,
357 gen_op_addl_A0_EBP_s1,
358 gen_op_addl_A0_ESI_s1,
359 gen_op_addl_A0_EDI_s1,
362 gen_op_addl_A0_EAX_s2,
363 gen_op_addl_A0_ECX_s2,
364 gen_op_addl_A0_EDX_s2,
365 gen_op_addl_A0_EBX_s2,
366 gen_op_addl_A0_ESP_s2,
367 gen_op_addl_A0_EBP_s2,
368 gen_op_addl_A0_ESI_s2,
369 gen_op_addl_A0_EDI_s2,
372 gen_op_addl_A0_EAX_s3,
373 gen_op_addl_A0_ECX_s3,
374 gen_op_addl_A0_EDX_s3,
375 gen_op_addl_A0_EBX_s3,
376 gen_op_addl_A0_ESP_s3,
377 gen_op_addl_A0_EBP_s3,
378 gen_op_addl_A0_ESI_s3,
379 gen_op_addl_A0_EDI_s3,
383 static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
385 gen_op_cmovw_EAX_T1_T0,
386 gen_op_cmovw_ECX_T1_T0,
387 gen_op_cmovw_EDX_T1_T0,
388 gen_op_cmovw_EBX_T1_T0,
389 gen_op_cmovw_ESP_T1_T0,
390 gen_op_cmovw_EBP_T1_T0,
391 gen_op_cmovw_ESI_T1_T0,
392 gen_op_cmovw_EDI_T1_T0,
395 gen_op_cmovl_EAX_T1_T0,
396 gen_op_cmovl_ECX_T1_T0,
397 gen_op_cmovl_EDX_T1_T0,
398 gen_op_cmovl_EBX_T1_T0,
399 gen_op_cmovl_ESP_T1_T0,
400 gen_op_cmovl_EBP_T1_T0,
401 gen_op_cmovl_ESI_T1_T0,
402 gen_op_cmovl_EDI_T1_T0,
406 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
407 gen_op_addl_T0_T1_cc,
411 gen_op_andl_T0_T1_cc,
412 gen_op_subl_T0_T1_cc,
413 gen_op_xorl_T0_T1_cc,
414 gen_op_cmpl_T0_T1_cc,
417 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
419 gen_op_adcb_T0_T1_cc,
420 gen_op_sbbb_T0_T1_cc,
423 gen_op_adcw_T0_T1_cc,
424 gen_op_sbbw_T0_T1_cc,
427 gen_op_adcl_T0_T1_cc,
428 gen_op_sbbl_T0_T1_cc,
432 static const int cc_op_arithb[8] = {
443 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
444 gen_op_cmpxchgb_T0_T1_EAX_cc,
445 gen_op_cmpxchgw_T0_T1_EAX_cc,
446 gen_op_cmpxchgl_T0_T1_EAX_cc,
449 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
451 gen_op_rolb_T0_T1_cc,
452 gen_op_rorb_T0_T1_cc,
453 gen_op_rclb_T0_T1_cc,
454 gen_op_rcrb_T0_T1_cc,
455 gen_op_shlb_T0_T1_cc,
456 gen_op_shrb_T0_T1_cc,
457 gen_op_shlb_T0_T1_cc,
458 gen_op_sarb_T0_T1_cc,
461 gen_op_rolw_T0_T1_cc,
462 gen_op_rorw_T0_T1_cc,
463 gen_op_rclw_T0_T1_cc,
464 gen_op_rcrw_T0_T1_cc,
465 gen_op_shlw_T0_T1_cc,
466 gen_op_shrw_T0_T1_cc,
467 gen_op_shlw_T0_T1_cc,
468 gen_op_sarw_T0_T1_cc,
471 gen_op_roll_T0_T1_cc,
472 gen_op_rorl_T0_T1_cc,
473 gen_op_rcll_T0_T1_cc,
474 gen_op_rcrl_T0_T1_cc,
475 gen_op_shll_T0_T1_cc,
476 gen_op_shrl_T0_T1_cc,
477 gen_op_shll_T0_T1_cc,
478 gen_op_sarl_T0_T1_cc,
482 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
484 gen_op_shldw_T0_T1_im_cc,
485 gen_op_shrdw_T0_T1_im_cc,
488 gen_op_shldl_T0_T1_im_cc,
489 gen_op_shrdl_T0_T1_im_cc,
493 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
495 gen_op_shldw_T0_T1_ECX_cc,
496 gen_op_shrdw_T0_T1_ECX_cc,
499 gen_op_shldl_T0_T1_ECX_cc,
500 gen_op_shrdl_T0_T1_ECX_cc,
504 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
507 gen_op_btsw_T0_T1_cc,
508 gen_op_btrw_T0_T1_cc,
509 gen_op_btcw_T0_T1_cc,
513 gen_op_btsl_T0_T1_cc,
514 gen_op_btrl_T0_T1_cc,
515 gen_op_btcl_T0_T1_cc,
519 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
530 static GenOpFunc *gen_op_lds_T0_A0[3] = {
535 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
540 /* sign does not matter */
541 static GenOpFunc *gen_op_ld_T0_A0[3] = {
547 static GenOpFunc *gen_op_ld_T1_A0[3] = {
553 static GenOpFunc *gen_op_st_T0_A0[3] = {
559 static GenOpFunc *gen_op_movs[6] = {
568 static GenOpFunc *gen_op_stos[6] = {
577 static GenOpFunc *gen_op_lods[6] = {
586 static GenOpFunc *gen_op_scas[9] = {
598 static GenOpFunc *gen_op_cmps[9] = {
610 static GenOpFunc *gen_op_ins[6] = {
620 static GenOpFunc *gen_op_outs[6] = {
629 static GenOpFunc *gen_op_in[3] = {
635 static GenOpFunc *gen_op_out[3] = {
652 static GenOpFunc2 *gen_jcc_slow[8] = {
663 static GenOpFunc2 *gen_jcc_sub[3][8] = {
695 static GenOpFunc2 *gen_op_loop[2][4] = {
710 static GenOpFunc *gen_setcc_slow[8] = {
721 static GenOpFunc *gen_setcc_sub[3][8] = {
726 gen_op_setbe_T0_subb,
730 gen_op_setle_T0_subb,
736 gen_op_setbe_T0_subw,
740 gen_op_setle_T0_subw,
746 gen_op_setbe_T0_subl,
750 gen_op_setle_T0_subl,
754 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
760 gen_op_fsubr_ST0_FT0,
762 gen_op_fdivr_ST0_FT0,
765 /* NOTE the exception in "r" op ordering */
766 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
771 gen_op_fsubr_STN_ST0,
773 gen_op_fdivr_STN_ST0,
777 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
780 gen_op_mov_TN_reg[ot][0][d]();
782 gen_op_mov_TN_reg[ot][1][s]();
783 if (op == OP_ADCL || op == OP_SBBL) {
784 if (s1->cc_op != CC_OP_DYNAMIC)
785 gen_op_set_cc_op(s1->cc_op);
786 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
787 s1->cc_op = CC_OP_DYNAMIC;
789 gen_op_arith_T0_T1_cc[op]();
790 s1->cc_op = cc_op_arithb[op] + ot;
792 if (d != OR_TMP0 && op != OP_CMPL)
793 gen_op_mov_reg_T0[ot][d]();
796 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
798 gen_op_movl_T1_im(c);
799 gen_op(s1, op, ot, d, OR_TMP1);
802 static void gen_inc(DisasContext *s1, int ot, int d, int c)
805 gen_op_mov_TN_reg[ot][0][d]();
806 if (s1->cc_op != CC_OP_DYNAMIC)
807 gen_op_set_cc_op(s1->cc_op);
810 s1->cc_op = CC_OP_INCB + ot;
813 s1->cc_op = CC_OP_DECB + ot;
816 gen_op_mov_reg_T0[ot][d]();
819 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
822 gen_op_mov_TN_reg[ot][0][d]();
824 gen_op_mov_TN_reg[ot][1][s]();
825 /* for zero counts, flags are not updated, so must do it dynamically */
826 if (s1->cc_op != CC_OP_DYNAMIC)
827 gen_op_set_cc_op(s1->cc_op);
829 gen_op_shift_T0_T1_cc[ot][op]();
832 gen_op_mov_reg_T0[ot][d]();
833 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
836 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
838 /* currently not optimized */
839 gen_op_movl_T1_im(c);
840 gen_shift(s1, op, ot, d, OR_TMP1);
843 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
850 int mod, rm, code, override, must_add_seg;
852 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
854 must_add_seg = s->addseg;
855 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
856 PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
857 if (s->prefix & PREFIX_ES)
859 else if (s->prefix & PREFIX_CS)
861 else if (s->prefix & PREFIX_SS)
863 else if (s->prefix & PREFIX_DS)
865 else if (s->prefix & PREFIX_FS)
872 mod = (modrm >> 6) & 3;
884 code = ldub(s->pc++);
885 scale = (code >> 6) & 3;
886 index = (code >> 3) & 7;
901 disp = (int8_t)ldub(s->pc++);
911 gen_op_movl_A0_reg[base]();
913 gen_op_addl_A0_im(disp);
915 gen_op_movl_A0_im(disp);
917 if (havesib && (index != 4 || scale != 0)) {
918 gen_op_addl_A0_reg_sN[scale][index]();
922 if (base == R_EBP || base == R_ESP)
927 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
935 gen_op_movl_A0_im(disp);
936 rm = 0; /* avoid SS override */
943 disp = (int8_t)ldub(s->pc++);
953 gen_op_movl_A0_reg[R_EBX]();
954 gen_op_addl_A0_reg_sN[0][R_ESI]();
957 gen_op_movl_A0_reg[R_EBX]();
958 gen_op_addl_A0_reg_sN[0][R_EDI]();
961 gen_op_movl_A0_reg[R_EBP]();
962 gen_op_addl_A0_reg_sN[0][R_ESI]();
965 gen_op_movl_A0_reg[R_EBP]();
966 gen_op_addl_A0_reg_sN[0][R_EDI]();
969 gen_op_movl_A0_reg[R_ESI]();
972 gen_op_movl_A0_reg[R_EDI]();
975 gen_op_movl_A0_reg[R_EBP]();
979 gen_op_movl_A0_reg[R_EBX]();
983 gen_op_addl_A0_im(disp);
984 gen_op_andl_A0_ffff();
988 if (rm == 2 || rm == 3 || rm == 6)
993 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1003 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1005 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1007 int mod, rm, opreg, disp;
1009 mod = (modrm >> 6) & 3;
1014 gen_op_mov_TN_reg[ot][0][reg]();
1015 gen_op_mov_reg_T0[ot][rm]();
1017 gen_op_mov_TN_reg[ot][0][rm]();
1019 gen_op_mov_reg_T0[ot][reg]();
1022 gen_lea_modrm(s, modrm, &opreg, &disp);
1025 gen_op_mov_TN_reg[ot][0][reg]();
1026 gen_op_st_T0_A0[ot]();
1028 gen_op_ld_T0_A0[ot]();
1030 gen_op_mov_reg_T0[ot][reg]();
1035 static inline uint32_t insn_get(DisasContext *s, int ot)
1057 static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1063 jcc_op = (b >> 1) & 7;
1065 /* we optimize the cmp/jcc case */
1069 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1074 /* some jumps are easy to compute */
1101 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1104 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1112 if (s->cc_op != CC_OP_DYNAMIC)
1113 gen_op_set_cc_op(s->cc_op);
1114 func = gen_jcc_slow[jcc_op];
1118 func(val, next_eip);
1120 func(next_eip, val);
1124 static void gen_setcc(DisasContext *s, int b)
1130 jcc_op = (b >> 1) & 7;
1132 /* we optimize the cmp/jcc case */
1136 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1141 /* some jumps are easy to compute */
1159 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1162 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1170 if (s->cc_op != CC_OP_DYNAMIC)
1171 gen_op_set_cc_op(s->cc_op);
1172 func = gen_setcc_slow[jcc_op];
1181 /* move T0 to seg_reg and compute if the CPU state may change */
1182 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1184 gen_op_movl_seg_T0(seg_reg);
1185 if (!s->addseg && seg_reg < R_FS)
1186 s->is_jmp = 2; /* abort translation because the register may
1187 have a non zero base */
1190 /* generate a push. It depends on ss32, addseg and dflag */
1191 static void gen_push_T0(DisasContext *s)
1201 gen_op_pushl_ss32_T0();
1203 gen_op_pushw_ss32_T0();
1207 gen_op_pushl_ss16_T0();
1209 gen_op_pushw_ss16_T0();
1213 /* two step pop is necessary for precise exceptions */
1214 static void gen_pop_T0(DisasContext *s)
1224 gen_op_popl_ss32_T0();
1226 gen_op_popw_ss32_T0();
1230 gen_op_popl_ss16_T0();
1232 gen_op_popw_ss16_T0();
1236 static void gen_pop_update(DisasContext *s)
1240 gen_op_addl_ESP_4();
1242 gen_op_addl_ESP_2();
1245 gen_op_addw_ESP_4();
1247 gen_op_addw_ESP_2();
1251 /* NOTE: wrap around in 16 bit not fully handled */
1252 static void gen_pusha(DisasContext *s)
1255 gen_op_movl_A0_ESP();
1256 gen_op_addl_A0_im(-16 << s->dflag);
1258 gen_op_andl_A0_ffff();
1259 gen_op_movl_T1_A0();
1261 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1262 for(i = 0;i < 8; i++) {
1263 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1264 gen_op_st_T0_A0[OT_WORD + s->dflag]();
1265 gen_op_addl_A0_im(2 << s->dflag);
1267 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1270 /* NOTE: wrap around in 16 bit not fully handled */
1271 static void gen_popa(DisasContext *s)
1274 gen_op_movl_A0_ESP();
1276 gen_op_andl_A0_ffff();
1277 gen_op_movl_T1_A0();
1278 gen_op_addl_T1_im(16 << s->dflag);
1280 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1281 for(i = 0;i < 8; i++) {
1282 /* ESP is not reloaded */
1284 gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1285 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1287 gen_op_addl_A0_im(2 << s->dflag);
1289 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1292 /* NOTE: wrap around in 16 bit not fully handled */
1293 /* XXX: check this */
1294 static void gen_enter(DisasContext *s, int esp_addend, int level)
1296 int ot, level1, addend, opsize;
1298 ot = s->dflag + OT_WORD;
1301 opsize = 2 << s->dflag;
1303 gen_op_movl_A0_ESP();
1304 gen_op_addl_A0_im(-opsize);
1306 gen_op_andl_A0_ffff();
1307 gen_op_movl_T1_A0();
1309 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1311 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1312 gen_op_st_T0_A0[ot]();
1315 gen_op_addl_A0_im(-opsize);
1316 gen_op_addl_T0_im(-opsize);
1317 gen_op_st_T0_A0[ot]();
1319 gen_op_addl_A0_im(-opsize);
1320 /* XXX: add st_T1_A0 ? */
1321 gen_op_movl_T0_T1();
1322 gen_op_st_T0_A0[ot]();
1324 gen_op_mov_reg_T1[ot][R_EBP]();
1325 addend = -esp_addend;
1327 addend -= opsize * (level1 + 1);
1328 gen_op_addl_T1_im(addend);
1329 gen_op_mov_reg_T1[ot][R_ESP]();
1332 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1333 is set to true if the instruction sets the PC (last instruction of
1335 long disas_insn(DisasContext *s, uint8_t *pc_start)
1337 int b, prefixes, aflag, dflag;
1339 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1340 unsigned int next_eip;
1346 // cur_pc = s->pc; /* for insn generation */
1350 /* check prefixes */
1353 prefixes |= PREFIX_REPZ;
1356 prefixes |= PREFIX_REPNZ;
1359 prefixes |= PREFIX_LOCK;
1362 prefixes |= PREFIX_CS;
1365 prefixes |= PREFIX_SS;
1368 prefixes |= PREFIX_DS;
1371 prefixes |= PREFIX_ES;
1374 prefixes |= PREFIX_FS;
1377 prefixes |= PREFIX_GS;
1380 prefixes |= PREFIX_DATA;
1383 prefixes |= PREFIX_ADR;
1386 prefixes |= PREFIX_FWAIT;
1390 if (prefixes & PREFIX_DATA)
1392 if (prefixes & PREFIX_ADR)
1395 s->prefix = prefixes;
1399 /* lock generation */
1400 if (prefixes & PREFIX_LOCK)
1403 /* now check op code */
1407 /**************************/
1408 /* extended op code */
1409 b = ldub(s->pc++) | 0x100;
1412 /**************************/
1430 ot = dflag ? OT_LONG : OT_WORD;
1433 case 0: /* OP Ev, Gv */
1434 modrm = ldub(s->pc++);
1435 reg = ((modrm >> 3) & 7) + OR_EAX;
1436 mod = (modrm >> 6) & 3;
1439 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1440 gen_op_ld_T0_A0[ot]();
1443 opreg = OR_EAX + rm;
1445 gen_op(s, op, ot, opreg, reg);
1446 if (mod != 3 && op != 7) {
1447 gen_op_st_T0_A0[ot]();
1450 case 1: /* OP Gv, Ev */
1451 modrm = ldub(s->pc++);
1452 mod = (modrm >> 6) & 3;
1453 reg = ((modrm >> 3) & 7) + OR_EAX;
1456 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1457 gen_op_ld_T1_A0[ot]();
1460 opreg = OR_EAX + rm;
1462 gen_op(s, op, ot, reg, opreg);
1464 case 2: /* OP A, Iv */
1465 val = insn_get(s, ot);
1466 gen_opi(s, op, ot, OR_EAX, val);
1472 case 0x80: /* GRP1 */
1481 ot = dflag ? OT_LONG : OT_WORD;
1483 modrm = ldub(s->pc++);
1484 mod = (modrm >> 6) & 3;
1486 op = (modrm >> 3) & 7;
1489 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1490 gen_op_ld_T0_A0[ot]();
1493 opreg = rm + OR_EAX;
1500 val = insn_get(s, ot);
1503 val = (int8_t)insn_get(s, OT_BYTE);
1507 gen_opi(s, op, ot, opreg, val);
1508 if (op != 7 && mod != 3) {
1509 gen_op_st_T0_A0[ot]();
1514 /**************************/
1515 /* inc, dec, and other misc arith */
1516 case 0x40 ... 0x47: /* inc Gv */
1517 ot = dflag ? OT_LONG : OT_WORD;
1518 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1520 case 0x48 ... 0x4f: /* dec Gv */
1521 ot = dflag ? OT_LONG : OT_WORD;
1522 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1524 case 0xf6: /* GRP3 */
1529 ot = dflag ? OT_LONG : OT_WORD;
1531 modrm = ldub(s->pc++);
1532 mod = (modrm >> 6) & 3;
1534 op = (modrm >> 3) & 7;
1536 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1537 gen_op_ld_T0_A0[ot]();
1539 gen_op_mov_TN_reg[ot][0][rm]();
1544 val = insn_get(s, ot);
1545 gen_op_movl_T1_im(val);
1546 gen_op_testl_T0_T1_cc();
1547 s->cc_op = CC_OP_LOGICB + ot;
1552 gen_op_st_T0_A0[ot]();
1554 gen_op_mov_reg_T0[ot][rm]();
1558 gen_op_negl_T0_cc();
1560 gen_op_st_T0_A0[ot]();
1562 gen_op_mov_reg_T0[ot][rm]();
1564 s->cc_op = CC_OP_SUBB + ot;
1569 gen_op_mulb_AL_T0();
1572 gen_op_mulw_AX_T0();
1576 gen_op_mull_EAX_T0();
1579 s->cc_op = CC_OP_MUL;
1584 gen_op_imulb_AL_T0();
1587 gen_op_imulw_AX_T0();
1591 gen_op_imull_EAX_T0();
1594 s->cc_op = CC_OP_MUL;
1599 gen_op_divb_AL_T0();
1602 gen_op_divw_AX_T0();
1606 gen_op_divl_EAX_T0();
1613 gen_op_idivb_AL_T0();
1616 gen_op_idivw_AX_T0();
1620 gen_op_idivl_EAX_T0();
1629 case 0xfe: /* GRP4 */
1630 case 0xff: /* GRP5 */
1634 ot = dflag ? OT_LONG : OT_WORD;
1636 modrm = ldub(s->pc++);
1637 mod = (modrm >> 6) & 3;
1639 op = (modrm >> 3) & 7;
1640 if (op >= 2 && b == 0xfe) {
1644 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1645 if (op != 3 && op != 5)
1646 gen_op_ld_T0_A0[ot]();
1648 gen_op_mov_TN_reg[ot][0][rm]();
1652 case 0: /* inc Ev */
1653 gen_inc(s, ot, OR_TMP0, 1);
1655 gen_op_st_T0_A0[ot]();
1657 gen_op_mov_reg_T0[ot][rm]();
1659 case 1: /* dec Ev */
1660 gen_inc(s, ot, OR_TMP0, -1);
1662 gen_op_st_T0_A0[ot]();
1664 gen_op_mov_reg_T0[ot][rm]();
1666 case 2: /* call Ev */
1667 /* XXX: optimize if memory (no and is necessary) */
1669 gen_op_andl_T0_ffff();
1671 next_eip = s->pc - s->cs_base;
1672 gen_op_movl_T0_im(next_eip);
1676 case 3: /* lcall Ev */
1677 /* push return segment + offset */
1678 gen_op_movl_T0_seg(R_CS);
1680 next_eip = s->pc - s->cs_base;
1681 gen_op_movl_T0_im(next_eip);
1684 gen_op_ld_T1_A0[ot]();
1685 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1686 gen_op_lduw_T0_A0();
1687 gen_movl_seg_T0(s, R_CS);
1688 gen_op_movl_T0_T1();
1692 case 4: /* jmp Ev */
1694 gen_op_andl_T0_ffff();
1698 case 5: /* ljmp Ev */
1699 gen_op_ld_T1_A0[ot]();
1700 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1701 gen_op_lduw_T0_A0();
1702 gen_movl_seg_T0(s, R_CS);
1703 gen_op_movl_T0_T1();
1707 case 6: /* push Ev */
1715 case 0x84: /* test Ev, Gv */
1720 ot = dflag ? OT_LONG : OT_WORD;
1722 modrm = ldub(s->pc++);
1723 mod = (modrm >> 6) & 3;
1725 reg = (modrm >> 3) & 7;
1727 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1728 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1729 gen_op_testl_T0_T1_cc();
1730 s->cc_op = CC_OP_LOGICB + ot;
1733 case 0xa8: /* test eAX, Iv */
1738 ot = dflag ? OT_LONG : OT_WORD;
1739 val = insn_get(s, ot);
1741 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1742 gen_op_movl_T1_im(val);
1743 gen_op_testl_T0_T1_cc();
1744 s->cc_op = CC_OP_LOGICB + ot;
1747 case 0x98: /* CWDE/CBW */
1749 gen_op_movswl_EAX_AX();
1751 gen_op_movsbw_AX_AL();
1753 case 0x99: /* CDQ/CWD */
1755 gen_op_movslq_EDX_EAX();
1757 gen_op_movswl_DX_AX();
1759 case 0x1af: /* imul Gv, Ev */
1760 case 0x69: /* imul Gv, Ev, I */
1762 ot = dflag ? OT_LONG : OT_WORD;
1763 modrm = ldub(s->pc++);
1764 reg = ((modrm >> 3) & 7) + OR_EAX;
1765 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1767 val = insn_get(s, ot);
1768 gen_op_movl_T1_im(val);
1769 } else if (b == 0x6b) {
1770 val = insn_get(s, OT_BYTE);
1771 gen_op_movl_T1_im(val);
1773 gen_op_mov_TN_reg[ot][1][reg]();
1776 if (ot == OT_LONG) {
1777 gen_op_imull_T0_T1();
1779 gen_op_imulw_T0_T1();
1781 gen_op_mov_reg_T0[ot][reg]();
1782 s->cc_op = CC_OP_MUL;
1785 case 0x1c1: /* xadd Ev, Gv */
1789 ot = dflag ? OT_LONG : OT_WORD;
1790 modrm = ldub(s->pc++);
1791 reg = (modrm >> 3) & 7;
1792 mod = (modrm >> 6) & 3;
1795 gen_op_mov_TN_reg[ot][0][reg]();
1796 gen_op_mov_TN_reg[ot][1][rm]();
1797 gen_op_addl_T0_T1_cc();
1798 gen_op_mov_reg_T0[ot][rm]();
1799 gen_op_mov_reg_T1[ot][reg]();
1801 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1802 gen_op_mov_TN_reg[ot][0][reg]();
1803 gen_op_ld_T1_A0[ot]();
1804 gen_op_addl_T0_T1_cc();
1805 gen_op_st_T0_A0[ot]();
1806 gen_op_mov_reg_T1[ot][reg]();
1808 s->cc_op = CC_OP_ADDB + ot;
1811 case 0x1b1: /* cmpxchg Ev, Gv */
1815 ot = dflag ? OT_LONG : OT_WORD;
1816 modrm = ldub(s->pc++);
1817 reg = (modrm >> 3) & 7;
1818 mod = (modrm >> 6) & 3;
1819 gen_op_mov_TN_reg[ot][1][reg]();
1822 gen_op_mov_TN_reg[ot][0][rm]();
1823 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1824 gen_op_mov_reg_T0[ot][rm]();
1826 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1827 gen_op_ld_T0_A0[ot]();
1828 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1829 gen_op_st_T0_A0[ot]();
1831 s->cc_op = CC_OP_SUBB + ot;
1834 /**************************/
1836 case 0x50 ... 0x57: /* push */
1837 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1840 case 0x58 ... 0x5f: /* pop */
1841 ot = dflag ? OT_LONG : OT_WORD;
1843 gen_op_mov_reg_T0[ot][b & 7]();
1846 case 0x60: /* pusha */
1849 case 0x61: /* popa */
1852 case 0x68: /* push Iv */
1854 ot = dflag ? OT_LONG : OT_WORD;
1856 val = insn_get(s, ot);
1858 val = (int8_t)insn_get(s, OT_BYTE);
1859 gen_op_movl_T0_im(val);
1862 case 0x8f: /* pop Ev */
1863 ot = dflag ? OT_LONG : OT_WORD;
1864 modrm = ldub(s->pc++);
1866 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1869 case 0xc8: /* enter */
1874 level = ldub(s->pc++);
1875 gen_enter(s, val, level);
1878 case 0xc9: /* leave */
1879 /* XXX: exception not precise (ESP is update before potential exception) */
1881 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1882 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1884 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1885 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1888 ot = dflag ? OT_LONG : OT_WORD;
1889 gen_op_mov_reg_T0[ot][R_EBP]();
1892 case 0x06: /* push es */
1893 case 0x0e: /* push cs */
1894 case 0x16: /* push ss */
1895 case 0x1e: /* push ds */
1896 gen_op_movl_T0_seg(b >> 3);
1899 case 0x1a0: /* push fs */
1900 case 0x1a8: /* push gs */
1901 gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
1904 case 0x07: /* pop es */
1905 case 0x17: /* pop ss */
1906 case 0x1f: /* pop ds */
1908 gen_movl_seg_T0(s, b >> 3);
1911 case 0x1a1: /* pop fs */
1912 case 0x1a9: /* pop gs */
1914 gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
1918 /**************************/
1921 case 0x89: /* mov Gv, Ev */
1925 ot = dflag ? OT_LONG : OT_WORD;
1926 modrm = ldub(s->pc++);
1927 reg = (modrm >> 3) & 7;
1929 /* generate a generic store */
1930 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1933 case 0xc7: /* mov Ev, Iv */
1937 ot = dflag ? OT_LONG : OT_WORD;
1938 modrm = ldub(s->pc++);
1939 mod = (modrm >> 6) & 3;
1941 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1942 val = insn_get(s, ot);
1943 gen_op_movl_T0_im(val);
1945 gen_op_st_T0_A0[ot]();
1947 gen_op_mov_reg_T0[ot][modrm & 7]();
1950 case 0x8b: /* mov Ev, Gv */
1954 ot = dflag ? OT_LONG : OT_WORD;
1955 modrm = ldub(s->pc++);
1956 reg = (modrm >> 3) & 7;
1958 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1959 gen_op_mov_reg_T0[ot][reg]();
1961 case 0x8e: /* mov seg, Gv */
1962 ot = dflag ? OT_LONG : OT_WORD;
1963 modrm = ldub(s->pc++);
1964 reg = (modrm >> 3) & 7;
1965 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1966 if (reg >= 6 || reg == R_CS)
1968 gen_movl_seg_T0(s, reg);
1970 case 0x8c: /* mov Gv, seg */
1971 ot = dflag ? OT_LONG : OT_WORD;
1972 modrm = ldub(s->pc++);
1973 reg = (modrm >> 3) & 7;
1976 gen_op_movl_T0_seg(reg);
1977 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1980 case 0x1b6: /* movzbS Gv, Eb */
1981 case 0x1b7: /* movzwS Gv, Eb */
1982 case 0x1be: /* movsbS Gv, Eb */
1983 case 0x1bf: /* movswS Gv, Eb */
1986 /* d_ot is the size of destination */
1987 d_ot = dflag + OT_WORD;
1988 /* ot is the size of source */
1989 ot = (b & 1) + OT_BYTE;
1990 modrm = ldub(s->pc++);
1991 reg = ((modrm >> 3) & 7) + OR_EAX;
1992 mod = (modrm >> 6) & 3;
1996 gen_op_mov_TN_reg[ot][0][rm]();
1997 switch(ot | (b & 8)) {
1999 gen_op_movzbl_T0_T0();
2002 gen_op_movsbl_T0_T0();
2005 gen_op_movzwl_T0_T0();
2009 gen_op_movswl_T0_T0();
2012 gen_op_mov_reg_T0[d_ot][reg]();
2014 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2016 gen_op_lds_T0_A0[ot]();
2018 gen_op_ldu_T0_A0[ot]();
2020 gen_op_mov_reg_T0[d_ot][reg]();
2025 case 0x8d: /* lea */
2026 ot = dflag ? OT_LONG : OT_WORD;
2027 modrm = ldub(s->pc++);
2028 reg = (modrm >> 3) & 7;
2029 /* we must ensure that no segment is added */
2030 s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS |
2031 PREFIX_ES | PREFIX_FS | PREFIX_GS);
2034 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2036 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2039 case 0xa0: /* mov EAX, Ov */
2041 case 0xa2: /* mov Ov, EAX */
2046 ot = dflag ? OT_LONG : OT_WORD;
2048 offset_addr = insn_get(s, OT_LONG);
2050 offset_addr = insn_get(s, OT_WORD);
2051 gen_op_movl_A0_im(offset_addr);
2052 /* handle override */
2053 /* XXX: factorize that */
2055 int override, must_add_seg;
2057 must_add_seg = s->addseg;
2058 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
2059 PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
2060 if (s->prefix & PREFIX_ES)
2062 else if (s->prefix & PREFIX_CS)
2064 else if (s->prefix & PREFIX_SS)
2066 else if (s->prefix & PREFIX_DS)
2068 else if (s->prefix & PREFIX_FS)
2075 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2079 gen_op_ld_T0_A0[ot]();
2080 gen_op_mov_reg_T0[ot][R_EAX]();
2082 gen_op_mov_TN_reg[ot][0][R_EAX]();
2083 gen_op_st_T0_A0[ot]();
2087 case 0xb0 ... 0xb7: /* mov R, Ib */
2088 val = insn_get(s, OT_BYTE);
2089 gen_op_movl_T0_im(val);
2090 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2092 case 0xb8 ... 0xbf: /* mov R, Iv */
2093 ot = dflag ? OT_LONG : OT_WORD;
2094 val = insn_get(s, ot);
2095 reg = OR_EAX + (b & 7);
2096 gen_op_movl_T0_im(val);
2097 gen_op_mov_reg_T0[ot][reg]();
2100 case 0x91 ... 0x97: /* xchg R, EAX */
2101 ot = dflag ? OT_LONG : OT_WORD;
2106 case 0x87: /* xchg Ev, Gv */
2110 ot = dflag ? OT_LONG : OT_WORD;
2111 modrm = ldub(s->pc++);
2112 reg = (modrm >> 3) & 7;
2113 mod = (modrm >> 6) & 3;
2117 gen_op_mov_TN_reg[ot][0][reg]();
2118 gen_op_mov_TN_reg[ot][1][rm]();
2119 gen_op_mov_reg_T0[ot][rm]();
2120 gen_op_mov_reg_T1[ot][reg]();
2122 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2123 gen_op_mov_TN_reg[ot][0][reg]();
2124 gen_op_ld_T1_A0[ot]();
2125 gen_op_st_T0_A0[ot]();
2126 gen_op_mov_reg_T1[ot][reg]();
2129 case 0xc4: /* les Gv */
2132 case 0xc5: /* lds Gv */
2135 case 0x1b2: /* lss Gv */
2138 case 0x1b4: /* lfs Gv */
2141 case 0x1b5: /* lgs Gv */
2144 ot = dflag ? OT_LONG : OT_WORD;
2145 modrm = ldub(s->pc++);
2146 reg = (modrm >> 3) & 7;
2147 mod = (modrm >> 6) & 3;
2150 gen_op_ld_T1_A0[ot]();
2151 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2152 /* load the segment first to handle exceptions properly */
2153 gen_op_lduw_T0_A0();
2154 gen_movl_seg_T0(s, op);
2155 /* then put the data */
2156 gen_op_mov_reg_T1[ot][reg]();
2159 /************************/
2170 ot = dflag ? OT_LONG : OT_WORD;
2172 modrm = ldub(s->pc++);
2173 mod = (modrm >> 6) & 3;
2175 op = (modrm >> 3) & 7;
2178 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2179 gen_op_ld_T0_A0[ot]();
2182 opreg = rm + OR_EAX;
2187 gen_shift(s, op, ot, opreg, OR_ECX);
2190 shift = ldub(s->pc++);
2192 gen_shifti(s, op, ot, opreg, shift);
2196 gen_op_st_T0_A0[ot]();
2211 case 0x1a4: /* shld imm */
2215 case 0x1a5: /* shld cl */
2219 case 0x1ac: /* shrd imm */
2223 case 0x1ad: /* shrd cl */
2227 ot = dflag ? OT_LONG : OT_WORD;
2228 modrm = ldub(s->pc++);
2229 mod = (modrm >> 6) & 3;
2231 reg = (modrm >> 3) & 7;
2234 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2235 gen_op_ld_T0_A0[ot]();
2237 gen_op_mov_TN_reg[ot][0][rm]();
2239 gen_op_mov_TN_reg[ot][1][reg]();
2242 val = ldub(s->pc++);
2245 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2246 if (op == 0 && ot != OT_WORD)
2247 s->cc_op = CC_OP_SHLB + ot;
2249 s->cc_op = CC_OP_SARB + ot;
2252 if (s->cc_op != CC_OP_DYNAMIC)
2253 gen_op_set_cc_op(s->cc_op);
2254 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2255 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2258 gen_op_st_T0_A0[ot]();
2260 gen_op_mov_reg_T0[ot][rm]();
2264 /************************/
2267 modrm = ldub(s->pc++);
2268 mod = (modrm >> 6) & 3;
2270 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2274 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2276 case 0x00 ... 0x07: /* fxxxs */
2277 case 0x10 ... 0x17: /* fixxxl */
2278 case 0x20 ... 0x27: /* fxxxl */
2279 case 0x30 ... 0x37: /* fixxx */
2286 gen_op_flds_FT0_A0();
2289 gen_op_fildl_FT0_A0();
2292 gen_op_fldl_FT0_A0();
2296 gen_op_fild_FT0_A0();
2300 gen_op_fp_arith_ST0_FT0[op1]();
2302 /* fcomp needs pop */
2307 case 0x08: /* flds */
2308 case 0x0a: /* fsts */
2309 case 0x0b: /* fstps */
2310 case 0x18: /* fildl */
2311 case 0x1a: /* fistl */
2312 case 0x1b: /* fistpl */
2313 case 0x28: /* fldl */
2314 case 0x2a: /* fstl */
2315 case 0x2b: /* fstpl */
2316 case 0x38: /* filds */
2317 case 0x3a: /* fists */
2318 case 0x3b: /* fistps */
2325 gen_op_flds_ST0_A0();
2328 gen_op_fildl_ST0_A0();
2331 gen_op_fldl_ST0_A0();
2335 gen_op_fild_ST0_A0();
2342 gen_op_fsts_ST0_A0();
2345 gen_op_fistl_ST0_A0();
2348 gen_op_fstl_ST0_A0();
2352 gen_op_fist_ST0_A0();
2360 case 0x0d: /* fldcw mem */
2363 case 0x0f: /* fnstcw mem */
2366 case 0x1d: /* fldt mem */
2368 gen_op_fldt_ST0_A0();
2370 case 0x1f: /* fstpt mem */
2371 gen_op_fstt_ST0_A0();
2374 case 0x2f: /* fnstsw mem */
2377 case 0x3c: /* fbld */
2379 gen_op_fbld_ST0_A0();
2381 case 0x3e: /* fbstp */
2382 gen_op_fbst_ST0_A0();
2385 case 0x3d: /* fildll */
2387 gen_op_fildll_ST0_A0();
2389 case 0x3f: /* fistpll */
2390 gen_op_fistll_ST0_A0();
2397 /* register float ops */
2401 case 0x08: /* fld sti */
2403 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2405 case 0x09: /* fxchg sti */
2406 gen_op_fxchg_ST0_STN(opreg);
2408 case 0x0a: /* grp d9/2 */
2416 case 0x0c: /* grp d9/4 */
2426 gen_op_fcom_ST0_FT0();
2435 case 0x0d: /* grp d9/5 */
2444 gen_op_fldl2t_ST0();
2448 gen_op_fldl2e_ST0();
2456 gen_op_fldlg2_ST0();
2460 gen_op_fldln2_ST0();
2471 case 0x0e: /* grp d9/6 */
2482 case 3: /* fpatan */
2485 case 4: /* fxtract */
2488 case 5: /* fprem1 */
2491 case 6: /* fdecstp */
2495 case 7: /* fincstp */
2500 case 0x0f: /* grp d9/7 */
2505 case 1: /* fyl2xp1 */
2511 case 3: /* fsincos */
2514 case 5: /* fscale */
2517 case 4: /* frndint */
2529 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2530 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2531 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2537 gen_op_fp_arith_STN_ST0[op1](opreg);
2541 gen_op_fmov_FT0_STN(opreg);
2542 gen_op_fp_arith_ST0_FT0[op1]();
2546 case 0x02: /* fcom */
2547 gen_op_fmov_FT0_STN(opreg);
2548 gen_op_fcom_ST0_FT0();
2550 case 0x03: /* fcomp */
2551 gen_op_fmov_FT0_STN(opreg);
2552 gen_op_fcom_ST0_FT0();
2555 case 0x15: /* da/5 */
2557 case 1: /* fucompp */
2558 gen_op_fmov_FT0_STN(1);
2559 gen_op_fucom_ST0_FT0();
2572 case 3: /* fninit */
2579 case 0x2a: /* fst sti */
2580 gen_op_fmov_STN_ST0(opreg);
2582 case 0x2b: /* fstp sti */
2583 gen_op_fmov_STN_ST0(opreg);
2586 case 0x2c: /* fucom st(i) */
2587 gen_op_fmov_FT0_STN(opreg);
2588 gen_op_fucom_ST0_FT0();
2590 case 0x2d: /* fucomp st(i) */
2591 gen_op_fmov_FT0_STN(opreg);
2592 gen_op_fucom_ST0_FT0();
2595 case 0x33: /* de/3 */
2597 case 1: /* fcompp */
2598 gen_op_fmov_FT0_STN(1);
2599 gen_op_fcom_ST0_FT0();
2607 case 0x3c: /* df/4 */
2610 gen_op_fnstsw_EAX();
2621 /************************/
2623 case 0xa4: /* movsS */
2628 ot = dflag ? OT_LONG : OT_WORD;
2629 if (prefixes & PREFIX_REPZ) {
2630 gen_op_movs[3 + ot]();
2636 case 0xaa: /* stosS */
2641 ot = dflag ? OT_LONG : OT_WORD;
2642 if (prefixes & PREFIX_REPZ) {
2643 gen_op_stos[3 + ot]();
2648 case 0xac: /* lodsS */
2653 ot = dflag ? OT_LONG : OT_WORD;
2654 if (prefixes & PREFIX_REPZ) {
2655 gen_op_lods[3 + ot]();
2660 case 0xae: /* scasS */
2665 ot = dflag ? OT_LONG : OT_WORD;
2666 if (prefixes & PREFIX_REPNZ) {
2667 if (s->cc_op != CC_OP_DYNAMIC)
2668 gen_op_set_cc_op(s->cc_op);
2669 gen_op_scas[6 + ot]();
2670 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2671 } else if (prefixes & PREFIX_REPZ) {
2672 if (s->cc_op != CC_OP_DYNAMIC)
2673 gen_op_set_cc_op(s->cc_op);
2674 gen_op_scas[3 + ot]();
2675 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2678 s->cc_op = CC_OP_SUBB + ot;
2682 case 0xa6: /* cmpsS */
2687 ot = dflag ? OT_LONG : OT_WORD;
2688 if (prefixes & PREFIX_REPNZ) {
2689 if (s->cc_op != CC_OP_DYNAMIC)
2690 gen_op_set_cc_op(s->cc_op);
2691 gen_op_cmps[6 + ot]();
2692 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2693 } else if (prefixes & PREFIX_REPZ) {
2694 if (s->cc_op != CC_OP_DYNAMIC)
2695 gen_op_set_cc_op(s->cc_op);
2696 gen_op_cmps[3 + ot]();
2697 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2700 s->cc_op = CC_OP_SUBB + ot;
2704 /************************/
2706 case 0x6c: /* insS */
2711 ot = dflag ? OT_LONG : OT_WORD;
2712 if (prefixes & PREFIX_REPZ) {
2713 gen_op_ins[3 + ot]();
2718 case 0x6e: /* outsS */
2723 ot = dflag ? OT_LONG : OT_WORD;
2724 if (prefixes & PREFIX_REPZ) {
2725 gen_op_outs[3 + ot]();
2735 ot = dflag ? OT_LONG : OT_WORD;
2736 val = ldub(s->pc++);
2737 gen_op_movl_T0_im(val);
2739 gen_op_mov_reg_T1[ot][R_EAX]();
2746 ot = dflag ? OT_LONG : OT_WORD;
2747 val = ldub(s->pc++);
2748 gen_op_movl_T0_im(val);
2749 gen_op_mov_TN_reg[ot][1][R_EAX]();
2757 ot = dflag ? OT_LONG : OT_WORD;
2758 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2760 gen_op_mov_reg_T1[ot][R_EAX]();
2767 ot = dflag ? OT_LONG : OT_WORD;
2768 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2769 gen_op_mov_TN_reg[ot][1][R_EAX]();
2773 /************************/
2775 case 0xc2: /* ret im */
2780 gen_op_addl_ESP_im(val + (2 << s->dflag));
2782 gen_op_addw_ESP_im(val + (2 << s->dflag));
2784 gen_op_andl_T0_ffff();
2788 case 0xc3: /* ret */
2792 gen_op_andl_T0_ffff();
2796 case 0xca: /* lret im */
2802 gen_op_andl_T0_ffff();
2807 gen_movl_seg_T0(s, R_CS);
2809 /* add stack offset */
2811 gen_op_addl_ESP_im(val + (2 << s->dflag));
2813 gen_op_addw_ESP_im(val + (2 << s->dflag));
2816 case 0xcb: /* lret */
2820 gen_op_andl_T0_ffff();
2825 gen_movl_seg_T0(s, R_CS);
2829 case 0xe8: /* call im */
2831 unsigned int next_eip;
2832 ot = dflag ? OT_LONG : OT_WORD;
2833 val = insn_get(s, ot);
2834 next_eip = s->pc - s->cs_base;
2838 gen_op_movl_T0_im(next_eip);
2844 case 0x9a: /* lcall im */
2846 unsigned int selector, offset;
2848 ot = dflag ? OT_LONG : OT_WORD;
2849 offset = insn_get(s, ot);
2850 selector = insn_get(s, OT_WORD);
2852 /* push return segment + offset */
2853 gen_op_movl_T0_seg(R_CS);
2855 next_eip = s->pc - s->cs_base;
2856 gen_op_movl_T0_im(next_eip);
2859 /* change cs and pc */
2860 gen_op_movl_T0_im(selector);
2861 gen_movl_seg_T0(s, R_CS);
2862 gen_op_jmp_im((unsigned long)offset);
2866 case 0xe9: /* jmp */
2867 ot = dflag ? OT_LONG : OT_WORD;
2868 val = insn_get(s, ot);
2869 val += s->pc - s->cs_base;
2875 case 0xea: /* ljmp im */
2877 unsigned int selector, offset;
2879 ot = dflag ? OT_LONG : OT_WORD;
2880 offset = insn_get(s, ot);
2881 selector = insn_get(s, OT_WORD);
2883 /* change cs and pc */
2884 gen_op_movl_T0_im(selector);
2885 gen_movl_seg_T0(s, R_CS);
2886 gen_op_jmp_im((unsigned long)offset);
2890 case 0xeb: /* jmp Jb */
2891 val = (int8_t)insn_get(s, OT_BYTE);
2892 val += s->pc - s->cs_base;
2898 case 0x70 ... 0x7f: /* jcc Jb */
2899 val = (int8_t)insn_get(s, OT_BYTE);
2901 case 0x180 ... 0x18f: /* jcc Jv */
2903 val = insn_get(s, OT_LONG);
2905 val = (int16_t)insn_get(s, OT_WORD);
2908 next_eip = s->pc - s->cs_base;
2912 gen_jcc(s, b, val, next_eip);
2916 case 0x190 ... 0x19f: /* setcc Gv */
2917 modrm = ldub(s->pc++);
2919 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2921 case 0x140 ... 0x14f: /* cmov Gv, Ev */
2922 ot = dflag ? OT_LONG : OT_WORD;
2923 modrm = ldub(s->pc++);
2924 reg = (modrm >> 3) & 7;
2925 mod = (modrm >> 6) & 3;
2928 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2929 gen_op_ld_T1_A0[ot]();
2932 gen_op_mov_TN_reg[ot][1][rm]();
2934 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
2937 /************************/
2939 case 0x9c: /* pushf */
2940 if (s->cc_op != CC_OP_DYNAMIC)
2941 gen_op_set_cc_op(s->cc_op);
2942 gen_op_movl_T0_eflags();
2945 case 0x9d: /* popf */
2947 gen_op_movl_eflags_T0();
2949 s->cc_op = CC_OP_EFLAGS;
2951 case 0x9e: /* sahf */
2952 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2953 if (s->cc_op != CC_OP_DYNAMIC)
2954 gen_op_set_cc_op(s->cc_op);
2955 gen_op_movb_eflags_T0();
2956 s->cc_op = CC_OP_EFLAGS;
2958 case 0x9f: /* lahf */
2959 if (s->cc_op != CC_OP_DYNAMIC)
2960 gen_op_set_cc_op(s->cc_op);
2961 gen_op_movl_T0_eflags();
2962 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2964 case 0xf5: /* cmc */
2965 if (s->cc_op != CC_OP_DYNAMIC)
2966 gen_op_set_cc_op(s->cc_op);
2968 s->cc_op = CC_OP_EFLAGS;
2970 case 0xf8: /* clc */
2971 if (s->cc_op != CC_OP_DYNAMIC)
2972 gen_op_set_cc_op(s->cc_op);
2974 s->cc_op = CC_OP_EFLAGS;
2976 case 0xf9: /* stc */
2977 if (s->cc_op != CC_OP_DYNAMIC)
2978 gen_op_set_cc_op(s->cc_op);
2980 s->cc_op = CC_OP_EFLAGS;
2982 case 0xfc: /* cld */
2985 case 0xfd: /* std */
2989 /************************/
2990 /* bit operations */
2991 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2992 ot = dflag ? OT_LONG : OT_WORD;
2993 modrm = ldub(s->pc++);
2994 op = (modrm >> 3) & 7;
2995 mod = (modrm >> 6) & 3;
2998 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2999 gen_op_ld_T0_A0[ot]();
3001 gen_op_mov_TN_reg[ot][0][rm]();
3004 val = ldub(s->pc++);
3005 gen_op_movl_T1_im(val);
3009 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3010 s->cc_op = CC_OP_SARB + ot;
3013 gen_op_st_T0_A0[ot]();
3015 gen_op_mov_reg_T0[ot][rm]();
3018 case 0x1a3: /* bt Gv, Ev */
3021 case 0x1ab: /* bts */
3024 case 0x1b3: /* btr */
3027 case 0x1bb: /* btc */
3030 ot = dflag ? OT_LONG : OT_WORD;
3031 modrm = ldub(s->pc++);
3032 reg = (modrm >> 3) & 7;
3033 mod = (modrm >> 6) & 3;
3035 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3037 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3038 /* specific case: we need to add a displacement */
3040 gen_op_add_bitw_A0_T1();
3042 gen_op_add_bitl_A0_T1();
3043 gen_op_ld_T0_A0[ot]();
3045 gen_op_mov_TN_reg[ot][0][rm]();
3047 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3048 s->cc_op = CC_OP_SARB + ot;
3051 gen_op_st_T0_A0[ot]();
3053 gen_op_mov_reg_T0[ot][rm]();
3056 case 0x1bc: /* bsf */
3057 case 0x1bd: /* bsr */
3058 ot = dflag ? OT_LONG : OT_WORD;
3059 modrm = ldub(s->pc++);
3060 reg = (modrm >> 3) & 7;
3061 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3062 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3063 /* NOTE: we always write back the result. Intel doc says it is
3064 undefined if T0 == 0 */
3065 gen_op_mov_reg_T0[ot][reg]();
3066 s->cc_op = CC_OP_LOGICB + ot;
3068 /************************/
3070 case 0x27: /* daa */
3071 if (s->cc_op != CC_OP_DYNAMIC)
3072 gen_op_set_cc_op(s->cc_op);
3074 s->cc_op = CC_OP_EFLAGS;
3076 case 0x2f: /* das */
3077 if (s->cc_op != CC_OP_DYNAMIC)
3078 gen_op_set_cc_op(s->cc_op);
3080 s->cc_op = CC_OP_EFLAGS;
3082 case 0x37: /* aaa */
3083 if (s->cc_op != CC_OP_DYNAMIC)
3084 gen_op_set_cc_op(s->cc_op);
3086 s->cc_op = CC_OP_EFLAGS;
3088 case 0x3f: /* aas */
3089 if (s->cc_op != CC_OP_DYNAMIC)
3090 gen_op_set_cc_op(s->cc_op);
3092 s->cc_op = CC_OP_EFLAGS;
3094 case 0xd4: /* aam */
3095 val = ldub(s->pc++);
3097 s->cc_op = CC_OP_LOGICB;
3099 case 0xd5: /* aad */
3100 val = ldub(s->pc++);
3102 s->cc_op = CC_OP_LOGICB;
3104 /************************/
3106 case 0x90: /* nop */
3108 case 0xcc: /* int3 */
3109 gen_op_int3((long)pc_start);
3112 case 0xcd: /* int N */
3113 val = ldub(s->pc++);
3114 /* XXX: currently we ignore the interrupt number */
3115 gen_op_int_im((long)pc_start);
3118 case 0xce: /* into */
3119 if (s->cc_op != CC_OP_DYNAMIC)
3120 gen_op_set_cc_op(s->cc_op);
3121 gen_op_into((long)pc_start, (long)s->pc);
3124 case 0x1c8 ... 0x1cf: /* bswap reg */
3126 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3128 gen_op_mov_reg_T0[OT_LONG][reg]();
3130 case 0xd6: /* salc */
3131 if (s->cc_op != CC_OP_DYNAMIC)
3132 gen_op_set_cc_op(s->cc_op);
3135 case 0xe0: /* loopnz */
3136 case 0xe1: /* loopz */
3137 if (s->cc_op != CC_OP_DYNAMIC)
3138 gen_op_set_cc_op(s->cc_op);
3140 case 0xe2: /* loop */
3141 case 0xe3: /* jecxz */
3142 val = (int8_t)insn_get(s, OT_BYTE);
3143 next_eip = s->pc - s->cs_base;
3147 gen_op_loop[s->aflag][b & 3](val, next_eip);
3150 case 0x131: /* rdtsc */
3154 case 0x1a2: /* cpuid */
3161 /* lock generation */
3162 if (s->prefix & PREFIX_LOCK)
3166 /* XXX: ensure that no lock was generated */
3170 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3171 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3173 /* flags read by an operation */
3174 static uint16_t opc_read_flags[NB_OPS] = {
3175 [INDEX_op_aas] = CC_A,
3176 [INDEX_op_aaa] = CC_A,
3177 [INDEX_op_das] = CC_A | CC_C,
3178 [INDEX_op_daa] = CC_A | CC_C,
3180 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3181 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3182 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3183 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3184 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3185 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3187 [INDEX_op_into] = CC_O,
3189 [INDEX_op_jo_cc] = CC_O,
3190 [INDEX_op_jb_cc] = CC_C,
3191 [INDEX_op_jz_cc] = CC_Z,
3192 [INDEX_op_jbe_cc] = CC_Z | CC_C,
3193 [INDEX_op_js_cc] = CC_S,
3194 [INDEX_op_jp_cc] = CC_P,
3195 [INDEX_op_jl_cc] = CC_O | CC_S,
3196 [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
3198 [INDEX_op_jb_subb] = CC_C,
3199 [INDEX_op_jb_subw] = CC_C,
3200 [INDEX_op_jb_subl] = CC_C,
3202 [INDEX_op_jz_subb] = CC_Z,
3203 [INDEX_op_jz_subw] = CC_Z,
3204 [INDEX_op_jz_subl] = CC_Z,
3206 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3207 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3208 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3210 [INDEX_op_js_subb] = CC_S,
3211 [INDEX_op_js_subw] = CC_S,
3212 [INDEX_op_js_subl] = CC_S,
3214 [INDEX_op_jl_subb] = CC_O | CC_S,
3215 [INDEX_op_jl_subw] = CC_O | CC_S,
3216 [INDEX_op_jl_subl] = CC_O | CC_S,
3218 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3219 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3220 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3222 [INDEX_op_loopnzw] = CC_Z,
3223 [INDEX_op_loopnzl] = CC_Z,
3224 [INDEX_op_loopzw] = CC_Z,
3225 [INDEX_op_loopzl] = CC_Z,
3227 [INDEX_op_seto_T0_cc] = CC_O,
3228 [INDEX_op_setb_T0_cc] = CC_C,
3229 [INDEX_op_setz_T0_cc] = CC_Z,
3230 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3231 [INDEX_op_sets_T0_cc] = CC_S,
3232 [INDEX_op_setp_T0_cc] = CC_P,
3233 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3234 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3236 [INDEX_op_setb_T0_subb] = CC_C,
3237 [INDEX_op_setb_T0_subw] = CC_C,
3238 [INDEX_op_setb_T0_subl] = CC_C,
3240 [INDEX_op_setz_T0_subb] = CC_Z,
3241 [INDEX_op_setz_T0_subw] = CC_Z,
3242 [INDEX_op_setz_T0_subl] = CC_Z,
3244 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3245 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3246 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3248 [INDEX_op_sets_T0_subb] = CC_S,
3249 [INDEX_op_sets_T0_subw] = CC_S,
3250 [INDEX_op_sets_T0_subl] = CC_S,
3252 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3253 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3254 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3256 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3257 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3258 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3260 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3261 [INDEX_op_cmc] = CC_C,
3262 [INDEX_op_salc] = CC_C,
3264 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3265 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3266 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3267 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3268 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3269 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3272 /* flags written by an operation */
3273 static uint16_t opc_write_flags[NB_OPS] = {
3274 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3275 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3276 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3277 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3278 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3279 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3280 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3281 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3282 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3283 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3284 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3285 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3286 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3287 [INDEX_op_incl_T0_cc] = CC_OSZAP,
3288 [INDEX_op_decl_T0_cc] = CC_OSZAP,
3289 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3291 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3292 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3293 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3294 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3295 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3296 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3297 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3298 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3301 [INDEX_op_aam] = CC_OSZAPC,
3302 [INDEX_op_aad] = CC_OSZAPC,
3303 [INDEX_op_aas] = CC_OSZAPC,
3304 [INDEX_op_aaa] = CC_OSZAPC,
3305 [INDEX_op_das] = CC_OSZAPC,
3306 [INDEX_op_daa] = CC_OSZAPC,
3308 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3309 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3310 [INDEX_op_clc] = CC_C,
3311 [INDEX_op_stc] = CC_C,
3312 [INDEX_op_cmc] = CC_C,
3314 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3315 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3316 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3317 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3318 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3319 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3321 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3322 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3323 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3324 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3325 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3326 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3328 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3329 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3330 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3332 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3333 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3334 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3336 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3337 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3338 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3340 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3341 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3342 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3343 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3345 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3346 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3347 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3348 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3350 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3351 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3352 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3353 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3354 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3355 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3356 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3357 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3359 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3360 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3361 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3362 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3364 [INDEX_op_scasb] = CC_OSZAPC,
3365 [INDEX_op_scasw] = CC_OSZAPC,
3366 [INDEX_op_scasl] = CC_OSZAPC,
3367 [INDEX_op_repz_scasb] = CC_OSZAPC,
3368 [INDEX_op_repz_scasw] = CC_OSZAPC,
3369 [INDEX_op_repz_scasl] = CC_OSZAPC,
3370 [INDEX_op_repnz_scasb] = CC_OSZAPC,
3371 [INDEX_op_repnz_scasw] = CC_OSZAPC,
3372 [INDEX_op_repnz_scasl] = CC_OSZAPC,
3374 [INDEX_op_cmpsb] = CC_OSZAPC,
3375 [INDEX_op_cmpsw] = CC_OSZAPC,
3376 [INDEX_op_cmpsl] = CC_OSZAPC,
3377 [INDEX_op_repz_cmpsb] = CC_OSZAPC,
3378 [INDEX_op_repz_cmpsw] = CC_OSZAPC,
3379 [INDEX_op_repz_cmpsl] = CC_OSZAPC,
3380 [INDEX_op_repnz_cmpsb] = CC_OSZAPC,
3381 [INDEX_op_repnz_cmpsw] = CC_OSZAPC,
3382 [INDEX_op_repnz_cmpsl] = CC_OSZAPC,
3384 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3385 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3388 /* simpler form of an operation if no flags need to be generated */
3389 static uint16_t opc_simpler[NB_OPS] = {
3390 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3391 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3392 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3393 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3394 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3395 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3396 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3397 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3399 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3400 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3401 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3403 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3404 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3405 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3407 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3408 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3409 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3411 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3412 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3413 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3415 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3416 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3417 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3420 static void optimize_flags_init(void)
3423 /* put default values in arrays */
3424 for(i = 0; i < NB_OPS; i++) {
3425 if (opc_simpler[i] == 0)
3430 /* CPU flags computation optimization: we move backward thru the
3431 generated code to see which flags are needed. The operation is
3432 modified if suitable */
3433 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3436 int live_flags, write_flags, op;
3438 opc_ptr = opc_buf + opc_buf_len;
3439 /* live_flags contains the flags needed by the next instructions
3440 in the code. At the end of the bloc, we consider that all the
3442 live_flags = CC_OSZAPC;
3443 while (opc_ptr > opc_buf) {
3445 /* if none of the flags written by the instruction is used,
3446 then we can try to find a simpler instruction */
3447 write_flags = opc_write_flags[op];
3448 if ((live_flags & write_flags) == 0) {
3449 *opc_ptr = opc_simpler[op];
3451 /* compute the live flags before the instruction */
3452 live_flags &= ~write_flags;
3453 live_flags |= opc_read_flags[op];
3459 static const char *op_str[] = {
3461 #include "opc-i386.h"
3465 static void dump_ops(const uint16_t *opc_buf)
3467 const uint16_t *opc_ptr;
3472 fprintf(logfile, "0x%04x: %s\n", opc_ptr - opc_buf - 1, op_str[c]);
3473 if (c == INDEX_op_end)
3480 /* XXX: make this buffer thread safe */
3481 /* XXX: make safe guess about sizes */
3482 #define MAX_OP_PER_INSTR 32
3483 #define OPC_BUF_SIZE 512
3484 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3486 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3488 static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3489 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3491 /* return non zero if the very first instruction is invalid so that
3492 the virtual CPU can trigger an exception. */
3493 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3494 int *gen_code_size_ptr,
3495 uint8_t *pc_start, uint8_t *cs_base, int flags)
3497 DisasContext dc1, *dc = &dc1;
3499 uint16_t *gen_opc_end;
3503 struct disassemble_info disasm_info;
3506 /* generate intermediate code */
3508 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3509 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3510 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3511 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3512 dc->cc_op = CC_OP_DYNAMIC;
3513 dc->cs_base = cs_base;
3515 gen_opc_ptr = gen_opc_buf;
3516 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3517 gen_opparam_ptr = gen_opparam_buf;
3522 ret = disas_insn(dc, pc_ptr);
3524 /* we trigger an illegal instruction operation only if it
3525 is the first instruction. Otherwise, we simply stop
3526 generating the code just before it */
3527 if (pc_ptr == pc_start)
3532 pc_ptr = (void *)ret;
3533 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
3534 /* we must store the eflags state if it is not already done */
3535 if (dc->cc_op != CC_OP_DYNAMIC)
3536 gen_op_set_cc_op(dc->cc_op);
3537 if (dc->is_jmp != 1) {
3538 /* we add an additionnal jmp to update the simulated PC */
3539 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3541 *gen_opc_ptr = INDEX_op_end;
3543 /* optimize flag computations */
3549 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3551 disasm_info.flavour = bfd_get_flavour (abfd);
3552 disasm_info.arch = bfd_get_arch (abfd);
3553 disasm_info.mach = bfd_get_mach (abfd);
3555 disasm_info.endian = BFD_ENDIAN_LITTLE;
3557 disasm_info.mach = bfd_mach_i386_i386;
3559 disasm_info.mach = bfd_mach_i386_i8086;
3560 fprintf(logfile, "----------------\n");
3561 fprintf(logfile, "IN:\n");
3562 disasm_info.buffer = pc_start;
3563 disasm_info.buffer_vma = (unsigned long)pc_start;
3564 disasm_info.buffer_length = pc_ptr - pc_start;
3566 while (pc < pc_ptr) {
3567 fprintf(logfile, "0x%08lx: ", (long)pc);
3568 count = print_insn_i386((unsigned long)pc, &disasm_info);
3569 fprintf(logfile, "\n");
3572 fprintf(logfile, "\n");
3574 fprintf(logfile, "OP:\n");
3575 dump_ops(gen_opc_buf);
3576 fprintf(logfile, "\n");
3580 /* optimize flag computations */
3581 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3585 fprintf(logfile, "AFTER FLAGS OPT:\n");
3586 dump_ops(gen_opc_buf);
3587 fprintf(logfile, "\n");
3591 /* generate machine code */
3592 gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3593 flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3594 *gen_code_size_ptr = gen_code_size;
3601 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3603 disasm_info.flavour = bfd_get_flavour (abfd);
3604 disasm_info.arch = bfd_get_arch (abfd);
3605 disasm_info.mach = bfd_get_mach (abfd);
3607 #ifdef WORDS_BIGENDIAN
3608 disasm_info.endian = BFD_ENDIAN_BIG;
3610 disasm_info.endian = BFD_ENDIAN_LITTLE;
3612 disasm_info.mach = bfd_mach_i386_i386;
3615 disasm_info.buffer = pc;
3616 disasm_info.buffer_vma = (unsigned long)pc;
3617 disasm_info.buffer_length = *gen_code_size_ptr;
3618 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3619 while (pc < gen_code_buf + *gen_code_size_ptr) {
3620 fprintf(logfile, "0x%08lx: ", (long)pc);
3621 count = print_insn_i386((unsigned long)pc, &disasm_info);
3622 fprintf(logfile, "\n");
3625 fprintf(logfile, "\n");
3632 CPUX86State *cpu_x86_init(void)
3638 cpu_x86_tblocks_init();
3640 env = malloc(sizeof(CPUX86State));
3643 memset(env, 0, sizeof(CPUX86State));
3644 /* basic FPU init */
3645 for(i = 0;i < 8; i++)
3651 /* init various static tables */
3654 optimize_flags_init();
3659 void cpu_x86_close(CPUX86State *env)