18 static uint8_t *gen_code_ptr;
19 int __op_param1, __op_param2, __op_param3;
25 static void error(const char *fmt, ...)
30 fprintf(stderr, "\n");
31 vfprintf(stderr, fmt, ap);
32 fprintf(stderr, "\n");
38 #define PREFIX_REPNZ 2
41 #define PREFIX_SS 0x10
42 #define PREFIX_DS 0x20
43 #define PREFIX_ES 0x40
44 #define PREFIX_FS 0x80
45 #define PREFIX_GS 0x100
46 #define PREFIX_DATA 0x200
47 #define PREFIX_ADR 0x400
48 #define PREFIX_FWAIT 0x800
50 typedef struct DisasContext {
51 /* current insn context */
54 uint8_t *pc; /* current pc */
55 int cc_op; /* current CC operation */
59 /* i386 arith/logic operations */
79 OP_SHL1, /* undocumented */
94 /* I386 int registers */
95 OR_EAX, /* MUST be even numbered */
103 OR_TMP0, /* temporary operand register */
105 OR_A0, /* temporary register used when doing address evaluation */
106 OR_ZERO, /* fixed zero register */
110 typedef void (GenOpFunc)(void);
111 typedef void (GenOpFunc1)(long);
112 typedef void (GenOpFunc2)(long, long);
114 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
147 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
180 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
203 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
273 static GenOpFunc *gen_op_movl_A0_reg[8] = {
284 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
296 gen_op_addl_A0_EAX_s1,
297 gen_op_addl_A0_ECX_s1,
298 gen_op_addl_A0_EDX_s1,
299 gen_op_addl_A0_EBX_s1,
300 gen_op_addl_A0_ESP_s1,
301 gen_op_addl_A0_EBP_s1,
302 gen_op_addl_A0_ESI_s1,
303 gen_op_addl_A0_EDI_s1,
306 gen_op_addl_A0_EAX_s2,
307 gen_op_addl_A0_ECX_s2,
308 gen_op_addl_A0_EDX_s2,
309 gen_op_addl_A0_EBX_s2,
310 gen_op_addl_A0_ESP_s2,
311 gen_op_addl_A0_EBP_s2,
312 gen_op_addl_A0_ESI_s2,
313 gen_op_addl_A0_EDI_s2,
316 gen_op_addl_A0_EAX_s3,
317 gen_op_addl_A0_ECX_s3,
318 gen_op_addl_A0_EDX_s3,
319 gen_op_addl_A0_EBX_s3,
320 gen_op_addl_A0_ESP_s3,
321 gen_op_addl_A0_EBP_s3,
322 gen_op_addl_A0_ESI_s3,
323 gen_op_addl_A0_EDI_s3,
327 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
328 gen_op_addl_T0_T1_cc,
332 gen_op_andl_T0_T1_cc,
333 gen_op_subl_T0_T1_cc,
334 gen_op_xorl_T0_T1_cc,
335 gen_op_cmpl_T0_T1_cc,
338 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
340 gen_op_adcb_T0_T1_cc,
341 gen_op_sbbb_T0_T1_cc,
344 gen_op_adcw_T0_T1_cc,
345 gen_op_sbbw_T0_T1_cc,
348 gen_op_adcl_T0_T1_cc,
349 gen_op_sbbl_T0_T1_cc,
353 static const int cc_op_arithb[8] = {
364 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
366 gen_op_rolb_T0_T1_cc,
367 gen_op_rorb_T0_T1_cc,
368 gen_op_rclb_T0_T1_cc,
369 gen_op_rcrb_T0_T1_cc,
370 gen_op_shlb_T0_T1_cc,
371 gen_op_shrb_T0_T1_cc,
372 gen_op_shlb_T0_T1_cc,
373 gen_op_sarb_T0_T1_cc,
376 gen_op_rolw_T0_T1_cc,
377 gen_op_rorw_T0_T1_cc,
378 gen_op_rclw_T0_T1_cc,
379 gen_op_rcrw_T0_T1_cc,
380 gen_op_shlw_T0_T1_cc,
381 gen_op_shrw_T0_T1_cc,
382 gen_op_shlw_T0_T1_cc,
383 gen_op_sarw_T0_T1_cc,
386 gen_op_roll_T0_T1_cc,
387 gen_op_rorl_T0_T1_cc,
388 gen_op_rcll_T0_T1_cc,
389 gen_op_rcrl_T0_T1_cc,
390 gen_op_shll_T0_T1_cc,
391 gen_op_shrl_T0_T1_cc,
392 gen_op_shll_T0_T1_cc,
393 gen_op_sarl_T0_T1_cc,
397 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
399 gen_op_shldw_T0_T1_im_cc,
400 gen_op_shrdw_T0_T1_im_cc,
403 gen_op_shldl_T0_T1_im_cc,
404 gen_op_shrdl_T0_T1_im_cc,
408 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
410 gen_op_shldw_T0_T1_ECX_cc,
411 gen_op_shrdw_T0_T1_ECX_cc,
414 gen_op_shldl_T0_T1_ECX_cc,
415 gen_op_shrdl_T0_T1_ECX_cc,
419 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
422 gen_op_btsw_T0_T1_cc,
423 gen_op_btrw_T0_T1_cc,
424 gen_op_btcw_T0_T1_cc,
428 gen_op_btsl_T0_T1_cc,
429 gen_op_btrl_T0_T1_cc,
430 gen_op_btcl_T0_T1_cc,
434 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
445 static GenOpFunc *gen_op_lds_T0_A0[3] = {
450 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
455 /* sign does not matter */
456 static GenOpFunc *gen_op_ld_T0_A0[3] = {
462 static GenOpFunc *gen_op_ld_T1_A0[3] = {
468 static GenOpFunc *gen_op_st_T0_A0[3] = {
474 static GenOpFunc *gen_op_movs[6] = {
483 static GenOpFunc *gen_op_stos[6] = {
492 static GenOpFunc *gen_op_lods[6] = {
501 static GenOpFunc *gen_op_scas[9] = {
513 static GenOpFunc *gen_op_cmps[9] = {
525 static GenOpFunc *gen_op_ins[6] = {
535 static GenOpFunc *gen_op_outs[6] = {
544 static GenOpFunc *gen_op_in[3] = {
550 static GenOpFunc *gen_op_out[3] = {
567 static GenOpFunc2 *gen_jcc_slow[8] = {
578 static GenOpFunc2 *gen_jcc_sub[3][8] = {
611 static GenOpFunc *gen_setcc_slow[8] = {
622 static GenOpFunc *gen_setcc_sub[3][8] = {
627 gen_op_setbe_T0_subb,
631 gen_op_setle_T0_subb,
637 gen_op_setbe_T0_subw,
641 gen_op_setle_T0_subw,
647 gen_op_setbe_T0_subl,
651 gen_op_setle_T0_subl,
655 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
661 gen_op_fsubr_ST0_FT0,
663 gen_op_fdivr_ST0_FT0,
666 /* NOTE the exception in "r" op ordering */
667 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
672 gen_op_fsubr_STN_ST0,
674 gen_op_fdivr_STN_ST0,
678 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
681 gen_op_mov_TN_reg[ot][0][d]();
683 gen_op_mov_TN_reg[ot][1][s]();
684 if (op == OP_ADCL || op == OP_SBBL) {
685 if (s1->cc_op != CC_OP_DYNAMIC)
686 gen_op_set_cc_op(s1->cc_op);
687 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
688 s1->cc_op = CC_OP_DYNAMIC;
690 gen_op_arith_T0_T1_cc[op]();
691 s1->cc_op = cc_op_arithb[op] + ot;
693 if (d != OR_TMP0 && op != OP_CMPL)
694 gen_op_mov_reg_T0[ot][d]();
697 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
699 gen_op_movl_T1_im(c);
700 gen_op(s1, op, ot, d, OR_TMP1);
703 static void gen_inc(DisasContext *s1, int ot, int d, int c)
706 gen_op_mov_TN_reg[ot][0][d]();
707 if (s1->cc_op != CC_OP_DYNAMIC)
708 gen_op_set_cc_op(s1->cc_op);
711 s1->cc_op = CC_OP_INCB + ot;
714 s1->cc_op = CC_OP_DECB + ot;
717 gen_op_mov_reg_T0[ot][d]();
720 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
723 gen_op_mov_TN_reg[ot][0][d]();
725 gen_op_mov_TN_reg[ot][1][s]();
726 /* for zero counts, flags are not updated, so must do it dynamically */
727 if (s1->cc_op != CC_OP_DYNAMIC)
728 gen_op_set_cc_op(s1->cc_op);
730 gen_op_shift_T0_T1_cc[ot][op]();
733 gen_op_mov_reg_T0[ot][d]();
734 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
737 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
739 /* currently not optimized */
740 gen_op_movl_T1_im(c);
741 gen_shift(s1, op, ot, d, OR_TMP1);
744 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
751 int reg1, reg2, opreg;
754 mod = (modrm >> 6) & 3;
765 code = ldub(s->pc++);
766 scale = (code >> 6) & 3;
767 index = (code >> 3) & 7;
782 disp = (int8_t)ldub(s->pc++);
794 if (havebase || (havesib && (index != 4 || scale != 0))) {
796 reg1 = OR_EAX + base;
797 if (havesib && index != 4) {
799 reg2 = index + OR_EAX;
801 reg1 = index + OR_EAX;
804 /* XXX: disp only ? */
805 if (reg2 == OR_ZERO) {
806 /* op: disp + (reg1 << scale) */
807 if (reg1 == OR_ZERO) {
808 gen_op_movl_A0_im(disp);
809 } else if (scale == 0 && disp == 0) {
810 gen_op_movl_A0_reg[reg1]();
812 gen_op_movl_A0_im(disp);
813 gen_op_addl_A0_reg_sN[scale][reg1]();
816 /* op: disp + reg1 + (reg2 << scale) */
818 gen_op_movl_A0_im(disp);
819 gen_op_addl_A0_reg_sN[0][reg1]();
821 gen_op_movl_A0_reg[reg1]();
823 gen_op_addl_A0_reg_sN[scale][reg2]();
831 gen_op_movl_A0_im(disp);
838 disp = (int8_t)ldub(s->pc++);
848 gen_op_movl_A0_reg[R_EBX]();
849 gen_op_addl_A0_reg_sN[0][R_ESI]();
852 gen_op_movl_A0_reg[R_EBX]();
853 gen_op_addl_A0_reg_sN[0][R_EDI]();
856 gen_op_movl_A0_reg[R_EBP]();
857 gen_op_addl_A0_reg_sN[0][R_ESI]();
860 gen_op_movl_A0_reg[R_EBP]();
861 gen_op_addl_A0_reg_sN[0][R_EDI]();
864 gen_op_movl_A0_reg[R_ESI]();
867 gen_op_movl_A0_reg[R_EDI]();
870 gen_op_movl_A0_reg[R_EBP]();
874 gen_op_movl_A0_reg[R_EBX]();
878 gen_op_addl_A0_im(disp);
879 gen_op_andl_A0_ffff();
888 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
890 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
892 int mod, rm, opreg, disp;
894 mod = (modrm >> 6) & 3;
899 gen_op_mov_TN_reg[ot][0][reg]();
900 gen_op_mov_reg_T0[ot][rm]();
902 gen_op_mov_TN_reg[ot][0][rm]();
904 gen_op_mov_reg_T0[ot][reg]();
907 gen_lea_modrm(s, modrm, &opreg, &disp);
910 gen_op_mov_TN_reg[ot][0][reg]();
911 gen_op_st_T0_A0[ot]();
913 gen_op_ld_T0_A0[ot]();
915 gen_op_mov_reg_T0[ot][reg]();
920 static inline uint32_t insn_get(DisasContext *s, int ot)
942 static void gen_jcc(DisasContext *s, int b, int val)
948 jcc_op = (b >> 1) & 7;
950 /* we optimize the cmp/jcc case */
954 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
959 /* some jumps are easy to compute */
986 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
989 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
997 if (s->cc_op != CC_OP_DYNAMIC)
998 gen_op_set_cc_op(s->cc_op);
999 func = gen_jcc_slow[jcc_op];
1003 func(val, (long)s->pc);
1005 func((long)s->pc, val);
1009 static void gen_setcc(DisasContext *s, int b)
1015 jcc_op = (b >> 1) & 7;
1017 /* we optimize the cmp/jcc case */
1021 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1026 /* some jumps are easy to compute */
1044 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1047 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1055 if (s->cc_op != CC_OP_DYNAMIC)
1056 gen_op_set_cc_op(s->cc_op);
1057 func = gen_setcc_slow[jcc_op];
1066 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1067 is set to true if the instruction sets the PC (last instruction of
1069 long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1071 int b, prefixes, aflag, dflag;
1073 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1079 // cur_pc = s->pc; /* for insn generation */
1083 /* check prefixes */
1086 prefixes |= PREFIX_REPZ;
1089 prefixes |= PREFIX_REPNZ;
1092 prefixes |= PREFIX_LOCK;
1095 prefixes |= PREFIX_CS;
1098 prefixes |= PREFIX_SS;
1101 prefixes |= PREFIX_DS;
1104 prefixes |= PREFIX_ES;
1107 prefixes |= PREFIX_FS;
1110 prefixes |= PREFIX_GS;
1113 prefixes |= PREFIX_DATA;
1116 prefixes |= PREFIX_ADR;
1119 prefixes |= PREFIX_FWAIT;
1123 if (prefixes & PREFIX_DATA)
1125 if (prefixes & PREFIX_ADR)
1128 s->prefix = prefixes;
1132 /* now check op code */
1136 /**************************/
1137 /* extended op code */
1138 b = ldub(s->pc++) | 0x100;
1141 /**************************/
1159 ot = dflag ? OT_LONG : OT_WORD;
1162 case 0: /* OP Ev, Gv */
1163 modrm = ldub(s->pc++);
1164 reg = ((modrm >> 3) & 7) + OR_EAX;
1165 mod = (modrm >> 6) & 3;
1168 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1169 gen_op_ld_T0_A0[ot]();
1172 opreg = OR_EAX + rm;
1174 gen_op(s, op, ot, opreg, reg);
1175 if (mod != 3 && op != 7) {
1176 gen_op_st_T0_A0[ot]();
1179 case 1: /* OP Gv, Ev */
1180 modrm = ldub(s->pc++);
1181 mod = (modrm >> 6) & 3;
1182 reg = ((modrm >> 3) & 7) + OR_EAX;
1185 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1186 gen_op_ld_T1_A0[ot]();
1189 opreg = OR_EAX + rm;
1191 gen_op(s, op, ot, reg, opreg);
1193 case 2: /* OP A, Iv */
1194 val = insn_get(s, ot);
1195 gen_opi(s, op, ot, OR_EAX, val);
1201 case 0x80: /* GRP1 */
1210 ot = dflag ? OT_LONG : OT_WORD;
1212 modrm = ldub(s->pc++);
1213 mod = (modrm >> 6) & 3;
1215 op = (modrm >> 3) & 7;
1218 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1219 gen_op_ld_T0_A0[ot]();
1222 opreg = rm + OR_EAX;
1229 val = insn_get(s, ot);
1232 val = (int8_t)insn_get(s, OT_BYTE);
1236 gen_opi(s, op, ot, opreg, val);
1237 if (op != 7 && mod != 3) {
1238 gen_op_st_T0_A0[ot]();
1243 /**************************/
1244 /* inc, dec, and other misc arith */
1245 case 0x40 ... 0x47: /* inc Gv */
1246 ot = dflag ? OT_LONG : OT_WORD;
1247 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1249 case 0x48 ... 0x4f: /* dec Gv */
1250 ot = dflag ? OT_LONG : OT_WORD;
1251 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1253 case 0xf6: /* GRP3 */
1258 ot = dflag ? OT_LONG : OT_WORD;
1260 modrm = ldub(s->pc++);
1261 mod = (modrm >> 6) & 3;
1263 op = (modrm >> 3) & 7;
1265 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1266 gen_op_ld_T0_A0[ot]();
1268 gen_op_mov_TN_reg[ot][0][rm]();
1273 val = insn_get(s, ot);
1274 gen_op_movl_T1_im(val);
1275 gen_op_testl_T0_T1_cc();
1276 s->cc_op = CC_OP_LOGICB + ot;
1281 gen_op_st_T0_A0[ot]();
1283 gen_op_mov_reg_T0[ot][rm]();
1287 gen_op_negl_T0_cc();
1289 gen_op_st_T0_A0[ot]();
1291 gen_op_mov_reg_T0[ot][rm]();
1293 s->cc_op = CC_OP_SUBB + ot;
1298 gen_op_mulb_AL_T0();
1301 gen_op_mulw_AX_T0();
1305 gen_op_mull_EAX_T0();
1308 s->cc_op = CC_OP_MUL;
1313 gen_op_imulb_AL_T0();
1316 gen_op_imulw_AX_T0();
1320 gen_op_imull_EAX_T0();
1323 s->cc_op = CC_OP_MUL;
1328 gen_op_divb_AL_T0();
1331 gen_op_divw_AX_T0();
1335 gen_op_divl_EAX_T0();
1342 gen_op_idivb_AL_T0();
1345 gen_op_idivw_AX_T0();
1349 gen_op_idivl_EAX_T0();
1354 error("GRP3: bad instruction");
1359 case 0xfe: /* GRP4 */
1360 case 0xff: /* GRP5 */
1364 ot = dflag ? OT_LONG : OT_WORD;
1366 modrm = ldub(s->pc++);
1367 mod = (modrm >> 6) & 3;
1369 op = (modrm >> 3) & 7;
1370 if (op >= 2 && b == 0xfe) {
1371 error("GRP4: bad instruction");
1375 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1376 gen_op_ld_T0_A0[ot]();
1378 gen_op_mov_TN_reg[ot][0][rm]();
1382 case 0: /* inc Ev */
1383 gen_inc(s, ot, OR_TMP0, 1);
1385 gen_op_st_T0_A0[ot]();
1387 gen_op_mov_reg_T0[ot][rm]();
1389 case 1: /* dec Ev */
1390 gen_inc(s, ot, OR_TMP0, -1);
1392 gen_op_st_T0_A0[ot]();
1394 gen_op_mov_reg_T0[ot][rm]();
1396 case 2: /* call Ev */
1397 gen_op_movl_T1_im((long)s->pc);
1402 case 4: /* jmp Ev */
1406 case 6: /* push Ev */
1410 error("GRP5: bad instruction");
1415 case 0x84: /* test Ev, Gv */
1420 ot = dflag ? OT_LONG : OT_WORD;
1422 modrm = ldub(s->pc++);
1423 mod = (modrm >> 6) & 3;
1425 reg = (modrm >> 3) & 7;
1427 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1428 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1429 gen_op_testl_T0_T1_cc();
1430 s->cc_op = CC_OP_LOGICB + ot;
1433 case 0xa8: /* test eAX, Iv */
1438 ot = dflag ? OT_LONG : OT_WORD;
1439 val = insn_get(s, ot);
1441 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1442 gen_op_movl_T1_im(val);
1443 gen_op_testl_T0_T1_cc();
1444 s->cc_op = CC_OP_LOGICB + ot;
1447 case 0x98: /* CWDE/CBW */
1449 gen_op_movswl_EAX_AX();
1451 gen_op_movsbw_AX_AL();
1453 case 0x99: /* CDQ/CWD */
1455 gen_op_movslq_EDX_EAX();
1457 gen_op_movswl_DX_AX();
1459 case 0x1af: /* imul Gv, Ev */
1460 case 0x69: /* imul Gv, Ev, I */
1462 ot = dflag ? OT_LONG : OT_WORD;
1463 modrm = ldub(s->pc++);
1464 reg = ((modrm >> 3) & 7) + OR_EAX;
1465 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1467 val = insn_get(s, ot);
1468 gen_op_movl_T1_im(val);
1469 } else if (b == 0x6b) {
1470 val = insn_get(s, OT_BYTE);
1471 gen_op_movl_T1_im(val);
1473 gen_op_mov_TN_reg[ot][1][reg]();
1476 if (ot == OT_LONG) {
1477 gen_op_imull_T0_T1();
1479 gen_op_imulw_T0_T1();
1481 gen_op_mov_reg_T0[ot][reg]();
1482 s->cc_op = CC_OP_MUL;
1485 /**************************/
1487 case 0x50 ... 0x57: /* push */
1488 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1491 case 0x58 ... 0x5f: /* pop */
1493 gen_op_mov_reg_T0[OT_LONG][b & 7]();
1495 case 0x68: /* push Iv */
1497 ot = dflag ? OT_LONG : OT_WORD;
1499 val = insn_get(s, ot);
1501 val = (int8_t)insn_get(s, OT_BYTE);
1502 gen_op_movl_T0_im(val);
1505 case 0x8f: /* pop Ev */
1506 ot = dflag ? OT_LONG : OT_WORD;
1507 modrm = ldub(s->pc++);
1509 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1511 case 0xc9: /* leave */
1512 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1513 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1515 gen_op_mov_reg_T0[OT_LONG][R_EBP]();
1517 /**************************/
1520 case 0x89: /* mov Gv, Ev */
1524 ot = dflag ? OT_LONG : OT_WORD;
1525 modrm = ldub(s->pc++);
1526 reg = (modrm >> 3) & 7;
1528 /* generate a generic store */
1529 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1532 case 0xc7: /* mov Ev, Iv */
1536 ot = dflag ? OT_LONG : OT_WORD;
1537 modrm = ldub(s->pc++);
1538 mod = (modrm >> 6) & 3;
1540 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1541 val = insn_get(s, ot);
1542 gen_op_movl_T0_im(val);
1544 gen_op_st_T0_A0[ot]();
1546 gen_op_mov_reg_T0[ot][modrm & 7]();
1549 case 0x8b: /* mov Ev, Gv */
1553 ot = dflag ? OT_LONG : OT_WORD;
1554 modrm = ldub(s->pc++);
1555 reg = (modrm >> 3) & 7;
1557 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1558 gen_op_mov_reg_T0[ot][reg]();
1561 case 0x1b6: /* movzbS Gv, Eb */
1562 case 0x1b7: /* movzwS Gv, Eb */
1563 case 0x1be: /* movsbS Gv, Eb */
1564 case 0x1bf: /* movswS Gv, Eb */
1567 /* d_ot is the size of destination */
1568 d_ot = dflag + OT_WORD;
1569 /* ot is the size of source */
1570 ot = (b & 1) + OT_BYTE;
1571 modrm = ldub(s->pc++);
1572 reg = ((modrm >> 3) & 7) + OR_EAX;
1573 mod = (modrm >> 6) & 3;
1577 gen_op_mov_TN_reg[ot][0][rm]();
1578 switch(ot | (b & 8)) {
1580 gen_op_movzbl_T0_T0();
1583 gen_op_movsbl_T0_T0();
1586 gen_op_movzwl_T0_T0();
1590 gen_op_movswl_T0_T0();
1593 gen_op_mov_reg_T0[d_ot][reg]();
1595 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1597 gen_op_lds_T0_A0[ot]();
1599 gen_op_ldu_T0_A0[ot]();
1601 gen_op_mov_reg_T0[d_ot][reg]();
1606 case 0x8d: /* lea */
1607 ot = dflag ? OT_LONG : OT_WORD;
1608 modrm = ldub(s->pc++);
1609 reg = (modrm >> 3) & 7;
1611 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1612 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
1615 case 0xa0: /* mov EAX, Ov */
1617 case 0xa2: /* mov Ov, EAX */
1622 ot = dflag ? OT_LONG : OT_WORD;
1624 offset_addr = insn_get(s, OT_LONG);
1626 offset_addr = insn_get(s, OT_WORD);
1627 gen_op_movl_A0_im(offset_addr);
1629 gen_op_ld_T0_A0[ot]();
1630 gen_op_mov_reg_T0[ot][R_EAX]();
1632 gen_op_mov_TN_reg[ot][0][R_EAX]();
1633 gen_op_st_T0_A0[ot]();
1637 case 0xb0 ... 0xb7: /* mov R, Ib */
1638 val = insn_get(s, OT_BYTE);
1639 gen_op_movl_T0_im(val);
1640 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
1642 case 0xb8 ... 0xbf: /* mov R, Iv */
1643 ot = dflag ? OT_LONG : OT_WORD;
1644 val = insn_get(s, ot);
1645 reg = OR_EAX + (b & 7);
1646 gen_op_movl_T0_im(val);
1647 gen_op_mov_reg_T0[ot][reg]();
1650 case 0x91 ... 0x97: /* xchg R, EAX */
1651 ot = dflag ? OT_LONG : OT_WORD;
1653 gen_op_mov_TN_reg[ot][0][reg]();
1654 gen_op_mov_TN_reg[ot][1][R_EAX]();
1655 gen_op_mov_reg_T0[ot][R_EAX]();
1656 gen_op_mov_reg_T1[ot][reg]();
1659 case 0x87: /* xchg Ev, Gv */
1663 ot = dflag ? OT_LONG : OT_WORD;
1664 modrm = ldub(s->pc++);
1665 reg = (modrm >> 3) & 7;
1667 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1668 gen_op_mov_TN_reg[ot][0][reg]();
1669 gen_op_ld_T1_A0[ot]();
1670 gen_op_st_T0_A0[ot]();
1671 gen_op_mov_reg_T1[ot][reg]();
1674 /************************/
1685 ot = dflag ? OT_LONG : OT_WORD;
1687 modrm = ldub(s->pc++);
1688 mod = (modrm >> 6) & 3;
1690 op = (modrm >> 3) & 7;
1693 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1694 gen_op_ld_T0_A0[ot]();
1697 opreg = rm + OR_EAX;
1702 gen_shift(s, op, ot, opreg, OR_ECX);
1705 shift = ldub(s->pc++);
1707 gen_shifti(s, op, ot, opreg, shift);
1711 gen_op_st_T0_A0[ot]();
1726 case 0x1a4: /* shld imm */
1730 case 0x1a5: /* shld cl */
1734 case 0x1ac: /* shrd imm */
1738 case 0x1ad: /* shrd cl */
1742 ot = dflag ? OT_LONG : OT_WORD;
1743 modrm = ldub(s->pc++);
1744 mod = (modrm >> 6) & 3;
1746 reg = (modrm >> 3) & 7;
1749 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1750 gen_op_ld_T0_A0[ot]();
1752 gen_op_mov_TN_reg[ot][0][rm]();
1754 gen_op_mov_TN_reg[ot][1][reg]();
1757 val = ldub(s->pc++);
1760 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
1761 if (op == 0 && ot != OT_WORD)
1762 s->cc_op = CC_OP_SHLB + ot;
1764 s->cc_op = CC_OP_SARB + ot;
1767 if (s->cc_op != CC_OP_DYNAMIC)
1768 gen_op_set_cc_op(s->cc_op);
1769 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
1770 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1773 gen_op_st_T0_A0[ot]();
1775 gen_op_mov_reg_T0[ot][rm]();
1779 /************************/
1782 modrm = ldub(s->pc++);
1783 mod = (modrm >> 6) & 3;
1785 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
1789 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1791 case 0x00 ... 0x07: /* fxxxs */
1792 case 0x10 ... 0x17: /* fixxxl */
1793 case 0x20 ... 0x27: /* fxxxl */
1794 case 0x30 ... 0x37: /* fixxx */
1801 gen_op_flds_FT0_A0();
1804 gen_op_fildl_FT0_A0();
1807 gen_op_fldl_FT0_A0();
1811 gen_op_fild_FT0_A0();
1815 gen_op_fp_arith_ST0_FT0[op1]();
1817 /* fcomp needs pop */
1822 case 0x08: /* flds */
1823 case 0x0a: /* fsts */
1824 case 0x0b: /* fstps */
1825 case 0x18: /* fildl */
1826 case 0x1a: /* fistl */
1827 case 0x1b: /* fistpl */
1828 case 0x28: /* fldl */
1829 case 0x2a: /* fstl */
1830 case 0x2b: /* fstpl */
1831 case 0x38: /* filds */
1832 case 0x3a: /* fists */
1833 case 0x3b: /* fistps */
1840 gen_op_flds_ST0_A0();
1843 gen_op_fildl_ST0_A0();
1846 gen_op_fldl_ST0_A0();
1850 gen_op_fild_ST0_A0();
1857 gen_op_fsts_ST0_A0();
1860 gen_op_fistl_ST0_A0();
1863 gen_op_fstl_ST0_A0();
1867 gen_op_fist_ST0_A0();
1875 case 0x0d: /* fldcw mem */
1878 case 0x0f: /* fnstcw mem */
1881 case 0x1d: /* fldt mem */
1883 gen_op_fldt_ST0_A0();
1885 case 0x1f: /* fstpt mem */
1886 gen_op_fstt_ST0_A0();
1889 case 0x2f: /* fnstsw mem */
1892 case 0x3c: /* fbld */
1894 gen_op_fbld_ST0_A0();
1896 case 0x3e: /* fbstp */
1897 gen_op_fbst_ST0_A0();
1900 case 0x3d: /* fildll */
1902 gen_op_fildll_ST0_A0();
1904 case 0x3f: /* fistpll */
1905 gen_op_fistll_ST0_A0();
1909 error("unhandled FPm [op=0x%02x]\n", op);
1913 /* register float ops */
1917 case 0x08: /* fld sti */
1919 gen_op_fmov_ST0_STN((opreg + 1) & 7);
1921 case 0x09: /* fxchg sti */
1922 gen_op_fxchg_ST0_STN(opreg);
1924 case 0x0a: /* grp d9/2 */
1929 error("unhandled FP GRP d9/2\n");
1933 case 0x0c: /* grp d9/4 */
1943 gen_op_fcom_ST0_FT0();
1952 case 0x0d: /* grp d9/5 */
1961 gen_op_fldl2t_ST0();
1965 gen_op_fldl2e_ST0();
1973 gen_op_fldlg2_ST0();
1977 gen_op_fldln2_ST0();
1988 case 0x0e: /* grp d9/6 */
1999 case 3: /* fpatan */
2002 case 4: /* fxtract */
2005 case 5: /* fprem1 */
2008 case 6: /* fdecstp */
2012 case 7: /* fincstp */
2017 case 0x0f: /* grp d9/7 */
2022 case 1: /* fyl2xp1 */
2028 case 3: /* fsincos */
2031 case 5: /* fscale */
2034 case 4: /* frndint */
2046 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2047 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2048 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2054 gen_op_fp_arith_STN_ST0[op1](opreg);
2058 gen_op_fmov_FT0_STN(opreg);
2059 gen_op_fp_arith_ST0_FT0[op1]();
2063 case 0x02: /* fcom */
2064 gen_op_fmov_FT0_STN(opreg);
2065 gen_op_fcom_ST0_FT0();
2067 case 0x03: /* fcomp */
2068 gen_op_fmov_FT0_STN(opreg);
2069 gen_op_fcom_ST0_FT0();
2072 case 0x15: /* da/5 */
2074 case 1: /* fucompp */
2075 gen_op_fmov_FT0_STN(1);
2076 gen_op_fucom_ST0_FT0();
2084 case 0x2a: /* fst sti */
2085 gen_op_fmov_STN_ST0(opreg);
2087 case 0x2b: /* fstp sti */
2088 gen_op_fmov_STN_ST0(opreg);
2091 case 0x2c: /* fucom st(i) */
2092 gen_op_fmov_FT0_STN(opreg);
2093 gen_op_fucom_ST0_FT0();
2095 case 0x2d: /* fucomp st(i) */
2096 gen_op_fmov_FT0_STN(opreg);
2097 gen_op_fucom_ST0_FT0();
2100 case 0x33: /* de/3 */
2102 case 1: /* fcompp */
2103 gen_op_fmov_FT0_STN(1);
2104 gen_op_fcom_ST0_FT0();
2112 case 0x3c: /* df/4 */
2115 gen_op_fnstsw_EAX();
2118 error("unhandled FP %x df/4\n", rm);
2123 error("unhandled FPr [op=0x%x]\n", op);
2128 /************************/
2130 case 0xa4: /* movsS */
2135 ot = dflag ? OT_LONG : OT_WORD;
2136 if (prefixes & PREFIX_REPZ) {
2137 gen_op_movs[3 + ot]();
2143 case 0xaa: /* stosS */
2148 ot = dflag ? OT_LONG : OT_WORD;
2149 if (prefixes & PREFIX_REPZ) {
2150 gen_op_stos[3 + ot]();
2155 case 0xac: /* lodsS */
2160 ot = dflag ? OT_LONG : OT_WORD;
2161 if (prefixes & PREFIX_REPZ) {
2162 gen_op_lods[3 + ot]();
2167 case 0xae: /* scasS */
2172 ot = dflag ? OT_LONG : OT_WORD;
2173 if (prefixes & PREFIX_REPNZ) {
2174 if (s->cc_op != CC_OP_DYNAMIC)
2175 gen_op_set_cc_op(s->cc_op);
2176 gen_op_scas[6 + ot]();
2177 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2178 } else if (prefixes & PREFIX_REPZ) {
2179 if (s->cc_op != CC_OP_DYNAMIC)
2180 gen_op_set_cc_op(s->cc_op);
2181 gen_op_scas[3 + ot]();
2182 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2185 s->cc_op = CC_OP_SUBB + ot;
2189 case 0xa6: /* cmpsS */
2194 ot = dflag ? OT_LONG : OT_WORD;
2195 if (prefixes & PREFIX_REPNZ) {
2196 if (s->cc_op != CC_OP_DYNAMIC)
2197 gen_op_set_cc_op(s->cc_op);
2198 gen_op_cmps[6 + ot]();
2199 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2200 } else if (prefixes & PREFIX_REPZ) {
2201 if (s->cc_op != CC_OP_DYNAMIC)
2202 gen_op_set_cc_op(s->cc_op);
2203 gen_op_cmps[3 + ot]();
2204 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2207 s->cc_op = CC_OP_SUBB + ot;
2211 /************************/
2213 case 0x6c: /* insS */
2218 ot = dflag ? OT_LONG : OT_WORD;
2219 if (prefixes & PREFIX_REPZ) {
2220 gen_op_ins[3 + ot]();
2225 case 0x6e: /* outsS */
2230 ot = dflag ? OT_LONG : OT_WORD;
2231 if (prefixes & PREFIX_REPZ) {
2232 gen_op_outs[3 + ot]();
2242 ot = dflag ? OT_LONG : OT_WORD;
2243 val = ldub(s->pc++);
2244 gen_op_movl_T0_im(val);
2246 gen_op_mov_reg_T1[ot][R_EAX]();
2253 ot = dflag ? OT_LONG : OT_WORD;
2254 val = ldub(s->pc++);
2255 gen_op_movl_T0_im(val);
2256 gen_op_mov_TN_reg[ot][1][R_EAX]();
2264 ot = dflag ? OT_LONG : OT_WORD;
2265 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2267 gen_op_mov_reg_T1[ot][R_EAX]();
2274 ot = dflag ? OT_LONG : OT_WORD;
2275 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2276 gen_op_mov_TN_reg[ot][1][R_EAX]();
2280 /************************/
2282 case 0xc2: /* ret im */
2283 /* XXX: handle stack pop ? */
2287 gen_op_addl_ESP_im(val);
2291 case 0xc3: /* ret */
2296 case 0xe8: /* call */
2297 val = insn_get(s, OT_LONG);
2299 gen_op_movl_T1_im((long)s->pc);
2304 case 0xe9: /* jmp */
2305 val = insn_get(s, OT_LONG);
2310 case 0xeb: /* jmp Jb */
2311 val = (int8_t)insn_get(s, OT_BYTE);
2316 case 0x70 ... 0x7f: /* jcc Jb */
2317 val = (int8_t)insn_get(s, OT_BYTE);
2320 case 0x180 ... 0x18f: /* jcc Jv */
2322 val = insn_get(s, OT_LONG);
2324 val = (int16_t)insn_get(s, OT_WORD);
2326 val += (long)s->pc; /* XXX: fix 16 bit wrap */
2332 case 0x190 ... 0x19f:
2333 modrm = ldub(s->pc++);
2335 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2338 /************************/
2340 case 0x9c: /* pushf */
2341 if (s->cc_op != CC_OP_DYNAMIC)
2342 gen_op_set_cc_op(s->cc_op);
2343 gen_op_movl_T0_eflags();
2346 case 0x9d: /* popf */
2348 gen_op_movl_eflags_T0();
2349 s->cc_op = CC_OP_EFLAGS;
2351 case 0x9e: /* sahf */
2352 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
2353 if (s->cc_op != CC_OP_DYNAMIC)
2354 gen_op_set_cc_op(s->cc_op);
2355 gen_op_movb_eflags_T0();
2356 s->cc_op = CC_OP_EFLAGS;
2358 case 0x9f: /* lahf */
2359 if (s->cc_op != CC_OP_DYNAMIC)
2360 gen_op_set_cc_op(s->cc_op);
2361 gen_op_movl_T0_eflags();
2362 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
2364 case 0xf5: /* cmc */
2365 if (s->cc_op != CC_OP_DYNAMIC)
2366 gen_op_set_cc_op(s->cc_op);
2368 s->cc_op = CC_OP_EFLAGS;
2370 case 0xf8: /* clc */
2371 if (s->cc_op != CC_OP_DYNAMIC)
2372 gen_op_set_cc_op(s->cc_op);
2374 s->cc_op = CC_OP_EFLAGS;
2376 case 0xf9: /* stc */
2377 if (s->cc_op != CC_OP_DYNAMIC)
2378 gen_op_set_cc_op(s->cc_op);
2380 s->cc_op = CC_OP_EFLAGS;
2382 case 0xfc: /* cld */
2385 case 0xfd: /* std */
2389 /************************/
2390 /* bit operations */
2391 case 0x1ba: /* bt/bts/btr/btc Gv, im */
2392 ot = dflag ? OT_LONG : OT_WORD;
2393 modrm = ldub(s->pc++);
2394 op = (modrm >> 3) & 7;
2395 mod = (modrm >> 6) & 3;
2398 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2399 gen_op_ld_T0_A0[ot]();
2401 gen_op_mov_TN_reg[ot][0][rm]();
2404 val = ldub(s->pc++);
2405 gen_op_movl_T1_im(val);
2409 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2410 s->cc_op = CC_OP_SARB + ot;
2413 gen_op_st_T0_A0[ot]();
2415 gen_op_mov_reg_T0[ot][rm]();
2418 case 0x1a3: /* bt Gv, Ev */
2421 case 0x1ab: /* bts */
2424 case 0x1b3: /* btr */
2427 case 0x1bb: /* btc */
2430 ot = dflag ? OT_LONG : OT_WORD;
2431 modrm = ldub(s->pc++);
2432 reg = (modrm >> 3) & 7;
2433 mod = (modrm >> 6) & 3;
2435 gen_op_mov_TN_reg[OT_LONG][1][reg]();
2437 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2438 /* specific case: we need to add a displacement */
2440 gen_op_add_bitw_A0_T1();
2442 gen_op_add_bitl_A0_T1();
2443 gen_op_ld_T0_A0[ot]();
2445 gen_op_mov_TN_reg[ot][0][rm]();
2447 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2448 s->cc_op = CC_OP_SARB + ot;
2451 gen_op_st_T0_A0[ot]();
2453 gen_op_mov_reg_T0[ot][rm]();
2456 case 0x1bc: /* bsf */
2457 case 0x1bd: /* bsr */
2458 ot = dflag ? OT_LONG : OT_WORD;
2459 modrm = ldub(s->pc++);
2460 reg = (modrm >> 3) & 7;
2461 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2462 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
2463 /* NOTE: we always write back the result. Intel doc says it is
2464 undefined if T0 == 0 */
2465 gen_op_mov_reg_T0[ot][reg]();
2466 s->cc_op = CC_OP_LOGICB + ot;
2468 /************************/
2470 case 0x90: /* nop */
2472 case 0xcc: /* int3 */
2473 gen_op_int3((long)pc_start);
2476 case 0xcd: /* int N */
2477 val = ldub(s->pc++);
2478 /* XXX: currently we ignore the interrupt number */
2479 gen_op_int_im((long)pc_start);
2482 case 0xce: /* into */
2483 if (s->cc_op != CC_OP_DYNAMIC)
2484 gen_op_set_cc_op(s->cc_op);
2485 gen_op_into((long)pc_start, (long)s->pc);
2488 case 0x1c8 ... 0x1cf: /* bswap reg */
2490 gen_op_mov_TN_reg[OT_LONG][0][reg]();
2492 gen_op_mov_reg_T0[OT_LONG][reg]();
2496 case 0x1a2: /* cpuid */
2501 error("unknown opcode %x", b);
2507 /* return the next pc */
2508 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
2509 int *gen_code_size_ptr, uint8_t *pc_start)
2511 DisasContext dc1, *dc = &dc1;
2512 uint8_t *gen_code_end, *pc_ptr;
2516 struct disassemble_info disasm_info;
2519 dc->cc_op = CC_OP_DYNAMIC;
2520 gen_code_ptr = gen_code_buf;
2521 gen_code_end = gen_code_buf + max_code_size - 4096;
2527 ret = disas_insn(dc, pc_ptr, &is_jmp);
2529 error("unknown instruction at PC=0x%x B=%02x %02x",
2530 pc_ptr, pc_ptr[0], pc_ptr[1]);
2531 pc_ptr = (void *)ret;
2532 } while (!is_jmp && gen_code_ptr < gen_code_end);
2533 /* we must store the eflags state if it is not already done */
2534 if (dc->cc_op != CC_OP_DYNAMIC)
2535 gen_op_set_cc_op(dc->cc_op);
2537 /* we add an additionnal jmp to update the simulated PC */
2541 *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
2548 INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
2550 disasm_info.flavour = bfd_get_flavour (abfd);
2551 disasm_info.arch = bfd_get_arch (abfd);
2552 disasm_info.mach = bfd_get_mach (abfd);
2554 #ifdef WORDS_BIGENDIAN
2555 disasm_info.endian = BFD_ENDIAN_BIG;
2557 disasm_info.endian = BFD_ENDIAN_LITTLE;
2559 fprintf(logfile, "IN:\n");
2560 disasm_info.buffer = pc_start;
2561 disasm_info.buffer_vma = (unsigned long)pc_start;
2562 disasm_info.buffer_length = pc_ptr - pc_start;
2564 while (pc < pc_ptr) {
2565 fprintf(logfile, "0x%08lx: ", (long)pc);
2566 count = print_insn_i386((unsigned long)pc, &disasm_info);
2567 fprintf(logfile, "\n");
2570 fprintf(logfile, "\n");
2573 disasm_info.buffer = pc;
2574 disasm_info.buffer_vma = (unsigned long)pc;
2575 disasm_info.buffer_length = *gen_code_size_ptr;
2576 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
2577 while (pc < gen_code_ptr) {
2578 fprintf(logfile, "0x%08lx: ", (long)pc);
2579 count = print_insn_i386((unsigned long)pc, &disasm_info);
2580 fprintf(logfile, "\n");
2583 fprintf(logfile, "\n");
2589 CPUX86State *cpu_x86_init(void)
2594 env = malloc(sizeof(CPUX86State));
2597 memset(env, 0, sizeof(CPUX86State));
2598 /* basic FPU init */
2599 for(i = 0;i < 8; i++)
2603 env->cc_op = CC_OP_EFLAGS;
2608 void cpu_x86_close(CPUX86State *env)