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 uint8_t *gen_code_ptr;
42 int __op_param1, __op_param2, __op_param3;
48 static void error(const char *fmt, ...)
53 fprintf(stderr, "\n");
54 vfprintf(stderr, fmt, ap);
55 fprintf(stderr, "\n");
61 #define PREFIX_REPNZ 2
64 #define PREFIX_SS 0x10
65 #define PREFIX_DS 0x20
66 #define PREFIX_ES 0x40
67 #define PREFIX_FS 0x80
68 #define PREFIX_GS 0x100
69 #define PREFIX_DATA 0x200
70 #define PREFIX_ADR 0x400
71 #define PREFIX_FWAIT 0x800
73 typedef struct DisasContext {
74 /* current insn context */
77 uint8_t *pc; /* current pc */
78 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
79 static state change (stop translation) */
80 /* current block context */
81 int code32; /* 32 bit code segment */
82 int cc_op; /* current CC operation */
83 int addseg; /* non zero if either DS/ES/SS have a non zero base */
84 int f_st; /* currently unused */
87 /* i386 arith/logic operations */
107 OP_SHL1, /* undocumented */
122 /* I386 int registers */
123 OR_EAX, /* MUST be even numbered */
131 OR_TMP0, /* temporary operand register */
133 OR_A0, /* temporary register used when doing address evaluation */
134 OR_ZERO, /* fixed zero register */
138 typedef void (GenOpFunc)(void);
139 typedef void (GenOpFunc1)(long);
140 typedef void (GenOpFunc2)(long, long);
142 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
175 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
208 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
231 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
301 static GenOpFunc *gen_op_movl_A0_reg[8] = {
312 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
324 gen_op_addl_A0_EAX_s1,
325 gen_op_addl_A0_ECX_s1,
326 gen_op_addl_A0_EDX_s1,
327 gen_op_addl_A0_EBX_s1,
328 gen_op_addl_A0_ESP_s1,
329 gen_op_addl_A0_EBP_s1,
330 gen_op_addl_A0_ESI_s1,
331 gen_op_addl_A0_EDI_s1,
334 gen_op_addl_A0_EAX_s2,
335 gen_op_addl_A0_ECX_s2,
336 gen_op_addl_A0_EDX_s2,
337 gen_op_addl_A0_EBX_s2,
338 gen_op_addl_A0_ESP_s2,
339 gen_op_addl_A0_EBP_s2,
340 gen_op_addl_A0_ESI_s2,
341 gen_op_addl_A0_EDI_s2,
344 gen_op_addl_A0_EAX_s3,
345 gen_op_addl_A0_ECX_s3,
346 gen_op_addl_A0_EDX_s3,
347 gen_op_addl_A0_EBX_s3,
348 gen_op_addl_A0_ESP_s3,
349 gen_op_addl_A0_EBP_s3,
350 gen_op_addl_A0_ESI_s3,
351 gen_op_addl_A0_EDI_s3,
355 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
356 gen_op_addl_T0_T1_cc,
360 gen_op_andl_T0_T1_cc,
361 gen_op_subl_T0_T1_cc,
362 gen_op_xorl_T0_T1_cc,
363 gen_op_cmpl_T0_T1_cc,
366 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
368 gen_op_adcb_T0_T1_cc,
369 gen_op_sbbb_T0_T1_cc,
372 gen_op_adcw_T0_T1_cc,
373 gen_op_sbbw_T0_T1_cc,
376 gen_op_adcl_T0_T1_cc,
377 gen_op_sbbl_T0_T1_cc,
381 static const int cc_op_arithb[8] = {
392 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
393 gen_op_cmpxchgb_T0_T1_EAX_cc,
394 gen_op_cmpxchgw_T0_T1_EAX_cc,
395 gen_op_cmpxchgl_T0_T1_EAX_cc,
398 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
400 gen_op_rolb_T0_T1_cc,
401 gen_op_rorb_T0_T1_cc,
402 gen_op_rclb_T0_T1_cc,
403 gen_op_rcrb_T0_T1_cc,
404 gen_op_shlb_T0_T1_cc,
405 gen_op_shrb_T0_T1_cc,
406 gen_op_shlb_T0_T1_cc,
407 gen_op_sarb_T0_T1_cc,
410 gen_op_rolw_T0_T1_cc,
411 gen_op_rorw_T0_T1_cc,
412 gen_op_rclw_T0_T1_cc,
413 gen_op_rcrw_T0_T1_cc,
414 gen_op_shlw_T0_T1_cc,
415 gen_op_shrw_T0_T1_cc,
416 gen_op_shlw_T0_T1_cc,
417 gen_op_sarw_T0_T1_cc,
420 gen_op_roll_T0_T1_cc,
421 gen_op_rorl_T0_T1_cc,
422 gen_op_rcll_T0_T1_cc,
423 gen_op_rcrl_T0_T1_cc,
424 gen_op_shll_T0_T1_cc,
425 gen_op_shrl_T0_T1_cc,
426 gen_op_shll_T0_T1_cc,
427 gen_op_sarl_T0_T1_cc,
431 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
433 gen_op_shldw_T0_T1_im_cc,
434 gen_op_shrdw_T0_T1_im_cc,
437 gen_op_shldl_T0_T1_im_cc,
438 gen_op_shrdl_T0_T1_im_cc,
442 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
444 gen_op_shldw_T0_T1_ECX_cc,
445 gen_op_shrdw_T0_T1_ECX_cc,
448 gen_op_shldl_T0_T1_ECX_cc,
449 gen_op_shrdl_T0_T1_ECX_cc,
453 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
456 gen_op_btsw_T0_T1_cc,
457 gen_op_btrw_T0_T1_cc,
458 gen_op_btcw_T0_T1_cc,
462 gen_op_btsl_T0_T1_cc,
463 gen_op_btrl_T0_T1_cc,
464 gen_op_btcl_T0_T1_cc,
468 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
479 static GenOpFunc *gen_op_lds_T0_A0[3] = {
484 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
489 /* sign does not matter */
490 static GenOpFunc *gen_op_ld_T0_A0[3] = {
496 static GenOpFunc *gen_op_ld_T1_A0[3] = {
502 static GenOpFunc *gen_op_st_T0_A0[3] = {
508 static GenOpFunc *gen_op_movs[6] = {
517 static GenOpFunc *gen_op_stos[6] = {
526 static GenOpFunc *gen_op_lods[6] = {
535 static GenOpFunc *gen_op_scas[9] = {
547 static GenOpFunc *gen_op_cmps[9] = {
559 static GenOpFunc *gen_op_ins[6] = {
569 static GenOpFunc *gen_op_outs[6] = {
578 static GenOpFunc *gen_op_in[3] = {
584 static GenOpFunc *gen_op_out[3] = {
601 static GenOpFunc2 *gen_jcc_slow[8] = {
612 static GenOpFunc2 *gen_jcc_sub[3][8] = {
644 static GenOpFunc2 *gen_op_loop[2][4] = {
659 static GenOpFunc *gen_setcc_slow[8] = {
670 static GenOpFunc *gen_setcc_sub[3][8] = {
675 gen_op_setbe_T0_subb,
679 gen_op_setle_T0_subb,
685 gen_op_setbe_T0_subw,
689 gen_op_setle_T0_subw,
695 gen_op_setbe_T0_subl,
699 gen_op_setle_T0_subl,
703 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
709 gen_op_fsubr_ST0_FT0,
711 gen_op_fdivr_ST0_FT0,
714 /* NOTE the exception in "r" op ordering */
715 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
720 gen_op_fsubr_STN_ST0,
722 gen_op_fdivr_STN_ST0,
726 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
729 gen_op_mov_TN_reg[ot][0][d]();
731 gen_op_mov_TN_reg[ot][1][s]();
732 if (op == OP_ADCL || op == OP_SBBL) {
733 if (s1->cc_op != CC_OP_DYNAMIC)
734 gen_op_set_cc_op(s1->cc_op);
735 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
736 s1->cc_op = CC_OP_DYNAMIC;
738 gen_op_arith_T0_T1_cc[op]();
739 s1->cc_op = cc_op_arithb[op] + ot;
741 if (d != OR_TMP0 && op != OP_CMPL)
742 gen_op_mov_reg_T0[ot][d]();
745 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
747 gen_op_movl_T1_im(c);
748 gen_op(s1, op, ot, d, OR_TMP1);
751 static void gen_inc(DisasContext *s1, int ot, int d, int c)
754 gen_op_mov_TN_reg[ot][0][d]();
755 if (s1->cc_op != CC_OP_DYNAMIC)
756 gen_op_set_cc_op(s1->cc_op);
759 s1->cc_op = CC_OP_INCB + ot;
762 s1->cc_op = CC_OP_DECB + ot;
765 gen_op_mov_reg_T0[ot][d]();
768 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
771 gen_op_mov_TN_reg[ot][0][d]();
773 gen_op_mov_TN_reg[ot][1][s]();
774 /* for zero counts, flags are not updated, so must do it dynamically */
775 if (s1->cc_op != CC_OP_DYNAMIC)
776 gen_op_set_cc_op(s1->cc_op);
778 gen_op_shift_T0_T1_cc[ot][op]();
781 gen_op_mov_reg_T0[ot][d]();
782 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
785 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
787 /* currently not optimized */
788 gen_op_movl_T1_im(c);
789 gen_shift(s1, op, ot, d, OR_TMP1);
792 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
799 int mod, rm, code, override, must_add_seg;
801 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
803 must_add_seg = s->addseg;
804 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
805 PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
806 if (s->prefix & PREFIX_ES)
808 else if (s->prefix & PREFIX_CS)
810 else if (s->prefix & PREFIX_SS)
812 else if (s->prefix & PREFIX_DS)
814 else if (s->prefix & PREFIX_FS)
821 mod = (modrm >> 6) & 3;
833 code = ldub(s->pc++);
834 scale = (code >> 6) & 3;
835 index = (code >> 3) & 7;
850 disp = (int8_t)ldub(s->pc++);
860 gen_op_movl_A0_reg[base]();
862 gen_op_addl_A0_im(disp);
864 gen_op_movl_A0_im(disp);
866 if (havesib && (index != 4 || scale != 0)) {
867 gen_op_addl_A0_reg_sN[scale][index]();
871 if (base == R_EBP || base == R_ESP)
876 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
884 gen_op_movl_A0_im(disp);
885 rm = 0; /* avoid SS override */
892 disp = (int8_t)ldub(s->pc++);
902 gen_op_movl_A0_reg[R_EBX]();
903 gen_op_addl_A0_reg_sN[0][R_ESI]();
906 gen_op_movl_A0_reg[R_EBX]();
907 gen_op_addl_A0_reg_sN[0][R_EDI]();
910 gen_op_movl_A0_reg[R_EBP]();
911 gen_op_addl_A0_reg_sN[0][R_ESI]();
914 gen_op_movl_A0_reg[R_EBP]();
915 gen_op_addl_A0_reg_sN[0][R_EDI]();
918 gen_op_movl_A0_reg[R_ESI]();
921 gen_op_movl_A0_reg[R_EDI]();
924 gen_op_movl_A0_reg[R_EBP]();
928 gen_op_movl_A0_reg[R_EBX]();
932 gen_op_addl_A0_im(disp);
933 gen_op_andl_A0_ffff();
937 if (rm == 2 || rm == 3 || rm == 6)
942 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
952 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
954 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
956 int mod, rm, opreg, disp;
958 mod = (modrm >> 6) & 3;
963 gen_op_mov_TN_reg[ot][0][reg]();
964 gen_op_mov_reg_T0[ot][rm]();
966 gen_op_mov_TN_reg[ot][0][rm]();
968 gen_op_mov_reg_T0[ot][reg]();
971 gen_lea_modrm(s, modrm, &opreg, &disp);
974 gen_op_mov_TN_reg[ot][0][reg]();
975 gen_op_st_T0_A0[ot]();
977 gen_op_ld_T0_A0[ot]();
979 gen_op_mov_reg_T0[ot][reg]();
984 static inline uint32_t insn_get(DisasContext *s, int ot)
1006 static void gen_jcc(DisasContext *s, int b, int val)
1012 jcc_op = (b >> 1) & 7;
1014 /* we optimize the cmp/jcc case */
1018 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1023 /* some jumps are easy to compute */
1050 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1053 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1061 if (s->cc_op != CC_OP_DYNAMIC)
1062 gen_op_set_cc_op(s->cc_op);
1063 func = gen_jcc_slow[jcc_op];
1067 func(val, (long)s->pc);
1069 func((long)s->pc, val);
1073 static void gen_setcc(DisasContext *s, int b)
1079 jcc_op = (b >> 1) & 7;
1081 /* we optimize the cmp/jcc case */
1085 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1090 /* some jumps are easy to compute */
1108 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1111 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1119 if (s->cc_op != CC_OP_DYNAMIC)
1120 gen_op_set_cc_op(s->cc_op);
1121 func = gen_setcc_slow[jcc_op];
1130 /* move T0 to seg_reg and compute if the CPU state may change */
1131 void gen_movl_seg_T0(DisasContext *s, int seg_reg)
1133 gen_op_movl_seg_T0(seg_reg);
1134 if (!s->addseg && seg_reg < R_FS)
1135 s->is_jmp = 2; /* abort translation because the register may
1136 have a non zero base */
1139 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1140 is set to true if the instruction sets the PC (last instruction of
1142 long disas_insn(DisasContext *s, uint8_t *pc_start)
1144 int b, prefixes, aflag, dflag;
1146 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1152 // cur_pc = s->pc; /* for insn generation */
1156 /* check prefixes */
1159 prefixes |= PREFIX_REPZ;
1162 prefixes |= PREFIX_REPNZ;
1165 prefixes |= PREFIX_LOCK;
1168 prefixes |= PREFIX_CS;
1171 prefixes |= PREFIX_SS;
1174 prefixes |= PREFIX_DS;
1177 prefixes |= PREFIX_ES;
1180 prefixes |= PREFIX_FS;
1183 prefixes |= PREFIX_GS;
1186 prefixes |= PREFIX_DATA;
1189 prefixes |= PREFIX_ADR;
1192 prefixes |= PREFIX_FWAIT;
1196 if (prefixes & PREFIX_DATA)
1198 if (prefixes & PREFIX_ADR)
1201 s->prefix = prefixes;
1205 /* now check op code */
1209 /**************************/
1210 /* extended op code */
1211 b = ldub(s->pc++) | 0x100;
1214 /**************************/
1232 ot = dflag ? OT_LONG : OT_WORD;
1235 case 0: /* OP Ev, Gv */
1236 modrm = ldub(s->pc++);
1237 reg = ((modrm >> 3) & 7) + OR_EAX;
1238 mod = (modrm >> 6) & 3;
1241 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1242 gen_op_ld_T0_A0[ot]();
1245 opreg = OR_EAX + rm;
1247 gen_op(s, op, ot, opreg, reg);
1248 if (mod != 3 && op != 7) {
1249 gen_op_st_T0_A0[ot]();
1252 case 1: /* OP Gv, Ev */
1253 modrm = ldub(s->pc++);
1254 mod = (modrm >> 6) & 3;
1255 reg = ((modrm >> 3) & 7) + OR_EAX;
1258 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1259 gen_op_ld_T1_A0[ot]();
1262 opreg = OR_EAX + rm;
1264 gen_op(s, op, ot, reg, opreg);
1266 case 2: /* OP A, Iv */
1267 val = insn_get(s, ot);
1268 gen_opi(s, op, ot, OR_EAX, val);
1274 case 0x80: /* GRP1 */
1283 ot = dflag ? OT_LONG : OT_WORD;
1285 modrm = ldub(s->pc++);
1286 mod = (modrm >> 6) & 3;
1288 op = (modrm >> 3) & 7;
1291 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1292 gen_op_ld_T0_A0[ot]();
1295 opreg = rm + OR_EAX;
1302 val = insn_get(s, ot);
1305 val = (int8_t)insn_get(s, OT_BYTE);
1309 gen_opi(s, op, ot, opreg, val);
1310 if (op != 7 && mod != 3) {
1311 gen_op_st_T0_A0[ot]();
1316 /**************************/
1317 /* inc, dec, and other misc arith */
1318 case 0x40 ... 0x47: /* inc Gv */
1319 ot = dflag ? OT_LONG : OT_WORD;
1320 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1322 case 0x48 ... 0x4f: /* dec Gv */
1323 ot = dflag ? OT_LONG : OT_WORD;
1324 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1326 case 0xf6: /* GRP3 */
1331 ot = dflag ? OT_LONG : OT_WORD;
1333 modrm = ldub(s->pc++);
1334 mod = (modrm >> 6) & 3;
1336 op = (modrm >> 3) & 7;
1338 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1339 gen_op_ld_T0_A0[ot]();
1341 gen_op_mov_TN_reg[ot][0][rm]();
1346 val = insn_get(s, ot);
1347 gen_op_movl_T1_im(val);
1348 gen_op_testl_T0_T1_cc();
1349 s->cc_op = CC_OP_LOGICB + ot;
1354 gen_op_st_T0_A0[ot]();
1356 gen_op_mov_reg_T0[ot][rm]();
1360 gen_op_negl_T0_cc();
1362 gen_op_st_T0_A0[ot]();
1364 gen_op_mov_reg_T0[ot][rm]();
1366 s->cc_op = CC_OP_SUBB + ot;
1371 gen_op_mulb_AL_T0();
1374 gen_op_mulw_AX_T0();
1378 gen_op_mull_EAX_T0();
1381 s->cc_op = CC_OP_MUL;
1386 gen_op_imulb_AL_T0();
1389 gen_op_imulw_AX_T0();
1393 gen_op_imull_EAX_T0();
1396 s->cc_op = CC_OP_MUL;
1401 gen_op_divb_AL_T0();
1404 gen_op_divw_AX_T0();
1408 gen_op_divl_EAX_T0();
1415 gen_op_idivb_AL_T0();
1418 gen_op_idivw_AX_T0();
1422 gen_op_idivl_EAX_T0();
1431 case 0xfe: /* GRP4 */
1432 case 0xff: /* GRP5 */
1436 ot = dflag ? OT_LONG : OT_WORD;
1438 modrm = ldub(s->pc++);
1439 mod = (modrm >> 6) & 3;
1441 op = (modrm >> 3) & 7;
1442 if (op >= 2 && b == 0xfe) {
1446 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1447 gen_op_ld_T0_A0[ot]();
1449 gen_op_mov_TN_reg[ot][0][rm]();
1453 case 0: /* inc Ev */
1454 gen_inc(s, ot, OR_TMP0, 1);
1456 gen_op_st_T0_A0[ot]();
1458 gen_op_mov_reg_T0[ot][rm]();
1460 case 1: /* dec Ev */
1461 gen_inc(s, ot, OR_TMP0, -1);
1463 gen_op_st_T0_A0[ot]();
1465 gen_op_mov_reg_T0[ot][rm]();
1467 case 2: /* call Ev */
1468 gen_op_movl_T1_im((long)s->pc);
1473 case 4: /* jmp Ev */
1477 case 6: /* push Ev */
1485 case 0x84: /* test Ev, Gv */
1490 ot = dflag ? OT_LONG : OT_WORD;
1492 modrm = ldub(s->pc++);
1493 mod = (modrm >> 6) & 3;
1495 reg = (modrm >> 3) & 7;
1497 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1498 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1499 gen_op_testl_T0_T1_cc();
1500 s->cc_op = CC_OP_LOGICB + ot;
1503 case 0xa8: /* test eAX, Iv */
1508 ot = dflag ? OT_LONG : OT_WORD;
1509 val = insn_get(s, ot);
1511 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1512 gen_op_movl_T1_im(val);
1513 gen_op_testl_T0_T1_cc();
1514 s->cc_op = CC_OP_LOGICB + ot;
1517 case 0x98: /* CWDE/CBW */
1519 gen_op_movswl_EAX_AX();
1521 gen_op_movsbw_AX_AL();
1523 case 0x99: /* CDQ/CWD */
1525 gen_op_movslq_EDX_EAX();
1527 gen_op_movswl_DX_AX();
1529 case 0x1af: /* imul Gv, Ev */
1530 case 0x69: /* imul Gv, Ev, I */
1532 ot = dflag ? OT_LONG : OT_WORD;
1533 modrm = ldub(s->pc++);
1534 reg = ((modrm >> 3) & 7) + OR_EAX;
1535 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1537 val = insn_get(s, ot);
1538 gen_op_movl_T1_im(val);
1539 } else if (b == 0x6b) {
1540 val = insn_get(s, OT_BYTE);
1541 gen_op_movl_T1_im(val);
1543 gen_op_mov_TN_reg[ot][1][reg]();
1546 if (ot == OT_LONG) {
1547 gen_op_imull_T0_T1();
1549 gen_op_imulw_T0_T1();
1551 gen_op_mov_reg_T0[ot][reg]();
1552 s->cc_op = CC_OP_MUL;
1555 case 0x1c1: /* xadd Ev, Gv */
1559 ot = dflag ? OT_LONG : OT_WORD;
1560 modrm = ldub(s->pc++);
1561 reg = (modrm >> 3) & 7;
1562 mod = (modrm >> 6) & 3;
1565 gen_op_mov_TN_reg[ot][0][reg]();
1566 gen_op_mov_TN_reg[ot][1][rm]();
1567 gen_op_addl_T0_T1_cc();
1568 gen_op_mov_reg_T0[ot][rm]();
1569 gen_op_mov_reg_T1[ot][reg]();
1571 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1572 gen_op_mov_TN_reg[ot][0][reg]();
1573 gen_op_ld_T1_A0[ot]();
1574 gen_op_addl_T0_T1_cc();
1575 gen_op_st_T0_A0[ot]();
1576 gen_op_mov_reg_T1[ot][reg]();
1578 s->cc_op = CC_OP_ADDB + ot;
1581 case 0x1b1: /* cmpxchg Ev, Gv */
1585 ot = dflag ? OT_LONG : OT_WORD;
1586 modrm = ldub(s->pc++);
1587 reg = (modrm >> 3) & 7;
1588 mod = (modrm >> 6) & 3;
1589 gen_op_mov_TN_reg[ot][1][reg]();
1592 gen_op_mov_TN_reg[ot][0][rm]();
1593 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1594 gen_op_mov_reg_T0[ot][rm]();
1596 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1597 gen_op_ld_T0_A0[ot]();
1598 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1599 gen_op_st_T0_A0[ot]();
1601 s->cc_op = CC_OP_SUBB + ot;
1604 /**************************/
1606 case 0x50 ... 0x57: /* push */
1607 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1610 case 0x58 ... 0x5f: /* pop */
1612 gen_op_mov_reg_T0[OT_LONG][b & 7]();
1614 case 0x60: /* pusha */
1620 case 0x61: /* popa */
1626 case 0x68: /* push Iv */
1628 ot = dflag ? OT_LONG : OT_WORD;
1630 val = insn_get(s, ot);
1632 val = (int8_t)insn_get(s, OT_BYTE);
1633 gen_op_movl_T0_im(val);
1636 case 0x8f: /* pop Ev */
1637 ot = dflag ? OT_LONG : OT_WORD;
1638 modrm = ldub(s->pc++);
1640 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1642 case 0xc8: /* enter */
1647 level = ldub(s->pc++);
1649 gen_op_enterl(val, level);
1652 case 0xc9: /* leave */
1653 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1654 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1656 gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1658 case 0x06: /* push es */
1659 case 0x0e: /* push cs */
1660 case 0x16: /* push ss */
1661 case 0x1e: /* push ds */
1662 gen_op_movl_T0_seg(b >> 3);
1665 case 0x1a0: /* push fs */
1666 case 0x1a8: /* push gs */
1667 gen_op_movl_T0_seg(((b >> 3) & 7) + R_FS);
1670 case 0x07: /* pop es */
1671 case 0x17: /* pop ss */
1672 case 0x1f: /* pop ds */
1674 gen_movl_seg_T0(s, b >> 3);
1676 case 0x1a1: /* pop fs */
1677 case 0x1a9: /* pop gs */
1679 gen_movl_seg_T0(s, ((b >> 3) & 7) + R_FS);
1682 /**************************/
1685 case 0x89: /* mov Gv, Ev */
1689 ot = dflag ? OT_LONG : OT_WORD;
1690 modrm = ldub(s->pc++);
1691 reg = (modrm >> 3) & 7;
1693 /* generate a generic store */
1694 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1697 case 0xc7: /* mov Ev, Iv */
1701 ot = dflag ? OT_LONG : OT_WORD;
1702 modrm = ldub(s->pc++);
1703 mod = (modrm >> 6) & 3;
1705 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1706 val = insn_get(s, ot);
1707 gen_op_movl_T0_im(val);
1709 gen_op_st_T0_A0[ot]();
1711 gen_op_mov_reg_T0[ot][modrm & 7]();
1714 case 0x8b: /* mov Ev, Gv */
1718 ot = dflag ? OT_LONG : OT_WORD;
1719 modrm = ldub(s->pc++);
1720 reg = (modrm >> 3) & 7;
1722 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1723 gen_op_mov_reg_T0[ot][reg]();
1725 case 0x8e: /* mov seg, Gv */
1726 ot = dflag ? OT_LONG : OT_WORD;
1727 modrm = ldub(s->pc++);
1728 reg = (modrm >> 3) & 7;
1729 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1732 gen_movl_seg_T0(s, reg);
1734 case 0x8c: /* mov Gv, seg */
1735 ot = dflag ? OT_LONG : OT_WORD;
1736 modrm = ldub(s->pc++);
1737 reg = (modrm >> 3) & 7;
1740 gen_op_movl_T0_seg(reg);
1741 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1744 case 0x1b6: /* movzbS Gv, Eb */
1745 case 0x1b7: /* movzwS Gv, Eb */
1746 case 0x1be: /* movsbS Gv, Eb */
1747 case 0x1bf: /* movswS Gv, Eb */
1750 /* d_ot is the size of destination */
1751 d_ot = dflag + OT_WORD;
1752 /* ot is the size of source */
1753 ot = (b & 1) + OT_BYTE;
1754 modrm = ldub(s->pc++);
1755 reg = ((modrm >> 3) & 7) + OR_EAX;
1756 mod = (modrm >> 6) & 3;
1760 gen_op_mov_TN_reg[ot][0][rm]();
1761 switch(ot | (b & 8)) {
1763 gen_op_movzbl_T0_T0();
1766 gen_op_movsbl_T0_T0();
1769 gen_op_movzwl_T0_T0();
1773 gen_op_movswl_T0_T0();
1776 gen_op_mov_reg_T0[d_ot][reg]();
1778 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1780 gen_op_lds_T0_A0[ot]();
1782 gen_op_ldu_T0_A0[ot]();
1784 gen_op_mov_reg_T0[d_ot][reg]();
1789 case 0x8d: /* lea */
1790 ot = dflag ? OT_LONG : OT_WORD;
1791 modrm = ldub(s->pc++);
1792 reg = (modrm >> 3) & 7;
1793 /* we must ensure that no segment is added */
1794 s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS |
1795 PREFIX_ES | PREFIX_FS | PREFIX_GS);
1798 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1800 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1803 case 0xa0: /* mov EAX, Ov */
1805 case 0xa2: /* mov Ov, EAX */
1810 ot = dflag ? OT_LONG : OT_WORD;
1812 offset_addr = insn_get(s, OT_LONG);
1814 offset_addr = insn_get(s, OT_WORD);
1815 gen_op_movl_A0_im(offset_addr);
1816 /* handle override */
1817 /* XXX: factorize that */
1819 int override, must_add_seg;
1821 must_add_seg = s->addseg;
1822 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
1823 PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
1824 if (s->prefix & PREFIX_ES)
1826 else if (s->prefix & PREFIX_CS)
1828 else if (s->prefix & PREFIX_SS)
1830 else if (s->prefix & PREFIX_DS)
1832 else if (s->prefix & PREFIX_FS)
1839 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1843 gen_op_ld_T0_A0[ot]();
1844 gen_op_mov_reg_T0[ot][R_EAX]();
1846 gen_op_mov_TN_reg[ot][0][R_EAX]();
1847 gen_op_st_T0_A0[ot]();
1851 case 0xb0 ... 0xb7: /* mov R, Ib */
1852 val = insn_get(s, OT_BYTE);
1853 gen_op_movl_T0_im(val);
1854 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1856 case 0xb8 ... 0xbf: /* mov R, Iv */
1857 ot = dflag ? OT_LONG : OT_WORD;
1858 val = insn_get(s, ot);
1859 reg = OR_EAX + (b & 7);
1860 gen_op_movl_T0_im(val);
1861 gen_op_mov_reg_T0[ot][reg]();
1864 case 0x91 ... 0x97: /* xchg R, EAX */
1865 ot = dflag ? OT_LONG : OT_WORD;
1870 case 0x87: /* xchg Ev, Gv */
1874 ot = dflag ? OT_LONG : OT_WORD;
1875 modrm = ldub(s->pc++);
1876 reg = (modrm >> 3) & 7;
1877 mod = (modrm >> 6) & 3;
1881 gen_op_mov_TN_reg[ot][0][reg]();
1882 gen_op_mov_TN_reg[ot][1][rm]();
1883 gen_op_mov_reg_T0[ot][rm]();
1884 gen_op_mov_reg_T1[ot][reg]();
1886 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1887 gen_op_mov_TN_reg[ot][0][reg]();
1888 gen_op_ld_T1_A0[ot]();
1889 gen_op_st_T0_A0[ot]();
1890 gen_op_mov_reg_T1[ot][reg]();
1893 case 0xc4: /* les Gv */
1896 case 0xc5: /* lds Gv */
1899 case 0x1b2: /* lss Gv */
1902 case 0x1b4: /* lfs Gv */
1905 case 0x1b5: /* lgs Gv */
1908 ot = dflag ? OT_LONG : OT_WORD;
1909 modrm = ldub(s->pc++);
1910 reg = (modrm >> 3) & 7;
1911 mod = (modrm >> 6) & 3;
1914 gen_op_ld_T1_A0[ot]();
1915 op_addl_A0_im(1 << (ot - OT_WORD + 1));
1916 /* load the segment first to handle exceptions properly */
1917 gen_op_lduw_T0_A0();
1918 gen_movl_seg_T0(s, op);
1919 /* then put the data */
1920 gen_op_mov_reg_T1[ot][reg]();
1923 /************************/
1934 ot = dflag ? OT_LONG : OT_WORD;
1936 modrm = ldub(s->pc++);
1937 mod = (modrm >> 6) & 3;
1939 op = (modrm >> 3) & 7;
1942 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1943 gen_op_ld_T0_A0[ot]();
1946 opreg = rm + OR_EAX;
1951 gen_shift(s, op, ot, opreg, OR_ECX);
1954 shift = ldub(s->pc++);
1956 gen_shifti(s, op, ot, opreg, shift);
1960 gen_op_st_T0_A0[ot]();
1975 case 0x1a4: /* shld imm */
1979 case 0x1a5: /* shld cl */
1983 case 0x1ac: /* shrd imm */
1987 case 0x1ad: /* shrd cl */
1991 ot = dflag ? OT_LONG : OT_WORD;
1992 modrm = ldub(s->pc++);
1993 mod = (modrm >> 6) & 3;
1995 reg = (modrm >> 3) & 7;
1998 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1999 gen_op_ld_T0_A0[ot]();
2001 gen_op_mov_TN_reg[ot][0][rm]();
2003 gen_op_mov_TN_reg[ot][1][reg]();
2006 val = ldub(s->pc++);
2009 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2010 if (op == 0 && ot != OT_WORD)
2011 s->cc_op = CC_OP_SHLB + ot;
2013 s->cc_op = CC_OP_SARB + ot;
2016 if (s->cc_op != CC_OP_DYNAMIC)
2017 gen_op_set_cc_op(s->cc_op);
2018 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2019 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2022 gen_op_st_T0_A0[ot]();
2024 gen_op_mov_reg_T0[ot][rm]();
2028 /************************/
2031 modrm = ldub(s->pc++);
2032 mod = (modrm >> 6) & 3;
2034 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2038 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2040 case 0x00 ... 0x07: /* fxxxs */
2041 case 0x10 ... 0x17: /* fixxxl */
2042 case 0x20 ... 0x27: /* fxxxl */
2043 case 0x30 ... 0x37: /* fixxx */
2050 gen_op_flds_FT0_A0();
2053 gen_op_fildl_FT0_A0();
2056 gen_op_fldl_FT0_A0();
2060 gen_op_fild_FT0_A0();
2064 gen_op_fp_arith_ST0_FT0[op1]();
2066 /* fcomp needs pop */
2071 case 0x08: /* flds */
2072 case 0x0a: /* fsts */
2073 case 0x0b: /* fstps */
2074 case 0x18: /* fildl */
2075 case 0x1a: /* fistl */
2076 case 0x1b: /* fistpl */
2077 case 0x28: /* fldl */
2078 case 0x2a: /* fstl */
2079 case 0x2b: /* fstpl */
2080 case 0x38: /* filds */
2081 case 0x3a: /* fists */
2082 case 0x3b: /* fistps */
2089 gen_op_flds_ST0_A0();
2092 gen_op_fildl_ST0_A0();
2095 gen_op_fldl_ST0_A0();
2099 gen_op_fild_ST0_A0();
2106 gen_op_fsts_ST0_A0();
2109 gen_op_fistl_ST0_A0();
2112 gen_op_fstl_ST0_A0();
2116 gen_op_fist_ST0_A0();
2124 case 0x0d: /* fldcw mem */
2127 case 0x0f: /* fnstcw mem */
2130 case 0x1d: /* fldt mem */
2132 gen_op_fldt_ST0_A0();
2134 case 0x1f: /* fstpt mem */
2135 gen_op_fstt_ST0_A0();
2138 case 0x2f: /* fnstsw mem */
2141 case 0x3c: /* fbld */
2143 gen_op_fbld_ST0_A0();
2145 case 0x3e: /* fbstp */
2146 gen_op_fbst_ST0_A0();
2149 case 0x3d: /* fildll */
2151 gen_op_fildll_ST0_A0();
2153 case 0x3f: /* fistpll */
2154 gen_op_fistll_ST0_A0();
2161 /* register float ops */
2165 case 0x08: /* fld sti */
2167 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2169 case 0x09: /* fxchg sti */
2170 gen_op_fxchg_ST0_STN(opreg);
2172 case 0x0a: /* grp d9/2 */
2180 case 0x0c: /* grp d9/4 */
2190 gen_op_fcom_ST0_FT0();
2199 case 0x0d: /* grp d9/5 */
2208 gen_op_fldl2t_ST0();
2212 gen_op_fldl2e_ST0();
2220 gen_op_fldlg2_ST0();
2224 gen_op_fldln2_ST0();
2235 case 0x0e: /* grp d9/6 */
2246 case 3: /* fpatan */
2249 case 4: /* fxtract */
2252 case 5: /* fprem1 */
2255 case 6: /* fdecstp */
2259 case 7: /* fincstp */
2264 case 0x0f: /* grp d9/7 */
2269 case 1: /* fyl2xp1 */
2275 case 3: /* fsincos */
2278 case 5: /* fscale */
2281 case 4: /* frndint */
2293 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2294 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2295 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2301 gen_op_fp_arith_STN_ST0[op1](opreg);
2305 gen_op_fmov_FT0_STN(opreg);
2306 gen_op_fp_arith_ST0_FT0[op1]();
2310 case 0x02: /* fcom */
2311 gen_op_fmov_FT0_STN(opreg);
2312 gen_op_fcom_ST0_FT0();
2314 case 0x03: /* fcomp */
2315 gen_op_fmov_FT0_STN(opreg);
2316 gen_op_fcom_ST0_FT0();
2319 case 0x15: /* da/5 */
2321 case 1: /* fucompp */
2322 gen_op_fmov_FT0_STN(1);
2323 gen_op_fucom_ST0_FT0();
2336 case 3: /* fninit */
2343 case 0x2a: /* fst sti */
2344 gen_op_fmov_STN_ST0(opreg);
2346 case 0x2b: /* fstp sti */
2347 gen_op_fmov_STN_ST0(opreg);
2350 case 0x2c: /* fucom st(i) */
2351 gen_op_fmov_FT0_STN(opreg);
2352 gen_op_fucom_ST0_FT0();
2354 case 0x2d: /* fucomp st(i) */
2355 gen_op_fmov_FT0_STN(opreg);
2356 gen_op_fucom_ST0_FT0();
2359 case 0x33: /* de/3 */
2361 case 1: /* fcompp */
2362 gen_op_fmov_FT0_STN(1);
2363 gen_op_fcom_ST0_FT0();
2371 case 0x3c: /* df/4 */
2374 gen_op_fnstsw_EAX();
2385 /************************/
2387 case 0xa4: /* movsS */
2392 ot = dflag ? OT_LONG : OT_WORD;
2393 if (prefixes & PREFIX_REPZ) {
2394 gen_op_movs[3 + ot]();
2400 case 0xaa: /* stosS */
2405 ot = dflag ? OT_LONG : OT_WORD;
2406 if (prefixes & PREFIX_REPZ) {
2407 gen_op_stos[3 + ot]();
2412 case 0xac: /* lodsS */
2417 ot = dflag ? OT_LONG : OT_WORD;
2418 if (prefixes & PREFIX_REPZ) {
2419 gen_op_lods[3 + ot]();
2424 case 0xae: /* scasS */
2429 ot = dflag ? OT_LONG : OT_WORD;
2430 if (prefixes & PREFIX_REPNZ) {
2431 if (s->cc_op != CC_OP_DYNAMIC)
2432 gen_op_set_cc_op(s->cc_op);
2433 gen_op_scas[6 + ot]();
2434 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2435 } else if (prefixes & PREFIX_REPZ) {
2436 if (s->cc_op != CC_OP_DYNAMIC)
2437 gen_op_set_cc_op(s->cc_op);
2438 gen_op_scas[3 + ot]();
2439 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2442 s->cc_op = CC_OP_SUBB + ot;
2446 case 0xa6: /* cmpsS */
2451 ot = dflag ? OT_LONG : OT_WORD;
2452 if (prefixes & PREFIX_REPNZ) {
2453 if (s->cc_op != CC_OP_DYNAMIC)
2454 gen_op_set_cc_op(s->cc_op);
2455 gen_op_cmps[6 + ot]();
2456 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2457 } else if (prefixes & PREFIX_REPZ) {
2458 if (s->cc_op != CC_OP_DYNAMIC)
2459 gen_op_set_cc_op(s->cc_op);
2460 gen_op_cmps[3 + ot]();
2461 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2464 s->cc_op = CC_OP_SUBB + ot;
2468 /************************/
2470 case 0x6c: /* insS */
2475 ot = dflag ? OT_LONG : OT_WORD;
2476 if (prefixes & PREFIX_REPZ) {
2477 gen_op_ins[3 + ot]();
2482 case 0x6e: /* outsS */
2487 ot = dflag ? OT_LONG : OT_WORD;
2488 if (prefixes & PREFIX_REPZ) {
2489 gen_op_outs[3 + ot]();
2499 ot = dflag ? OT_LONG : OT_WORD;
2500 val = ldub(s->pc++);
2501 gen_op_movl_T0_im(val);
2503 gen_op_mov_reg_T1[ot][R_EAX]();
2510 ot = dflag ? OT_LONG : OT_WORD;
2511 val = ldub(s->pc++);
2512 gen_op_movl_T0_im(val);
2513 gen_op_mov_TN_reg[ot][1][R_EAX]();
2521 ot = dflag ? OT_LONG : OT_WORD;
2522 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2524 gen_op_mov_reg_T1[ot][R_EAX]();
2531 ot = dflag ? OT_LONG : OT_WORD;
2532 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2533 gen_op_mov_TN_reg[ot][1][R_EAX]();
2537 /************************/
2539 case 0xc2: /* ret im */
2540 /* XXX: handle stack pop ? */
2544 gen_op_addl_ESP_im(val);
2548 case 0xc3: /* ret */
2553 case 0xe8: /* call */
2554 val = insn_get(s, OT_LONG);
2556 gen_op_movl_T1_im((long)s->pc);
2561 case 0xe9: /* jmp */
2562 val = insn_get(s, OT_LONG);
2567 case 0xeb: /* jmp Jb */
2568 val = (int8_t)insn_get(s, OT_BYTE);
2573 case 0x70 ... 0x7f: /* jcc Jb */
2574 val = (int8_t)insn_get(s, OT_BYTE);
2577 case 0x180 ... 0x18f: /* jcc Jv */
2579 val = insn_get(s, OT_LONG);
2581 val = (int16_t)insn_get(s, OT_WORD);
2583 val += (long)s->pc; /* XXX: fix 16 bit wrap */
2589 case 0x190 ... 0x19f:
2590 modrm = ldub(s->pc++);
2592 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2595 /************************/
2597 case 0x9c: /* pushf */
2598 if (s->cc_op != CC_OP_DYNAMIC)
2599 gen_op_set_cc_op(s->cc_op);
2600 gen_op_movl_T0_eflags();
2603 case 0x9d: /* popf */
2605 gen_op_movl_eflags_T0();
2606 s->cc_op = CC_OP_EFLAGS;
2608 case 0x9e: /* sahf */
2609 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2610 if (s->cc_op != CC_OP_DYNAMIC)
2611 gen_op_set_cc_op(s->cc_op);
2612 gen_op_movb_eflags_T0();
2613 s->cc_op = CC_OP_EFLAGS;
2615 case 0x9f: /* lahf */
2616 if (s->cc_op != CC_OP_DYNAMIC)
2617 gen_op_set_cc_op(s->cc_op);
2618 gen_op_movl_T0_eflags();
2619 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2621 case 0xf5: /* cmc */
2622 if (s->cc_op != CC_OP_DYNAMIC)
2623 gen_op_set_cc_op(s->cc_op);
2625 s->cc_op = CC_OP_EFLAGS;
2627 case 0xf8: /* clc */
2628 if (s->cc_op != CC_OP_DYNAMIC)
2629 gen_op_set_cc_op(s->cc_op);
2631 s->cc_op = CC_OP_EFLAGS;
2633 case 0xf9: /* stc */
2634 if (s->cc_op != CC_OP_DYNAMIC)
2635 gen_op_set_cc_op(s->cc_op);
2637 s->cc_op = CC_OP_EFLAGS;
2639 case 0xfc: /* cld */
2642 case 0xfd: /* std */
2646 /************************/
2647 /* bit operations */
2648 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2649 ot = dflag ? OT_LONG : OT_WORD;
2650 modrm = ldub(s->pc++);
2651 op = (modrm >> 3) & 7;
2652 mod = (modrm >> 6) & 3;
2655 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2656 gen_op_ld_T0_A0[ot]();
2658 gen_op_mov_TN_reg[ot][0][rm]();
2661 val = ldub(s->pc++);
2662 gen_op_movl_T1_im(val);
2666 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2667 s->cc_op = CC_OP_SARB + ot;
2670 gen_op_st_T0_A0[ot]();
2672 gen_op_mov_reg_T0[ot][rm]();
2675 case 0x1a3: /* bt Gv, Ev */
2678 case 0x1ab: /* bts */
2681 case 0x1b3: /* btr */
2684 case 0x1bb: /* btc */
2687 ot = dflag ? OT_LONG : OT_WORD;
2688 modrm = ldub(s->pc++);
2689 reg = (modrm >> 3) & 7;
2690 mod = (modrm >> 6) & 3;
2692 gen_op_mov_TN_reg[OT_LONG][1][reg]();
2694 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2695 /* specific case: we need to add a displacement */
2697 gen_op_add_bitw_A0_T1();
2699 gen_op_add_bitl_A0_T1();
2700 gen_op_ld_T0_A0[ot]();
2702 gen_op_mov_TN_reg[ot][0][rm]();
2704 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2705 s->cc_op = CC_OP_SARB + ot;
2708 gen_op_st_T0_A0[ot]();
2710 gen_op_mov_reg_T0[ot][rm]();
2713 case 0x1bc: /* bsf */
2714 case 0x1bd: /* bsr */
2715 ot = dflag ? OT_LONG : OT_WORD;
2716 modrm = ldub(s->pc++);
2717 reg = (modrm >> 3) & 7;
2718 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2719 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2720 /* NOTE: we always write back the result. Intel doc says it is
2721 undefined if T0 == 0 */
2722 gen_op_mov_reg_T0[ot][reg]();
2723 s->cc_op = CC_OP_LOGICB + ot;
2725 /************************/
2727 case 0x27: /* daa */
2728 if (s->cc_op != CC_OP_DYNAMIC)
2729 gen_op_set_cc_op(s->cc_op);
2731 s->cc_op = CC_OP_EFLAGS;
2733 case 0x2f: /* das */
2734 if (s->cc_op != CC_OP_DYNAMIC)
2735 gen_op_set_cc_op(s->cc_op);
2737 s->cc_op = CC_OP_EFLAGS;
2739 case 0x37: /* aaa */
2740 if (s->cc_op != CC_OP_DYNAMIC)
2741 gen_op_set_cc_op(s->cc_op);
2743 s->cc_op = CC_OP_EFLAGS;
2745 case 0x3f: /* aas */
2746 if (s->cc_op != CC_OP_DYNAMIC)
2747 gen_op_set_cc_op(s->cc_op);
2749 s->cc_op = CC_OP_EFLAGS;
2751 case 0xd4: /* aam */
2752 val = ldub(s->pc++);
2754 s->cc_op = CC_OP_LOGICB;
2756 case 0xd5: /* aad */
2757 val = ldub(s->pc++);
2759 s->cc_op = CC_OP_LOGICB;
2761 /************************/
2763 case 0x90: /* nop */
2765 case 0xcc: /* int3 */
2766 gen_op_int3((long)pc_start);
2769 case 0xcd: /* int N */
2770 val = ldub(s->pc++);
2771 /* XXX: currently we ignore the interrupt number */
2772 gen_op_int_im((long)pc_start);
2775 case 0xce: /* into */
2776 if (s->cc_op != CC_OP_DYNAMIC)
2777 gen_op_set_cc_op(s->cc_op);
2778 gen_op_into((long)pc_start, (long)s->pc);
2781 case 0x1c8 ... 0x1cf: /* bswap reg */
2783 gen_op_mov_TN_reg[OT_LONG][0][reg]();
2785 gen_op_mov_reg_T0[OT_LONG][reg]();
2787 case 0xd6: /* salc */
2788 if (s->cc_op != CC_OP_DYNAMIC)
2789 gen_op_set_cc_op(s->cc_op);
2792 case 0xe0: /* loopnz */
2793 case 0xe1: /* loopz */
2794 if (s->cc_op != CC_OP_DYNAMIC)
2795 gen_op_set_cc_op(s->cc_op);
2797 case 0xe2: /* loop */
2798 case 0xe3: /* jecxz */
2799 val = (int8_t)insn_get(s, OT_BYTE);
2801 gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
2804 case 0x1a2: /* rdtsc */
2808 case 0x1a2: /* cpuid */
2820 /* return the next pc */
2821 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
2822 int *gen_code_size_ptr, uint8_t *pc_start,
2825 DisasContext dc1, *dc = &dc1;
2826 uint8_t *gen_code_end, *pc_ptr;
2829 struct disassemble_info disasm_info;
2831 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
2832 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
2833 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
2834 dc->cc_op = CC_OP_DYNAMIC;
2835 gen_code_ptr = gen_code_buf;
2836 gen_code_end = gen_code_buf + max_code_size - 4096;
2842 ret = disas_insn(dc, pc_ptr);
2844 error("unknown instruction at PC=0x%x B=%02x %02x %02x",
2845 pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
2848 pc_ptr = (void *)ret;
2849 } while (!dc->is_jmp && gen_code_ptr < gen_code_end);
2850 /* we must store the eflags state if it is not already done */
2851 if (dc->cc_op != CC_OP_DYNAMIC)
2852 gen_op_set_cc_op(dc->cc_op);
2853 if (dc->is_jmp != 1) {
2854 /* we add an additionnal jmp to update the simulated PC */
2858 *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2865 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2867 disasm_info.flavour = bfd_get_flavour (abfd);
2868 disasm_info.arch = bfd_get_arch (abfd);
2869 disasm_info.mach = bfd_get_mach (abfd);
2871 #ifdef WORDS_BIGENDIAN
2872 disasm_info.endian = BFD_ENDIAN_BIG;
2874 disasm_info.endian = BFD_ENDIAN_LITTLE;
2876 fprintf(logfile, "IN:\n");
2877 disasm_info.buffer = pc_start;
2878 disasm_info.buffer_vma = (unsigned long)pc_start;
2879 disasm_info.buffer_length = pc_ptr - pc_start;
2881 while (pc < pc_ptr) {
2882 fprintf(logfile, "0x%08lx: ", (long)pc);
2883 count = print_insn_i386((unsigned long)pc, &disasm_info);
2884 fprintf(logfile, "\n");
2887 fprintf(logfile, "\n");
2890 disasm_info.buffer = pc;
2891 disasm_info.buffer_vma = (unsigned long)pc;
2892 disasm_info.buffer_length = *gen_code_size_ptr;
2893 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2894 while (pc < gen_code_ptr) {
2895 fprintf(logfile, "0x%08lx: ", (long)pc);
2896 count = print_insn_i386((unsigned long)pc, &disasm_info);
2897 fprintf(logfile, "\n");
2900 fprintf(logfile, "\n");
2906 CPUX86State *cpu_x86_init(void)
2911 cpu_x86_tblocks_init();
2913 env = malloc(sizeof(CPUX86State));
2916 memset(env, 0, sizeof(CPUX86State));
2917 /* basic FPU init */
2918 for(i = 0;i < 8; i++)
2922 env->cc_op = CC_OP_EFLAGS;
2927 void cpu_x86_close(CPUX86State *env)