4 * Copyright (c) 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 #define offsetof(type, field) ((size_t) &((type *)0)->field)
41 static uint16_t *gen_opc_ptr;
42 static uint32_t *gen_opparam_ptr;
43 int __op_param1, __op_param2, __op_param3;
49 #define PREFIX_REPNZ 2
52 #define PREFIX_SS 0x10
53 #define PREFIX_DS 0x20
54 #define PREFIX_ES 0x40
55 #define PREFIX_FS 0x80
56 #define PREFIX_GS 0x100
57 #define PREFIX_DATA 0x200
58 #define PREFIX_ADR 0x400
59 #define PREFIX_FWAIT 0x800
61 typedef struct DisasContext {
62 /* current insn context */
65 uint8_t *pc; /* current pc */
66 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
67 static state change (stop translation) */
68 /* current block context */
69 int code32; /* 32 bit code segment */
70 int cc_op; /* current CC operation */
71 int addseg; /* non zero if either DS/ES/SS have a non zero base */
72 int f_st; /* currently unused */
75 /* i386 arith/logic operations */
95 OP_SHL1, /* undocumented */
100 #define DEF(s) INDEX_op_ ## s,
101 #include "opc-i386.h"
117 /* I386 int registers */
118 OR_EAX, /* MUST be even numbered */
126 OR_TMP0, /* temporary operand register */
128 OR_A0, /* temporary register used when doing address evaluation */
129 OR_ZERO, /* fixed zero register */
133 typedef void (GenOpFunc)(void);
134 typedef void (GenOpFunc1)(long);
135 typedef void (GenOpFunc2)(long, long);
137 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
170 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
203 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
226 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
296 static GenOpFunc *gen_op_movl_A0_reg[8] = {
307 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
319 gen_op_addl_A0_EAX_s1,
320 gen_op_addl_A0_ECX_s1,
321 gen_op_addl_A0_EDX_s1,
322 gen_op_addl_A0_EBX_s1,
323 gen_op_addl_A0_ESP_s1,
324 gen_op_addl_A0_EBP_s1,
325 gen_op_addl_A0_ESI_s1,
326 gen_op_addl_A0_EDI_s1,
329 gen_op_addl_A0_EAX_s2,
330 gen_op_addl_A0_ECX_s2,
331 gen_op_addl_A0_EDX_s2,
332 gen_op_addl_A0_EBX_s2,
333 gen_op_addl_A0_ESP_s2,
334 gen_op_addl_A0_EBP_s2,
335 gen_op_addl_A0_ESI_s2,
336 gen_op_addl_A0_EDI_s2,
339 gen_op_addl_A0_EAX_s3,
340 gen_op_addl_A0_ECX_s3,
341 gen_op_addl_A0_EDX_s3,
342 gen_op_addl_A0_EBX_s3,
343 gen_op_addl_A0_ESP_s3,
344 gen_op_addl_A0_EBP_s3,
345 gen_op_addl_A0_ESI_s3,
346 gen_op_addl_A0_EDI_s3,
350 static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
352 gen_op_cmovw_EAX_T1_T0,
353 gen_op_cmovw_ECX_T1_T0,
354 gen_op_cmovw_EDX_T1_T0,
355 gen_op_cmovw_EBX_T1_T0,
356 gen_op_cmovw_ESP_T1_T0,
357 gen_op_cmovw_EBP_T1_T0,
358 gen_op_cmovw_ESI_T1_T0,
359 gen_op_cmovw_EDI_T1_T0,
362 gen_op_cmovl_EAX_T1_T0,
363 gen_op_cmovl_ECX_T1_T0,
364 gen_op_cmovl_EDX_T1_T0,
365 gen_op_cmovl_EBX_T1_T0,
366 gen_op_cmovl_ESP_T1_T0,
367 gen_op_cmovl_EBP_T1_T0,
368 gen_op_cmovl_ESI_T1_T0,
369 gen_op_cmovl_EDI_T1_T0,
373 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
374 gen_op_addl_T0_T1_cc,
378 gen_op_andl_T0_T1_cc,
379 gen_op_subl_T0_T1_cc,
380 gen_op_xorl_T0_T1_cc,
381 gen_op_cmpl_T0_T1_cc,
384 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
386 gen_op_adcb_T0_T1_cc,
387 gen_op_sbbb_T0_T1_cc,
390 gen_op_adcw_T0_T1_cc,
391 gen_op_sbbw_T0_T1_cc,
394 gen_op_adcl_T0_T1_cc,
395 gen_op_sbbl_T0_T1_cc,
399 static const int cc_op_arithb[8] = {
410 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
411 gen_op_cmpxchgb_T0_T1_EAX_cc,
412 gen_op_cmpxchgw_T0_T1_EAX_cc,
413 gen_op_cmpxchgl_T0_T1_EAX_cc,
416 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
418 gen_op_rolb_T0_T1_cc,
419 gen_op_rorb_T0_T1_cc,
420 gen_op_rclb_T0_T1_cc,
421 gen_op_rcrb_T0_T1_cc,
422 gen_op_shlb_T0_T1_cc,
423 gen_op_shrb_T0_T1_cc,
424 gen_op_shlb_T0_T1_cc,
425 gen_op_sarb_T0_T1_cc,
428 gen_op_rolw_T0_T1_cc,
429 gen_op_rorw_T0_T1_cc,
430 gen_op_rclw_T0_T1_cc,
431 gen_op_rcrw_T0_T1_cc,
432 gen_op_shlw_T0_T1_cc,
433 gen_op_shrw_T0_T1_cc,
434 gen_op_shlw_T0_T1_cc,
435 gen_op_sarw_T0_T1_cc,
438 gen_op_roll_T0_T1_cc,
439 gen_op_rorl_T0_T1_cc,
440 gen_op_rcll_T0_T1_cc,
441 gen_op_rcrl_T0_T1_cc,
442 gen_op_shll_T0_T1_cc,
443 gen_op_shrl_T0_T1_cc,
444 gen_op_shll_T0_T1_cc,
445 gen_op_sarl_T0_T1_cc,
449 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
451 gen_op_shldw_T0_T1_im_cc,
452 gen_op_shrdw_T0_T1_im_cc,
455 gen_op_shldl_T0_T1_im_cc,
456 gen_op_shrdl_T0_T1_im_cc,
460 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
462 gen_op_shldw_T0_T1_ECX_cc,
463 gen_op_shrdw_T0_T1_ECX_cc,
466 gen_op_shldl_T0_T1_ECX_cc,
467 gen_op_shrdl_T0_T1_ECX_cc,
471 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
474 gen_op_btsw_T0_T1_cc,
475 gen_op_btrw_T0_T1_cc,
476 gen_op_btcw_T0_T1_cc,
480 gen_op_btsl_T0_T1_cc,
481 gen_op_btrl_T0_T1_cc,
482 gen_op_btcl_T0_T1_cc,
486 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
497 static GenOpFunc *gen_op_lds_T0_A0[3] = {
502 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
507 /* sign does not matter */
508 static GenOpFunc *gen_op_ld_T0_A0[3] = {
514 static GenOpFunc *gen_op_ld_T1_A0[3] = {
520 static GenOpFunc *gen_op_st_T0_A0[3] = {
526 static GenOpFunc *gen_op_movs[6] = {
535 static GenOpFunc *gen_op_stos[6] = {
544 static GenOpFunc *gen_op_lods[6] = {
553 static GenOpFunc *gen_op_scas[9] = {
565 static GenOpFunc *gen_op_cmps[9] = {
577 static GenOpFunc *gen_op_ins[6] = {
587 static GenOpFunc *gen_op_outs[6] = {
596 static GenOpFunc *gen_op_in[3] = {
602 static GenOpFunc *gen_op_out[3] = {
619 static GenOpFunc2 *gen_jcc_slow[8] = {
630 static GenOpFunc2 *gen_jcc_sub[3][8] = {
662 static GenOpFunc2 *gen_op_loop[2][4] = {
677 static GenOpFunc *gen_setcc_slow[8] = {
688 static GenOpFunc *gen_setcc_sub[3][8] = {
693 gen_op_setbe_T0_subb,
697 gen_op_setle_T0_subb,
703 gen_op_setbe_T0_subw,
707 gen_op_setle_T0_subw,
713 gen_op_setbe_T0_subl,
717 gen_op_setle_T0_subl,
721 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
727 gen_op_fsubr_ST0_FT0,
729 gen_op_fdivr_ST0_FT0,
732 /* NOTE the exception in "r" op ordering */
733 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
738 gen_op_fsubr_STN_ST0,
740 gen_op_fdivr_STN_ST0,
744 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
747 gen_op_mov_TN_reg[ot][0][d]();
749 gen_op_mov_TN_reg[ot][1][s]();
750 if (op == OP_ADCL || op == OP_SBBL) {
751 if (s1->cc_op != CC_OP_DYNAMIC)
752 gen_op_set_cc_op(s1->cc_op);
753 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
754 s1->cc_op = CC_OP_DYNAMIC;
756 gen_op_arith_T0_T1_cc[op]();
757 s1->cc_op = cc_op_arithb[op] + ot;
759 if (d != OR_TMP0 && op != OP_CMPL)
760 gen_op_mov_reg_T0[ot][d]();
763 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
765 gen_op_movl_T1_im(c);
766 gen_op(s1, op, ot, d, OR_TMP1);
769 static void gen_inc(DisasContext *s1, int ot, int d, int c)
772 gen_op_mov_TN_reg[ot][0][d]();
773 if (s1->cc_op != CC_OP_DYNAMIC)
774 gen_op_set_cc_op(s1->cc_op);
777 s1->cc_op = CC_OP_INCB + ot;
780 s1->cc_op = CC_OP_DECB + ot;
783 gen_op_mov_reg_T0[ot][d]();
786 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
789 gen_op_mov_TN_reg[ot][0][d]();
791 gen_op_mov_TN_reg[ot][1][s]();
792 /* for zero counts, flags are not updated, so must do it dynamically */
793 if (s1->cc_op != CC_OP_DYNAMIC)
794 gen_op_set_cc_op(s1->cc_op);
796 gen_op_shift_T0_T1_cc[ot][op]();
799 gen_op_mov_reg_T0[ot][d]();
800 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
803 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
805 /* currently not optimized */
806 gen_op_movl_T1_im(c);
807 gen_shift(s1, op, ot, d, OR_TMP1);
810 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
817 int mod, rm, code, override, must_add_seg;
819 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
821 must_add_seg = s->addseg;
822 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
823 PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
824 if (s->prefix & PREFIX_ES)
826 else if (s->prefix & PREFIX_CS)
828 else if (s->prefix & PREFIX_SS)
830 else if (s->prefix & PREFIX_DS)
832 else if (s->prefix & PREFIX_FS)
839 mod = (modrm >> 6) & 3;
851 code = ldub(s->pc++);
852 scale = (code >> 6) & 3;
853 index = (code >> 3) & 7;
868 disp = (int8_t)ldub(s->pc++);
878 gen_op_movl_A0_reg[base]();
880 gen_op_addl_A0_im(disp);
882 gen_op_movl_A0_im(disp);
884 if (havesib && (index != 4 || scale != 0)) {
885 gen_op_addl_A0_reg_sN[scale][index]();
889 if (base == R_EBP || base == R_ESP)
894 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
902 gen_op_movl_A0_im(disp);
903 rm = 0; /* avoid SS override */
910 disp = (int8_t)ldub(s->pc++);
920 gen_op_movl_A0_reg[R_EBX]();
921 gen_op_addl_A0_reg_sN[0][R_ESI]();
924 gen_op_movl_A0_reg[R_EBX]();
925 gen_op_addl_A0_reg_sN[0][R_EDI]();
928 gen_op_movl_A0_reg[R_EBP]();
929 gen_op_addl_A0_reg_sN[0][R_ESI]();
932 gen_op_movl_A0_reg[R_EBP]();
933 gen_op_addl_A0_reg_sN[0][R_EDI]();
936 gen_op_movl_A0_reg[R_ESI]();
939 gen_op_movl_A0_reg[R_EDI]();
942 gen_op_movl_A0_reg[R_EBP]();
946 gen_op_movl_A0_reg[R_EBX]();
950 gen_op_addl_A0_im(disp);
951 gen_op_andl_A0_ffff();
955 if (rm == 2 || rm == 3 || rm == 6)
960 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
970 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
972 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
974 int mod, rm, opreg, disp;
976 mod = (modrm >> 6) & 3;
981 gen_op_mov_TN_reg[ot][0][reg]();
982 gen_op_mov_reg_T0[ot][rm]();
984 gen_op_mov_TN_reg[ot][0][rm]();
986 gen_op_mov_reg_T0[ot][reg]();
989 gen_lea_modrm(s, modrm, &opreg, &disp);
992 gen_op_mov_TN_reg[ot][0][reg]();
993 gen_op_st_T0_A0[ot]();
995 gen_op_ld_T0_A0[ot]();
997 gen_op_mov_reg_T0[ot][reg]();
1002 static inline uint32_t insn_get(DisasContext *s, int ot)
1024 static void gen_jcc(DisasContext *s, int b, int val)
1030 jcc_op = (b >> 1) & 7;
1032 /* we optimize the cmp/jcc case */
1036 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1041 /* some jumps are easy to compute */
1068 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1071 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1079 if (s->cc_op != CC_OP_DYNAMIC)
1080 gen_op_set_cc_op(s->cc_op);
1081 func = gen_jcc_slow[jcc_op];
1085 func(val, (long)s->pc);
1087 func((long)s->pc, val);
1091 static void gen_setcc(DisasContext *s, int b)
1097 jcc_op = (b >> 1) & 7;
1099 /* we optimize the cmp/jcc case */
1103 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1108 /* some jumps are easy to compute */
1126 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1129 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1137 if (s->cc_op != CC_OP_DYNAMIC)
1138 gen_op_set_cc_op(s->cc_op);
1139 func = gen_setcc_slow[jcc_op];
1148 /* move T0 to seg_reg and compute if the CPU state may change */
1149 void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1151 gen_op_movl_seg_T0(seg_reg);
1152 if (!s->addseg && seg_reg < R_FS)
1153 s->is_jmp = 2; /* abort translation because the register may
1154 have a non zero base */
1157 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1158 is set to true if the instruction sets the PC (last instruction of
1160 long disas_insn(DisasContext *s, uint8_t *pc_start)
1162 int b, prefixes, aflag, dflag;
1164 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1170 // cur_pc = s->pc; /* for insn generation */
1174 /* check prefixes */
1177 prefixes |= PREFIX_REPZ;
1180 prefixes |= PREFIX_REPNZ;
1183 prefixes |= PREFIX_LOCK;
1186 prefixes |= PREFIX_CS;
1189 prefixes |= PREFIX_SS;
1192 prefixes |= PREFIX_DS;
1195 prefixes |= PREFIX_ES;
1198 prefixes |= PREFIX_FS;
1201 prefixes |= PREFIX_GS;
1204 prefixes |= PREFIX_DATA;
1207 prefixes |= PREFIX_ADR;
1210 prefixes |= PREFIX_FWAIT;
1214 if (prefixes & PREFIX_DATA)
1216 if (prefixes & PREFIX_ADR)
1219 s->prefix = prefixes;
1223 /* now check op code */
1227 /**************************/
1228 /* extended op code */
1229 b = ldub(s->pc++) | 0x100;
1232 /**************************/
1250 ot = dflag ? OT_LONG : OT_WORD;
1253 case 0: /* OP Ev, Gv */
1254 modrm = ldub(s->pc++);
1255 reg = ((modrm >> 3) & 7) + OR_EAX;
1256 mod = (modrm >> 6) & 3;
1259 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1260 gen_op_ld_T0_A0[ot]();
1263 opreg = OR_EAX + rm;
1265 gen_op(s, op, ot, opreg, reg);
1266 if (mod != 3 && op != 7) {
1267 gen_op_st_T0_A0[ot]();
1270 case 1: /* OP Gv, Ev */
1271 modrm = ldub(s->pc++);
1272 mod = (modrm >> 6) & 3;
1273 reg = ((modrm >> 3) & 7) + OR_EAX;
1276 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1277 gen_op_ld_T1_A0[ot]();
1280 opreg = OR_EAX + rm;
1282 gen_op(s, op, ot, reg, opreg);
1284 case 2: /* OP A, Iv */
1285 val = insn_get(s, ot);
1286 gen_opi(s, op, ot, OR_EAX, val);
1292 case 0x80: /* GRP1 */
1301 ot = dflag ? OT_LONG : OT_WORD;
1303 modrm = ldub(s->pc++);
1304 mod = (modrm >> 6) & 3;
1306 op = (modrm >> 3) & 7;
1309 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1310 gen_op_ld_T0_A0[ot]();
1313 opreg = rm + OR_EAX;
1320 val = insn_get(s, ot);
1323 val = (int8_t)insn_get(s, OT_BYTE);
1327 gen_opi(s, op, ot, opreg, val);
1328 if (op != 7 && mod != 3) {
1329 gen_op_st_T0_A0[ot]();
1334 /**************************/
1335 /* inc, dec, and other misc arith */
1336 case 0x40 ... 0x47: /* inc Gv */
1337 ot = dflag ? OT_LONG : OT_WORD;
1338 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1340 case 0x48 ... 0x4f: /* dec Gv */
1341 ot = dflag ? OT_LONG : OT_WORD;
1342 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1344 case 0xf6: /* GRP3 */
1349 ot = dflag ? OT_LONG : OT_WORD;
1351 modrm = ldub(s->pc++);
1352 mod = (modrm >> 6) & 3;
1354 op = (modrm >> 3) & 7;
1356 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1357 gen_op_ld_T0_A0[ot]();
1359 gen_op_mov_TN_reg[ot][0][rm]();
1364 val = insn_get(s, ot);
1365 gen_op_movl_T1_im(val);
1366 gen_op_testl_T0_T1_cc();
1367 s->cc_op = CC_OP_LOGICB + ot;
1372 gen_op_st_T0_A0[ot]();
1374 gen_op_mov_reg_T0[ot][rm]();
1378 gen_op_negl_T0_cc();
1380 gen_op_st_T0_A0[ot]();
1382 gen_op_mov_reg_T0[ot][rm]();
1384 s->cc_op = CC_OP_SUBB + ot;
1389 gen_op_mulb_AL_T0();
1392 gen_op_mulw_AX_T0();
1396 gen_op_mull_EAX_T0();
1399 s->cc_op = CC_OP_MUL;
1404 gen_op_imulb_AL_T0();
1407 gen_op_imulw_AX_T0();
1411 gen_op_imull_EAX_T0();
1414 s->cc_op = CC_OP_MUL;
1419 gen_op_divb_AL_T0();
1422 gen_op_divw_AX_T0();
1426 gen_op_divl_EAX_T0();
1433 gen_op_idivb_AL_T0();
1436 gen_op_idivw_AX_T0();
1440 gen_op_idivl_EAX_T0();
1449 case 0xfe: /* GRP4 */
1450 case 0xff: /* GRP5 */
1454 ot = dflag ? OT_LONG : OT_WORD;
1456 modrm = ldub(s->pc++);
1457 mod = (modrm >> 6) & 3;
1459 op = (modrm >> 3) & 7;
1460 if (op >= 2 && b == 0xfe) {
1464 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1465 gen_op_ld_T0_A0[ot]();
1467 gen_op_mov_TN_reg[ot][0][rm]();
1471 case 0: /* inc Ev */
1472 gen_inc(s, ot, OR_TMP0, 1);
1474 gen_op_st_T0_A0[ot]();
1476 gen_op_mov_reg_T0[ot][rm]();
1478 case 1: /* dec Ev */
1479 gen_inc(s, ot, OR_TMP0, -1);
1481 gen_op_st_T0_A0[ot]();
1483 gen_op_mov_reg_T0[ot][rm]();
1485 case 2: /* call Ev */
1486 gen_op_movl_T1_im((long)s->pc);
1491 case 4: /* jmp Ev */
1495 case 6: /* push Ev */
1503 case 0x84: /* test Ev, Gv */
1508 ot = dflag ? OT_LONG : OT_WORD;
1510 modrm = ldub(s->pc++);
1511 mod = (modrm >> 6) & 3;
1513 reg = (modrm >> 3) & 7;
1515 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1516 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1517 gen_op_testl_T0_T1_cc();
1518 s->cc_op = CC_OP_LOGICB + ot;
1521 case 0xa8: /* test eAX, Iv */
1526 ot = dflag ? OT_LONG : OT_WORD;
1527 val = insn_get(s, ot);
1529 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1530 gen_op_movl_T1_im(val);
1531 gen_op_testl_T0_T1_cc();
1532 s->cc_op = CC_OP_LOGICB + ot;
1535 case 0x98: /* CWDE/CBW */
1537 gen_op_movswl_EAX_AX();
1539 gen_op_movsbw_AX_AL();
1541 case 0x99: /* CDQ/CWD */
1543 gen_op_movslq_EDX_EAX();
1545 gen_op_movswl_DX_AX();
1547 case 0x1af: /* imul Gv, Ev */
1548 case 0x69: /* imul Gv, Ev, I */
1550 ot = dflag ? OT_LONG : OT_WORD;
1551 modrm = ldub(s->pc++);
1552 reg = ((modrm >> 3) & 7) + OR_EAX;
1553 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1555 val = insn_get(s, ot);
1556 gen_op_movl_T1_im(val);
1557 } else if (b == 0x6b) {
1558 val = insn_get(s, OT_BYTE);
1559 gen_op_movl_T1_im(val);
1561 gen_op_mov_TN_reg[ot][1][reg]();
1564 if (ot == OT_LONG) {
1565 gen_op_imull_T0_T1();
1567 gen_op_imulw_T0_T1();
1569 gen_op_mov_reg_T0[ot][reg]();
1570 s->cc_op = CC_OP_MUL;
1573 case 0x1c1: /* xadd Ev, Gv */
1577 ot = dflag ? OT_LONG : OT_WORD;
1578 modrm = ldub(s->pc++);
1579 reg = (modrm >> 3) & 7;
1580 mod = (modrm >> 6) & 3;
1583 gen_op_mov_TN_reg[ot][0][reg]();
1584 gen_op_mov_TN_reg[ot][1][rm]();
1585 gen_op_addl_T0_T1_cc();
1586 gen_op_mov_reg_T0[ot][rm]();
1587 gen_op_mov_reg_T1[ot][reg]();
1589 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1590 gen_op_mov_TN_reg[ot][0][reg]();
1591 gen_op_ld_T1_A0[ot]();
1592 gen_op_addl_T0_T1_cc();
1593 gen_op_st_T0_A0[ot]();
1594 gen_op_mov_reg_T1[ot][reg]();
1596 s->cc_op = CC_OP_ADDB + ot;
1599 case 0x1b1: /* cmpxchg Ev, Gv */
1603 ot = dflag ? OT_LONG : OT_WORD;
1604 modrm = ldub(s->pc++);
1605 reg = (modrm >> 3) & 7;
1606 mod = (modrm >> 6) & 3;
1607 gen_op_mov_TN_reg[ot][1][reg]();
1610 gen_op_mov_TN_reg[ot][0][rm]();
1611 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1612 gen_op_mov_reg_T0[ot][rm]();
1614 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1615 gen_op_ld_T0_A0[ot]();
1616 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1617 gen_op_st_T0_A0[ot]();
1619 s->cc_op = CC_OP_SUBB + ot;
1622 /**************************/
1624 case 0x50 ... 0x57: /* push */
1625 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1628 case 0x58 ... 0x5f: /* pop */
1630 gen_op_mov_reg_T0[OT_LONG][b & 7]();
1632 case 0x60: /* pusha */
1638 case 0x61: /* popa */
1644 case 0x68: /* push Iv */
1646 ot = dflag ? OT_LONG : OT_WORD;
1648 val = insn_get(s, ot);
1650 val = (int8_t)insn_get(s, OT_BYTE);
1651 gen_op_movl_T0_im(val);
1654 case 0x8f: /* pop Ev */
1655 ot = dflag ? OT_LONG : OT_WORD;
1656 modrm = ldub(s->pc++);
1658 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1660 case 0xc8: /* enter */
1665 level = ldub(s->pc++);
1667 gen_op_enterl(val, level);
1670 case 0xc9: /* leave */
1671 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1672 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1674 gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1676 case 0x06: /* push es */
1677 case 0x0e: /* push cs */
1678 case 0x16: /* push ss */
1679 case 0x1e: /* push ds */
1680 gen_op_movl_T0_seg(b >> 3);
1683 case 0x1a0: /* push fs */
1684 case 0x1a8: /* push gs */
1685 gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
1688 case 0x07: /* pop es */
1689 case 0x17: /* pop ss */
1690 case 0x1f: /* pop ds */
1692 gen_movl_seg_T0(s, b >> 3);
1694 case 0x1a1: /* pop fs */
1695 case 0x1a9: /* pop gs */
1697 gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
1700 /**************************/
1703 case 0x89: /* mov Gv, Ev */
1707 ot = dflag ? OT_LONG : OT_WORD;
1708 modrm = ldub(s->pc++);
1709 reg = (modrm >> 3) & 7;
1711 /* generate a generic store */
1712 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1715 case 0xc7: /* mov Ev, Iv */
1719 ot = dflag ? OT_LONG : OT_WORD;
1720 modrm = ldub(s->pc++);
1721 mod = (modrm >> 6) & 3;
1723 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1724 val = insn_get(s, ot);
1725 gen_op_movl_T0_im(val);
1727 gen_op_st_T0_A0[ot]();
1729 gen_op_mov_reg_T0[ot][modrm & 7]();
1732 case 0x8b: /* mov Ev, Gv */
1736 ot = dflag ? OT_LONG : OT_WORD;
1737 modrm = ldub(s->pc++);
1738 reg = (modrm >> 3) & 7;
1740 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1741 gen_op_mov_reg_T0[ot][reg]();
1743 case 0x8e: /* mov seg, Gv */
1744 ot = dflag ? OT_LONG : OT_WORD;
1745 modrm = ldub(s->pc++);
1746 reg = (modrm >> 3) & 7;
1747 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1750 gen_movl_seg_T0(s, reg);
1752 case 0x8c: /* mov Gv, seg */
1753 ot = dflag ? OT_LONG : OT_WORD;
1754 modrm = ldub(s->pc++);
1755 reg = (modrm >> 3) & 7;
1758 gen_op_movl_T0_seg(reg);
1759 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1762 case 0x1b6: /* movzbS Gv, Eb */
1763 case 0x1b7: /* movzwS Gv, Eb */
1764 case 0x1be: /* movsbS Gv, Eb */
1765 case 0x1bf: /* movswS Gv, Eb */
1768 /* d_ot is the size of destination */
1769 d_ot = dflag + OT_WORD;
1770 /* ot is the size of source */
1771 ot = (b & 1) + OT_BYTE;
1772 modrm = ldub(s->pc++);
1773 reg = ((modrm >> 3) & 7) + OR_EAX;
1774 mod = (modrm >> 6) & 3;
1778 gen_op_mov_TN_reg[ot][0][rm]();
1779 switch(ot | (b & 8)) {
1781 gen_op_movzbl_T0_T0();
1784 gen_op_movsbl_T0_T0();
1787 gen_op_movzwl_T0_T0();
1791 gen_op_movswl_T0_T0();
1794 gen_op_mov_reg_T0[d_ot][reg]();
1796 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1798 gen_op_lds_T0_A0[ot]();
1800 gen_op_ldu_T0_A0[ot]();
1802 gen_op_mov_reg_T0[d_ot][reg]();
1807 case 0x8d: /* lea */
1808 ot = dflag ? OT_LONG : OT_WORD;
1809 modrm = ldub(s->pc++);
1810 reg = (modrm >> 3) & 7;
1811 /* we must ensure that no segment is added */
1812 s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS |
1813 PREFIX_ES | PREFIX_FS | PREFIX_GS);
1816 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1818 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1821 case 0xa0: /* mov EAX, Ov */
1823 case 0xa2: /* mov Ov, EAX */
1828 ot = dflag ? OT_LONG : OT_WORD;
1830 offset_addr = insn_get(s, OT_LONG);
1832 offset_addr = insn_get(s, OT_WORD);
1833 gen_op_movl_A0_im(offset_addr);
1834 /* handle override */
1835 /* XXX: factorize that */
1837 int override, must_add_seg;
1839 must_add_seg = s->addseg;
1840 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
1841 PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
1842 if (s->prefix & PREFIX_ES)
1844 else if (s->prefix & PREFIX_CS)
1846 else if (s->prefix & PREFIX_SS)
1848 else if (s->prefix & PREFIX_DS)
1850 else if (s->prefix & PREFIX_FS)
1857 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1861 gen_op_ld_T0_A0[ot]();
1862 gen_op_mov_reg_T0[ot][R_EAX]();
1864 gen_op_mov_TN_reg[ot][0][R_EAX]();
1865 gen_op_st_T0_A0[ot]();
1869 case 0xb0 ... 0xb7: /* mov R, Ib */
1870 val = insn_get(s, OT_BYTE);
1871 gen_op_movl_T0_im(val);
1872 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1874 case 0xb8 ... 0xbf: /* mov R, Iv */
1875 ot = dflag ? OT_LONG : OT_WORD;
1876 val = insn_get(s, ot);
1877 reg = OR_EAX + (b & 7);
1878 gen_op_movl_T0_im(val);
1879 gen_op_mov_reg_T0[ot][reg]();
1882 case 0x91 ... 0x97: /* xchg R, EAX */
1883 ot = dflag ? OT_LONG : OT_WORD;
1888 case 0x87: /* xchg Ev, Gv */
1892 ot = dflag ? OT_LONG : OT_WORD;
1893 modrm = ldub(s->pc++);
1894 reg = (modrm >> 3) & 7;
1895 mod = (modrm >> 6) & 3;
1899 gen_op_mov_TN_reg[ot][0][reg]();
1900 gen_op_mov_TN_reg[ot][1][rm]();
1901 gen_op_mov_reg_T0[ot][rm]();
1902 gen_op_mov_reg_T1[ot][reg]();
1904 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1905 gen_op_mov_TN_reg[ot][0][reg]();
1906 gen_op_ld_T1_A0[ot]();
1907 gen_op_st_T0_A0[ot]();
1908 gen_op_mov_reg_T1[ot][reg]();
1911 case 0xc4: /* les Gv */
1914 case 0xc5: /* lds Gv */
1917 case 0x1b2: /* lss Gv */
1920 case 0x1b4: /* lfs Gv */
1923 case 0x1b5: /* lgs Gv */
1926 ot = dflag ? OT_LONG : OT_WORD;
1927 modrm = ldub(s->pc++);
1928 reg = (modrm >> 3) & 7;
1929 mod = (modrm >> 6) & 3;
1932 gen_op_ld_T1_A0[ot]();
1933 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1934 /* load the segment first to handle exceptions properly */
1935 gen_op_lduw_T0_A0();
1936 gen_movl_seg_T0(s, op);
1937 /* then put the data */
1938 gen_op_mov_reg_T1[ot][reg]();
1941 /************************/
1952 ot = dflag ? OT_LONG : OT_WORD;
1954 modrm = ldub(s->pc++);
1955 mod = (modrm >> 6) & 3;
1957 op = (modrm >> 3) & 7;
1960 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1961 gen_op_ld_T0_A0[ot]();
1964 opreg = rm + OR_EAX;
1969 gen_shift(s, op, ot, opreg, OR_ECX);
1972 shift = ldub(s->pc++);
1974 gen_shifti(s, op, ot, opreg, shift);
1978 gen_op_st_T0_A0[ot]();
1993 case 0x1a4: /* shld imm */
1997 case 0x1a5: /* shld cl */
2001 case 0x1ac: /* shrd imm */
2005 case 0x1ad: /* shrd cl */
2009 ot = dflag ? OT_LONG : OT_WORD;
2010 modrm = ldub(s->pc++);
2011 mod = (modrm >> 6) & 3;
2013 reg = (modrm >> 3) & 7;
2016 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2017 gen_op_ld_T0_A0[ot]();
2019 gen_op_mov_TN_reg[ot][0][rm]();
2021 gen_op_mov_TN_reg[ot][1][reg]();
2024 val = ldub(s->pc++);
2027 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2028 if (op == 0 && ot != OT_WORD)
2029 s->cc_op = CC_OP_SHLB + ot;
2031 s->cc_op = CC_OP_SARB + ot;
2034 if (s->cc_op != CC_OP_DYNAMIC)
2035 gen_op_set_cc_op(s->cc_op);
2036 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2037 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2040 gen_op_st_T0_A0[ot]();
2042 gen_op_mov_reg_T0[ot][rm]();
2046 /************************/
2049 modrm = ldub(s->pc++);
2050 mod = (modrm >> 6) & 3;
2052 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2056 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2058 case 0x00 ... 0x07: /* fxxxs */
2059 case 0x10 ... 0x17: /* fixxxl */
2060 case 0x20 ... 0x27: /* fxxxl */
2061 case 0x30 ... 0x37: /* fixxx */
2068 gen_op_flds_FT0_A0();
2071 gen_op_fildl_FT0_A0();
2074 gen_op_fldl_FT0_A0();
2078 gen_op_fild_FT0_A0();
2082 gen_op_fp_arith_ST0_FT0[op1]();
2084 /* fcomp needs pop */
2089 case 0x08: /* flds */
2090 case 0x0a: /* fsts */
2091 case 0x0b: /* fstps */
2092 case 0x18: /* fildl */
2093 case 0x1a: /* fistl */
2094 case 0x1b: /* fistpl */
2095 case 0x28: /* fldl */
2096 case 0x2a: /* fstl */
2097 case 0x2b: /* fstpl */
2098 case 0x38: /* filds */
2099 case 0x3a: /* fists */
2100 case 0x3b: /* fistps */
2107 gen_op_flds_ST0_A0();
2110 gen_op_fildl_ST0_A0();
2113 gen_op_fldl_ST0_A0();
2117 gen_op_fild_ST0_A0();
2124 gen_op_fsts_ST0_A0();
2127 gen_op_fistl_ST0_A0();
2130 gen_op_fstl_ST0_A0();
2134 gen_op_fist_ST0_A0();
2142 case 0x0d: /* fldcw mem */
2145 case 0x0f: /* fnstcw mem */
2148 case 0x1d: /* fldt mem */
2150 gen_op_fldt_ST0_A0();
2152 case 0x1f: /* fstpt mem */
2153 gen_op_fstt_ST0_A0();
2156 case 0x2f: /* fnstsw mem */
2159 case 0x3c: /* fbld */
2161 gen_op_fbld_ST0_A0();
2163 case 0x3e: /* fbstp */
2164 gen_op_fbst_ST0_A0();
2167 case 0x3d: /* fildll */
2169 gen_op_fildll_ST0_A0();
2171 case 0x3f: /* fistpll */
2172 gen_op_fistll_ST0_A0();
2179 /* register float ops */
2183 case 0x08: /* fld sti */
2185 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2187 case 0x09: /* fxchg sti */
2188 gen_op_fxchg_ST0_STN(opreg);
2190 case 0x0a: /* grp d9/2 */
2198 case 0x0c: /* grp d9/4 */
2208 gen_op_fcom_ST0_FT0();
2217 case 0x0d: /* grp d9/5 */
2226 gen_op_fldl2t_ST0();
2230 gen_op_fldl2e_ST0();
2238 gen_op_fldlg2_ST0();
2242 gen_op_fldln2_ST0();
2253 case 0x0e: /* grp d9/6 */
2264 case 3: /* fpatan */
2267 case 4: /* fxtract */
2270 case 5: /* fprem1 */
2273 case 6: /* fdecstp */
2277 case 7: /* fincstp */
2282 case 0x0f: /* grp d9/7 */
2287 case 1: /* fyl2xp1 */
2293 case 3: /* fsincos */
2296 case 5: /* fscale */
2299 case 4: /* frndint */
2311 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2312 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2313 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2319 gen_op_fp_arith_STN_ST0[op1](opreg);
2323 gen_op_fmov_FT0_STN(opreg);
2324 gen_op_fp_arith_ST0_FT0[op1]();
2328 case 0x02: /* fcom */
2329 gen_op_fmov_FT0_STN(opreg);
2330 gen_op_fcom_ST0_FT0();
2332 case 0x03: /* fcomp */
2333 gen_op_fmov_FT0_STN(opreg);
2334 gen_op_fcom_ST0_FT0();
2337 case 0x15: /* da/5 */
2339 case 1: /* fucompp */
2340 gen_op_fmov_FT0_STN(1);
2341 gen_op_fucom_ST0_FT0();
2354 case 3: /* fninit */
2361 case 0x2a: /* fst sti */
2362 gen_op_fmov_STN_ST0(opreg);
2364 case 0x2b: /* fstp sti */
2365 gen_op_fmov_STN_ST0(opreg);
2368 case 0x2c: /* fucom st(i) */
2369 gen_op_fmov_FT0_STN(opreg);
2370 gen_op_fucom_ST0_FT0();
2372 case 0x2d: /* fucomp st(i) */
2373 gen_op_fmov_FT0_STN(opreg);
2374 gen_op_fucom_ST0_FT0();
2377 case 0x33: /* de/3 */
2379 case 1: /* fcompp */
2380 gen_op_fmov_FT0_STN(1);
2381 gen_op_fcom_ST0_FT0();
2389 case 0x3c: /* df/4 */
2392 gen_op_fnstsw_EAX();
2403 /************************/
2405 case 0xa4: /* movsS */
2410 ot = dflag ? OT_LONG : OT_WORD;
2411 if (prefixes & PREFIX_REPZ) {
2412 gen_op_movs[3 + ot]();
2418 case 0xaa: /* stosS */
2423 ot = dflag ? OT_LONG : OT_WORD;
2424 if (prefixes & PREFIX_REPZ) {
2425 gen_op_stos[3 + ot]();
2430 case 0xac: /* lodsS */
2435 ot = dflag ? OT_LONG : OT_WORD;
2436 if (prefixes & PREFIX_REPZ) {
2437 gen_op_lods[3 + ot]();
2442 case 0xae: /* scasS */
2447 ot = dflag ? OT_LONG : OT_WORD;
2448 if (prefixes & PREFIX_REPNZ) {
2449 if (s->cc_op != CC_OP_DYNAMIC)
2450 gen_op_set_cc_op(s->cc_op);
2451 gen_op_scas[6 + ot]();
2452 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2453 } else if (prefixes & PREFIX_REPZ) {
2454 if (s->cc_op != CC_OP_DYNAMIC)
2455 gen_op_set_cc_op(s->cc_op);
2456 gen_op_scas[3 + ot]();
2457 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2460 s->cc_op = CC_OP_SUBB + ot;
2464 case 0xa6: /* cmpsS */
2469 ot = dflag ? OT_LONG : OT_WORD;
2470 if (prefixes & PREFIX_REPNZ) {
2471 if (s->cc_op != CC_OP_DYNAMIC)
2472 gen_op_set_cc_op(s->cc_op);
2473 gen_op_cmps[6 + ot]();
2474 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2475 } else if (prefixes & PREFIX_REPZ) {
2476 if (s->cc_op != CC_OP_DYNAMIC)
2477 gen_op_set_cc_op(s->cc_op);
2478 gen_op_cmps[3 + ot]();
2479 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2482 s->cc_op = CC_OP_SUBB + ot;
2486 /************************/
2488 case 0x6c: /* insS */
2493 ot = dflag ? OT_LONG : OT_WORD;
2494 if (prefixes & PREFIX_REPZ) {
2495 gen_op_ins[3 + ot]();
2500 case 0x6e: /* outsS */
2505 ot = dflag ? OT_LONG : OT_WORD;
2506 if (prefixes & PREFIX_REPZ) {
2507 gen_op_outs[3 + ot]();
2517 ot = dflag ? OT_LONG : OT_WORD;
2518 val = ldub(s->pc++);
2519 gen_op_movl_T0_im(val);
2521 gen_op_mov_reg_T1[ot][R_EAX]();
2528 ot = dflag ? OT_LONG : OT_WORD;
2529 val = ldub(s->pc++);
2530 gen_op_movl_T0_im(val);
2531 gen_op_mov_TN_reg[ot][1][R_EAX]();
2539 ot = dflag ? OT_LONG : OT_WORD;
2540 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2542 gen_op_mov_reg_T1[ot][R_EAX]();
2549 ot = dflag ? OT_LONG : OT_WORD;
2550 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2551 gen_op_mov_TN_reg[ot][1][R_EAX]();
2555 /************************/
2557 case 0xc2: /* ret im */
2558 /* XXX: handle stack pop ? */
2562 gen_op_addl_ESP_im(val);
2566 case 0xc3: /* ret */
2571 case 0xe8: /* call */
2572 val = insn_get(s, OT_LONG);
2574 gen_op_movl_T1_im((long)s->pc);
2579 case 0xe9: /* jmp */
2580 val = insn_get(s, OT_LONG);
2585 case 0xeb: /* jmp Jb */
2586 val = (int8_t)insn_get(s, OT_BYTE);
2591 case 0x70 ... 0x7f: /* jcc Jb */
2592 val = (int8_t)insn_get(s, OT_BYTE);
2595 case 0x180 ... 0x18f: /* jcc Jv */
2597 val = insn_get(s, OT_LONG);
2599 val = (int16_t)insn_get(s, OT_WORD);
2601 val += (long)s->pc; /* XXX: fix 16 bit wrap */
2607 case 0x190 ... 0x19f: /* setcc Gv */
2608 modrm = ldub(s->pc++);
2610 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2612 case 0x140 ... 0x14f: /* cmov Gv, Ev */
2613 ot = dflag ? OT_LONG : OT_WORD;
2614 modrm = ldub(s->pc++);
2615 reg = (modrm >> 3) & 7;
2616 mod = (modrm >> 6) & 3;
2619 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2620 gen_op_ld_T1_A0[ot]();
2623 gen_op_mov_TN_reg[ot][1][rm]();
2625 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
2628 /************************/
2630 case 0x9c: /* pushf */
2631 if (s->cc_op != CC_OP_DYNAMIC)
2632 gen_op_set_cc_op(s->cc_op);
2633 gen_op_movl_T0_eflags();
2636 case 0x9d: /* popf */
2638 gen_op_movl_eflags_T0();
2639 s->cc_op = CC_OP_EFLAGS;
2641 case 0x9e: /* sahf */
2642 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2643 if (s->cc_op != CC_OP_DYNAMIC)
2644 gen_op_set_cc_op(s->cc_op);
2645 gen_op_movb_eflags_T0();
2646 s->cc_op = CC_OP_EFLAGS;
2648 case 0x9f: /* lahf */
2649 if (s->cc_op != CC_OP_DYNAMIC)
2650 gen_op_set_cc_op(s->cc_op);
2651 gen_op_movl_T0_eflags();
2652 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2654 case 0xf5: /* cmc */
2655 if (s->cc_op != CC_OP_DYNAMIC)
2656 gen_op_set_cc_op(s->cc_op);
2658 s->cc_op = CC_OP_EFLAGS;
2660 case 0xf8: /* clc */
2661 if (s->cc_op != CC_OP_DYNAMIC)
2662 gen_op_set_cc_op(s->cc_op);
2664 s->cc_op = CC_OP_EFLAGS;
2666 case 0xf9: /* stc */
2667 if (s->cc_op != CC_OP_DYNAMIC)
2668 gen_op_set_cc_op(s->cc_op);
2670 s->cc_op = CC_OP_EFLAGS;
2672 case 0xfc: /* cld */
2675 case 0xfd: /* std */
2679 /************************/
2680 /* bit operations */
2681 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2682 ot = dflag ? OT_LONG : OT_WORD;
2683 modrm = ldub(s->pc++);
2684 op = (modrm >> 3) & 7;
2685 mod = (modrm >> 6) & 3;
2688 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2689 gen_op_ld_T0_A0[ot]();
2691 gen_op_mov_TN_reg[ot][0][rm]();
2694 val = ldub(s->pc++);
2695 gen_op_movl_T1_im(val);
2699 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2700 s->cc_op = CC_OP_SARB + ot;
2703 gen_op_st_T0_A0[ot]();
2705 gen_op_mov_reg_T0[ot][rm]();
2708 case 0x1a3: /* bt Gv, Ev */
2711 case 0x1ab: /* bts */
2714 case 0x1b3: /* btr */
2717 case 0x1bb: /* btc */
2720 ot = dflag ? OT_LONG : OT_WORD;
2721 modrm = ldub(s->pc++);
2722 reg = (modrm >> 3) & 7;
2723 mod = (modrm >> 6) & 3;
2725 gen_op_mov_TN_reg[OT_LONG][1][reg]();
2727 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2728 /* specific case: we need to add a displacement */
2730 gen_op_add_bitw_A0_T1();
2732 gen_op_add_bitl_A0_T1();
2733 gen_op_ld_T0_A0[ot]();
2735 gen_op_mov_TN_reg[ot][0][rm]();
2737 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2738 s->cc_op = CC_OP_SARB + ot;
2741 gen_op_st_T0_A0[ot]();
2743 gen_op_mov_reg_T0[ot][rm]();
2746 case 0x1bc: /* bsf */
2747 case 0x1bd: /* bsr */
2748 ot = dflag ? OT_LONG : OT_WORD;
2749 modrm = ldub(s->pc++);
2750 reg = (modrm >> 3) & 7;
2751 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2752 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2753 /* NOTE: we always write back the result. Intel doc says it is
2754 undefined if T0 == 0 */
2755 gen_op_mov_reg_T0[ot][reg]();
2756 s->cc_op = CC_OP_LOGICB + ot;
2758 /************************/
2760 case 0x27: /* daa */
2761 if (s->cc_op != CC_OP_DYNAMIC)
2762 gen_op_set_cc_op(s->cc_op);
2764 s->cc_op = CC_OP_EFLAGS;
2766 case 0x2f: /* das */
2767 if (s->cc_op != CC_OP_DYNAMIC)
2768 gen_op_set_cc_op(s->cc_op);
2770 s->cc_op = CC_OP_EFLAGS;
2772 case 0x37: /* aaa */
2773 if (s->cc_op != CC_OP_DYNAMIC)
2774 gen_op_set_cc_op(s->cc_op);
2776 s->cc_op = CC_OP_EFLAGS;
2778 case 0x3f: /* aas */
2779 if (s->cc_op != CC_OP_DYNAMIC)
2780 gen_op_set_cc_op(s->cc_op);
2782 s->cc_op = CC_OP_EFLAGS;
2784 case 0xd4: /* aam */
2785 val = ldub(s->pc++);
2787 s->cc_op = CC_OP_LOGICB;
2789 case 0xd5: /* aad */
2790 val = ldub(s->pc++);
2792 s->cc_op = CC_OP_LOGICB;
2794 /************************/
2796 case 0x90: /* nop */
2798 case 0xcc: /* int3 */
2799 gen_op_int3((long)pc_start);
2802 case 0xcd: /* int N */
2803 val = ldub(s->pc++);
2804 /* XXX: currently we ignore the interrupt number */
2805 gen_op_int_im((long)pc_start);
2808 case 0xce: /* into */
2809 if (s->cc_op != CC_OP_DYNAMIC)
2810 gen_op_set_cc_op(s->cc_op);
2811 gen_op_into((long)pc_start, (long)s->pc);
2814 case 0x1c8 ... 0x1cf: /* bswap reg */
2816 gen_op_mov_TN_reg[OT_LONG][0][reg]();
2818 gen_op_mov_reg_T0[OT_LONG][reg]();
2820 case 0xd6: /* salc */
2821 if (s->cc_op != CC_OP_DYNAMIC)
2822 gen_op_set_cc_op(s->cc_op);
2825 case 0xe0: /* loopnz */
2826 case 0xe1: /* loopz */
2827 if (s->cc_op != CC_OP_DYNAMIC)
2828 gen_op_set_cc_op(s->cc_op);
2830 case 0xe2: /* loop */
2831 case 0xe3: /* jecxz */
2832 val = (int8_t)insn_get(s, OT_BYTE);
2834 gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
2837 case 0x131: /* rdtsc */
2841 case 0x1a2: /* cpuid */
2853 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
2854 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
2856 /* flags read by an operation */
2857 static uint16_t opc_read_flags[NB_OPS] = {
2858 [INDEX_op_aas] = CC_A,
2859 [INDEX_op_aaa] = CC_A,
2860 [INDEX_op_das] = CC_A | CC_C,
2861 [INDEX_op_daa] = CC_A | CC_C,
2863 [INDEX_op_adcb_T0_T1_cc] = CC_C,
2864 [INDEX_op_adcw_T0_T1_cc] = CC_C,
2865 [INDEX_op_adcl_T0_T1_cc] = CC_C,
2866 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
2867 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
2868 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
2870 [INDEX_op_into] = CC_O,
2872 [INDEX_op_jo_cc] = CC_O,
2873 [INDEX_op_jb_cc] = CC_C,
2874 [INDEX_op_jz_cc] = CC_Z,
2875 [INDEX_op_jbe_cc] = CC_Z | CC_C,
2876 [INDEX_op_js_cc] = CC_S,
2877 [INDEX_op_jp_cc] = CC_P,
2878 [INDEX_op_jl_cc] = CC_O | CC_S,
2879 [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,
2881 [INDEX_op_jb_subb] = CC_C,
2882 [INDEX_op_jb_subw] = CC_C,
2883 [INDEX_op_jb_subl] = CC_C,
2885 [INDEX_op_jz_subb] = CC_Z,
2886 [INDEX_op_jz_subw] = CC_Z,
2887 [INDEX_op_jz_subl] = CC_Z,
2889 [INDEX_op_jbe_subb] = CC_Z | CC_C,
2890 [INDEX_op_jbe_subw] = CC_Z | CC_C,
2891 [INDEX_op_jbe_subl] = CC_Z | CC_C,
2893 [INDEX_op_js_subb] = CC_S,
2894 [INDEX_op_js_subw] = CC_S,
2895 [INDEX_op_js_subl] = CC_S,
2897 [INDEX_op_jl_subb] = CC_O | CC_S,
2898 [INDEX_op_jl_subw] = CC_O | CC_S,
2899 [INDEX_op_jl_subl] = CC_O | CC_S,
2901 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
2902 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
2903 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
2905 [INDEX_op_loopnzw] = CC_Z,
2906 [INDEX_op_loopnzl] = CC_Z,
2907 [INDEX_op_loopzw] = CC_Z,
2908 [INDEX_op_loopzl] = CC_Z,
2910 [INDEX_op_seto_T0_cc] = CC_O,
2911 [INDEX_op_setb_T0_cc] = CC_C,
2912 [INDEX_op_setz_T0_cc] = CC_Z,
2913 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
2914 [INDEX_op_sets_T0_cc] = CC_S,
2915 [INDEX_op_setp_T0_cc] = CC_P,
2916 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
2917 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
2919 [INDEX_op_setb_T0_subb] = CC_C,
2920 [INDEX_op_setb_T0_subw] = CC_C,
2921 [INDEX_op_setb_T0_subl] = CC_C,
2923 [INDEX_op_setz_T0_subb] = CC_Z,
2924 [INDEX_op_setz_T0_subw] = CC_Z,
2925 [INDEX_op_setz_T0_subl] = CC_Z,
2927 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
2928 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
2929 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
2931 [INDEX_op_sets_T0_subb] = CC_S,
2932 [INDEX_op_sets_T0_subw] = CC_S,
2933 [INDEX_op_sets_T0_subl] = CC_S,
2935 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
2936 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
2937 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
2939 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
2940 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
2941 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
2943 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
2944 [INDEX_op_cmc] = CC_C,
2945 [INDEX_op_salc] = CC_C,
2947 [INDEX_op_rclb_T0_T1_cc] = CC_C,
2948 [INDEX_op_rclw_T0_T1_cc] = CC_C,
2949 [INDEX_op_rcll_T0_T1_cc] = CC_C,
2950 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
2951 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
2952 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
2955 /* flags written by an operation */
2956 static uint16_t opc_write_flags[NB_OPS] = {
2957 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
2958 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
2959 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
2960 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
2961 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
2962 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
2963 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
2964 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
2965 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
2966 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
2967 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
2968 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
2969 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
2970 [INDEX_op_incl_T0_cc] = CC_OSZAP,
2971 [INDEX_op_decl_T0_cc] = CC_OSZAP,
2972 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
2974 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
2975 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
2976 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
2977 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
2978 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
2979 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
2980 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
2981 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
2984 [INDEX_op_aam] = CC_OSZAPC,
2985 [INDEX_op_aad] = CC_OSZAPC,
2986 [INDEX_op_aas] = CC_OSZAPC,
2987 [INDEX_op_aaa] = CC_OSZAPC,
2988 [INDEX_op_das] = CC_OSZAPC,
2989 [INDEX_op_daa] = CC_OSZAPC,
2991 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
2992 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
2993 [INDEX_op_clc] = CC_C,
2994 [INDEX_op_stc] = CC_C,
2995 [INDEX_op_cmc] = CC_C,
2997 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
2998 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
2999 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3000 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3001 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3002 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3004 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3005 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3006 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3007 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3008 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3009 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3011 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3012 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3013 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3015 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3016 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3017 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3019 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3020 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3021 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3023 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3024 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3025 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3026 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3028 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3029 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3030 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3031 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3033 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3034 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3035 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3036 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3037 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3038 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3039 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3040 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3042 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3043 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3044 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3045 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3047 [INDEX_op_scasb] = CC_OSZAPC,
3048 [INDEX_op_scasw] = CC_OSZAPC,
3049 [INDEX_op_scasl] = CC_OSZAPC,
3050 [INDEX_op_repz_scasb] = CC_OSZAPC,
3051 [INDEX_op_repz_scasw] = CC_OSZAPC,
3052 [INDEX_op_repz_scasl] = CC_OSZAPC,
3053 [INDEX_op_repnz_scasb] = CC_OSZAPC,
3054 [INDEX_op_repnz_scasw] = CC_OSZAPC,
3055 [INDEX_op_repnz_scasl] = CC_OSZAPC,
3057 [INDEX_op_cmpsb] = CC_OSZAPC,
3058 [INDEX_op_cmpsw] = CC_OSZAPC,
3059 [INDEX_op_cmpsl] = CC_OSZAPC,
3060 [INDEX_op_repz_cmpsb] = CC_OSZAPC,
3061 [INDEX_op_repz_cmpsw] = CC_OSZAPC,
3062 [INDEX_op_repz_cmpsl] = CC_OSZAPC,
3063 [INDEX_op_repnz_cmpsb] = CC_OSZAPC,
3064 [INDEX_op_repnz_cmpsw] = CC_OSZAPC,
3065 [INDEX_op_repnz_cmpsl] = CC_OSZAPC,
3067 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3068 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3071 /* simpler form of an operation if no flags need to be generated */
3072 static uint16_t opc_simpler[NB_OPS] = {
3073 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3074 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3075 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3076 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3077 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3078 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3079 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3080 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3082 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3083 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3084 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3086 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3087 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3088 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3090 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3091 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3092 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3094 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3095 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3096 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3098 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3099 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3100 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3103 static void optimize_flags_init(void)
3106 /* put default values in arrays */
3107 for(i = 0; i < NB_OPS; i++) {
3108 if (opc_simpler[i] == 0)
3113 /* CPU flags computation optimization: we move backward thru the
3114 generated code to see which flags are needed. The operation is
3115 modified if suitable */
3116 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3119 int live_flags, write_flags, op;
3121 opc_ptr = opc_buf + opc_buf_len;
3122 /* live_flags contains the flags needed by the next instructions
3123 in the code. At the end of the bloc, we consider that all the
3125 live_flags = CC_OSZAPC;
3126 while (opc_ptr > opc_buf) {
3128 /* if none of the flags written by the instruction is used,
3129 then we can try to find a simpler instruction */
3130 write_flags = opc_write_flags[op];
3131 if ((live_flags & write_flags) == 0) {
3132 *opc_ptr = opc_simpler[op];
3134 /* compute the live flags before the instruction */
3135 live_flags &= ~write_flags;
3136 live_flags |= opc_read_flags[op];
3142 static const char *op_str[] = {
3144 #include "opc-i386.h"
3148 static void dump_ops(const uint16_t *opc_buf)
3150 const uint16_t *opc_ptr;
3155 fprintf(logfile, "0x%04x: %s\n", opc_ptr - opc_buf - 1, op_str[c]);
3156 if (c == INDEX_op_end)
3163 /* XXX: make this buffer thread safe */
3164 /* XXX: make safe guess about sizes */
3165 #define MAX_OP_PER_INSTR 32
3166 #define OPC_BUF_SIZE 512
3167 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3169 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3171 static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3172 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3174 /* return the next pc */
3175 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3176 int *gen_code_size_ptr, uint8_t *pc_start,
3179 DisasContext dc1, *dc = &dc1;
3181 uint16_t *gen_opc_end;
3184 struct disassemble_info disasm_info;
3187 /* generate intermediate code */
3189 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3190 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3191 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3192 dc->cc_op = CC_OP_DYNAMIC;
3194 gen_opc_ptr = gen_opc_buf;
3195 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3196 gen_opparam_ptr = gen_opparam_buf;
3201 ret = disas_insn(dc, pc_ptr);
3203 fprintf(stderr, "unknown instruction at PC=0x%08lx B=%02x %02x %02x",
3204 (long)pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
3207 pc_ptr = (void *)ret;
3208 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end);
3209 /* we must store the eflags state if it is not already done */
3210 if (dc->cc_op != CC_OP_DYNAMIC)
3211 gen_op_set_cc_op(dc->cc_op);
3212 if (dc->is_jmp != 1) {
3213 /* we add an additionnal jmp to update the simulated PC */
3216 *gen_opc_ptr = INDEX_op_end;
3218 /* optimize flag computations */
3224 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
3226 disasm_info.flavour = bfd_get_flavour (abfd);
3227 disasm_info.arch = bfd_get_arch (abfd);
3228 disasm_info.mach = bfd_get_mach (abfd);
3230 #ifdef WORDS_BIGENDIAN
3231 disasm_info.endian = BFD_ENDIAN_BIG;
3233 disasm_info.endian = BFD_ENDIAN_LITTLE;
3235 fprintf(logfile, "----------------\n");
3236 fprintf(logfile, "IN:\n");
3237 disasm_info.buffer = pc_start;
3238 disasm_info.buffer_vma = (unsigned long)pc_start;
3239 disasm_info.buffer_length = pc_ptr - pc_start;
3241 while (pc < pc_ptr) {
3242 fprintf(logfile, "0x%08lx: ", (long)pc);
3243 count = print_insn_i386((unsigned long)pc, &disasm_info);
3244 fprintf(logfile, "\n");
3247 fprintf(logfile, "\n");
3249 fprintf(logfile, "OP:\n");
3250 dump_ops(gen_opc_buf);
3251 fprintf(logfile, "\n");
3255 /* optimize flag computations */
3256 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3260 fprintf(logfile, "AFTER FLAGS OPT:\n");
3261 dump_ops(gen_opc_buf);
3262 fprintf(logfile, "\n");
3266 /* generate machine code */
3267 *gen_code_size_ptr = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);
3275 disasm_info.buffer = pc;
3276 disasm_info.buffer_vma = (unsigned long)pc;
3277 disasm_info.buffer_length = *gen_code_size_ptr;
3278 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3279 while (pc < gen_code_buf + *gen_code_size_ptr) {
3280 fprintf(logfile, "0x%08lx: ", (long)pc);
3281 count = print_insn_i386((unsigned long)pc, &disasm_info);
3282 fprintf(logfile, "\n");
3285 fprintf(logfile, "\n");
3291 CPUX86State *cpu_x86_init(void)
3297 cpu_x86_tblocks_init();
3299 env = malloc(sizeof(CPUX86State));
3302 memset(env, 0, sizeof(CPUX86State));
3303 /* basic FPU init */
3304 for(i = 0;i < 8; i++)
3308 env->cc_op = CC_OP_EFLAGS;
3311 /* init various static tables */
3314 optimize_flags_init();
3319 void cpu_x86_close(CPUX86State *env)