4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 /* XXX: move that elsewhere */
36 static uint16_t *gen_opc_ptr;
37 static uint32_t *gen_opparam_ptr;
39 #define PREFIX_REPZ 0x01
40 #define PREFIX_REPNZ 0x02
41 #define PREFIX_LOCK 0x04
42 #define PREFIX_DATA 0x08
43 #define PREFIX_ADR 0x10
45 typedef struct DisasContext {
46 /* current insn context */
47 int override; /* -1 if no override */
50 uint8_t *pc; /* pc = eip + cs_base */
51 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
52 static state change (stop translation) */
53 /* current block context */
54 uint8_t *cs_base; /* base of CS segment */
55 int code32; /* 32 bit code segment */
56 int ss32; /* 32 bit stack segment */
57 int cc_op; /* current CC operation */
58 int addseg; /* non zero if either DS/ES/SS have a non zero base */
59 int f_st; /* currently unused */
60 int vm86; /* vm86 mode */
63 int tf; /* TF cpu flag */
64 struct TranslationBlock *tb;
65 int popl_esp_hack; /* for correct popl with esp base handling */
68 /* i386 arith/logic operations */
88 OP_SHL1, /* undocumented */
93 #define DEF(s, n, copy_size) INDEX_op_ ## s,
99 #include "gen-op-i386.h"
110 /* I386 int registers */
111 OR_EAX, /* MUST be even numbered */
119 OR_TMP0, /* temporary operand register */
121 OR_A0, /* temporary register used when doing address evaluation */
122 OR_ZERO, /* fixed zero register */
126 typedef void (GenOpFunc)(void);
127 typedef void (GenOpFunc1)(long);
128 typedef void (GenOpFunc2)(long, long);
129 typedef void (GenOpFunc3)(long, long, long);
131 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
164 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
197 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
220 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
290 static GenOpFunc *gen_op_movl_A0_reg[8] = {
301 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
313 gen_op_addl_A0_EAX_s1,
314 gen_op_addl_A0_ECX_s1,
315 gen_op_addl_A0_EDX_s1,
316 gen_op_addl_A0_EBX_s1,
317 gen_op_addl_A0_ESP_s1,
318 gen_op_addl_A0_EBP_s1,
319 gen_op_addl_A0_ESI_s1,
320 gen_op_addl_A0_EDI_s1,
323 gen_op_addl_A0_EAX_s2,
324 gen_op_addl_A0_ECX_s2,
325 gen_op_addl_A0_EDX_s2,
326 gen_op_addl_A0_EBX_s2,
327 gen_op_addl_A0_ESP_s2,
328 gen_op_addl_A0_EBP_s2,
329 gen_op_addl_A0_ESI_s2,
330 gen_op_addl_A0_EDI_s2,
333 gen_op_addl_A0_EAX_s3,
334 gen_op_addl_A0_ECX_s3,
335 gen_op_addl_A0_EDX_s3,
336 gen_op_addl_A0_EBX_s3,
337 gen_op_addl_A0_ESP_s3,
338 gen_op_addl_A0_EBP_s3,
339 gen_op_addl_A0_ESI_s3,
340 gen_op_addl_A0_EDI_s3,
344 static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
346 gen_op_cmovw_EAX_T1_T0,
347 gen_op_cmovw_ECX_T1_T0,
348 gen_op_cmovw_EDX_T1_T0,
349 gen_op_cmovw_EBX_T1_T0,
350 gen_op_cmovw_ESP_T1_T0,
351 gen_op_cmovw_EBP_T1_T0,
352 gen_op_cmovw_ESI_T1_T0,
353 gen_op_cmovw_EDI_T1_T0,
356 gen_op_cmovl_EAX_T1_T0,
357 gen_op_cmovl_ECX_T1_T0,
358 gen_op_cmovl_EDX_T1_T0,
359 gen_op_cmovl_EBX_T1_T0,
360 gen_op_cmovl_ESP_T1_T0,
361 gen_op_cmovl_EBP_T1_T0,
362 gen_op_cmovl_ESI_T1_T0,
363 gen_op_cmovl_EDI_T1_T0,
367 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
368 gen_op_addl_T0_T1_cc,
372 gen_op_andl_T0_T1_cc,
373 gen_op_subl_T0_T1_cc,
374 gen_op_xorl_T0_T1_cc,
375 gen_op_cmpl_T0_T1_cc,
378 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
380 gen_op_adcb_T0_T1_cc,
381 gen_op_sbbb_T0_T1_cc,
384 gen_op_adcw_T0_T1_cc,
385 gen_op_sbbw_T0_T1_cc,
388 gen_op_adcl_T0_T1_cc,
389 gen_op_sbbl_T0_T1_cc,
393 static const int cc_op_arithb[8] = {
404 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
405 gen_op_cmpxchgb_T0_T1_EAX_cc,
406 gen_op_cmpxchgw_T0_T1_EAX_cc,
407 gen_op_cmpxchgl_T0_T1_EAX_cc,
410 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
412 gen_op_rolb_T0_T1_cc,
413 gen_op_rorb_T0_T1_cc,
414 gen_op_rclb_T0_T1_cc,
415 gen_op_rcrb_T0_T1_cc,
416 gen_op_shlb_T0_T1_cc,
417 gen_op_shrb_T0_T1_cc,
418 gen_op_shlb_T0_T1_cc,
419 gen_op_sarb_T0_T1_cc,
422 gen_op_rolw_T0_T1_cc,
423 gen_op_rorw_T0_T1_cc,
424 gen_op_rclw_T0_T1_cc,
425 gen_op_rcrw_T0_T1_cc,
426 gen_op_shlw_T0_T1_cc,
427 gen_op_shrw_T0_T1_cc,
428 gen_op_shlw_T0_T1_cc,
429 gen_op_sarw_T0_T1_cc,
432 gen_op_roll_T0_T1_cc,
433 gen_op_rorl_T0_T1_cc,
434 gen_op_rcll_T0_T1_cc,
435 gen_op_rcrl_T0_T1_cc,
436 gen_op_shll_T0_T1_cc,
437 gen_op_shrl_T0_T1_cc,
438 gen_op_shll_T0_T1_cc,
439 gen_op_sarl_T0_T1_cc,
443 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
445 gen_op_shldw_T0_T1_im_cc,
446 gen_op_shrdw_T0_T1_im_cc,
449 gen_op_shldl_T0_T1_im_cc,
450 gen_op_shrdl_T0_T1_im_cc,
454 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
456 gen_op_shldw_T0_T1_ECX_cc,
457 gen_op_shrdw_T0_T1_ECX_cc,
460 gen_op_shldl_T0_T1_ECX_cc,
461 gen_op_shrdl_T0_T1_ECX_cc,
465 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
468 gen_op_btsw_T0_T1_cc,
469 gen_op_btrw_T0_T1_cc,
470 gen_op_btcw_T0_T1_cc,
474 gen_op_btsl_T0_T1_cc,
475 gen_op_btrl_T0_T1_cc,
476 gen_op_btcl_T0_T1_cc,
480 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
491 static GenOpFunc *gen_op_lds_T0_A0[3] = {
496 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
501 /* sign does not matter */
502 static GenOpFunc *gen_op_ld_T0_A0[3] = {
508 static GenOpFunc *gen_op_ld_T1_A0[3] = {
514 static GenOpFunc *gen_op_st_T0_A0[3] = {
520 /* the _a32 and _a16 string operations use A0 as the base register. */
522 #define STRINGOP(x) \
523 gen_op_ ## x ## b_fast, \
524 gen_op_ ## x ## w_fast, \
525 gen_op_ ## x ## l_fast, \
526 gen_op_ ## x ## b_a32, \
527 gen_op_ ## x ## w_a32, \
528 gen_op_ ## x ## l_a32, \
529 gen_op_ ## x ## b_a16, \
530 gen_op_ ## x ## w_a16, \
531 gen_op_ ## x ## l_a16,
533 static GenOpFunc *gen_op_movs[9 * 2] = {
538 static GenOpFunc *gen_op_stos[9 * 2] = {
543 static GenOpFunc *gen_op_lods[9 * 2] = {
548 static GenOpFunc *gen_op_scas[9 * 3] = {
554 static GenOpFunc *gen_op_cmps[9 * 3] = {
560 static GenOpFunc *gen_op_ins[9 * 2] = {
566 static GenOpFunc *gen_op_outs[9 * 2] = {
572 static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
576 override = s->override;
579 if (s->addseg && override < 0)
582 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
590 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
591 /* 16 address, always override */
597 static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
614 static GenOpFunc *gen_op_in[3] = {
620 static GenOpFunc *gen_op_out[3] = {
637 static GenOpFunc3 *gen_jcc_sub[3][8] = {
669 static GenOpFunc2 *gen_op_loop[2][4] = {
684 static GenOpFunc *gen_setcc_slow[8] = {
695 static GenOpFunc *gen_setcc_sub[3][8] = {
700 gen_op_setbe_T0_subb,
704 gen_op_setle_T0_subb,
710 gen_op_setbe_T0_subw,
714 gen_op_setle_T0_subw,
720 gen_op_setbe_T0_subl,
724 gen_op_setle_T0_subl,
728 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
734 gen_op_fsubr_ST0_FT0,
736 gen_op_fdivr_ST0_FT0,
739 /* NOTE the exception in "r" op ordering */
740 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
745 gen_op_fsubr_STN_ST0,
747 gen_op_fdivr_STN_ST0,
751 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
754 gen_op_mov_TN_reg[ot][0][d]();
756 gen_op_mov_TN_reg[ot][1][s]();
757 if (op == OP_ADCL || op == OP_SBBL) {
758 if (s1->cc_op != CC_OP_DYNAMIC)
759 gen_op_set_cc_op(s1->cc_op);
760 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
761 s1->cc_op = CC_OP_DYNAMIC;
763 gen_op_arith_T0_T1_cc[op]();
764 s1->cc_op = cc_op_arithb[op] + ot;
766 if (d != OR_TMP0 && op != OP_CMPL)
767 gen_op_mov_reg_T0[ot][d]();
770 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
772 gen_op_movl_T1_im(c);
773 gen_op(s1, op, ot, d, OR_TMP1);
776 static void gen_inc(DisasContext *s1, int ot, int d, int c)
779 gen_op_mov_TN_reg[ot][0][d]();
780 if (s1->cc_op != CC_OP_DYNAMIC)
781 gen_op_set_cc_op(s1->cc_op);
784 s1->cc_op = CC_OP_INCB + ot;
787 s1->cc_op = CC_OP_DECB + ot;
790 gen_op_mov_reg_T0[ot][d]();
793 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
796 gen_op_mov_TN_reg[ot][0][d]();
798 gen_op_mov_TN_reg[ot][1][s]();
799 /* for zero counts, flags are not updated, so must do it dynamically */
800 if (s1->cc_op != CC_OP_DYNAMIC)
801 gen_op_set_cc_op(s1->cc_op);
803 gen_op_shift_T0_T1_cc[ot][op]();
806 gen_op_mov_reg_T0[ot][d]();
807 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
810 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
812 /* currently not optimized */
813 gen_op_movl_T1_im(c);
814 gen_shift(s1, op, ot, d, OR_TMP1);
817 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
824 int mod, rm, code, override, must_add_seg;
826 override = s->override;
827 must_add_seg = s->addseg;
830 mod = (modrm >> 6) & 3;
842 code = ldub(s->pc++);
843 scale = (code >> 6) & 3;
844 index = (code >> 3) & 7;
859 disp = (int8_t)ldub(s->pc++);
869 /* for correct popl handling with esp */
870 if (base == 4 && s->popl_esp_hack)
872 gen_op_movl_A0_reg[base]();
874 gen_op_addl_A0_im(disp);
876 gen_op_movl_A0_im(disp);
878 /* XXX: index == 4 is always invalid */
879 if (havesib && (index != 4 || scale != 0)) {
880 gen_op_addl_A0_reg_sN[scale][index]();
884 if (base == R_EBP || base == R_ESP)
889 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
897 gen_op_movl_A0_im(disp);
898 rm = 0; /* avoid SS override */
905 disp = (int8_t)ldub(s->pc++);
915 gen_op_movl_A0_reg[R_EBX]();
916 gen_op_addl_A0_reg_sN[0][R_ESI]();
919 gen_op_movl_A0_reg[R_EBX]();
920 gen_op_addl_A0_reg_sN[0][R_EDI]();
923 gen_op_movl_A0_reg[R_EBP]();
924 gen_op_addl_A0_reg_sN[0][R_ESI]();
927 gen_op_movl_A0_reg[R_EBP]();
928 gen_op_addl_A0_reg_sN[0][R_EDI]();
931 gen_op_movl_A0_reg[R_ESI]();
934 gen_op_movl_A0_reg[R_EDI]();
937 gen_op_movl_A0_reg[R_EBP]();
941 gen_op_movl_A0_reg[R_EBX]();
945 gen_op_addl_A0_im(disp);
946 gen_op_andl_A0_ffff();
950 if (rm == 2 || rm == 3 || rm == 6)
955 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
965 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
967 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
969 int mod, rm, opreg, disp;
971 mod = (modrm >> 6) & 3;
976 gen_op_mov_TN_reg[ot][0][reg]();
977 gen_op_mov_reg_T0[ot][rm]();
979 gen_op_mov_TN_reg[ot][0][rm]();
981 gen_op_mov_reg_T0[ot][reg]();
984 gen_lea_modrm(s, modrm, &opreg, &disp);
987 gen_op_mov_TN_reg[ot][0][reg]();
988 gen_op_st_T0_A0[ot]();
990 gen_op_ld_T0_A0[ot]();
992 gen_op_mov_reg_T0[ot][reg]();
997 static inline uint32_t insn_get(DisasContext *s, int ot)
1019 static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1021 TranslationBlock *tb;
1026 jcc_op = (b >> 1) & 7;
1028 /* we optimize the cmp/jcc case */
1032 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1035 /* some jumps are easy to compute */
1062 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1065 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1077 if (s->cc_op != CC_OP_DYNAMIC)
1078 gen_op_set_cc_op(s->cc_op);
1081 gen_setcc_slow[jcc_op]();
1087 func((long)tb, val, next_eip);
1089 func((long)tb, next_eip, val);
1094 static void gen_setcc(DisasContext *s, int b)
1100 jcc_op = (b >> 1) & 7;
1102 /* we optimize the cmp/jcc case */
1106 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1111 /* some jumps are easy to compute */
1129 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1132 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1140 if (s->cc_op != CC_OP_DYNAMIC)
1141 gen_op_set_cc_op(s->cc_op);
1142 func = gen_setcc_slow[jcc_op];
1151 /* move T0 to seg_reg and compute if the CPU state may change */
1152 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1155 gen_op_movl_seg_T0(seg_reg, cur_eip);
1157 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1158 if (!s->addseg && seg_reg < R_FS)
1159 s->is_jmp = 2; /* abort translation because the register may
1160 have a non zero base */
1163 /* generate a push. It depends on ss32, addseg and dflag */
1164 static void gen_push_T0(DisasContext *s)
1174 gen_op_pushl_ss32_T0();
1176 gen_op_pushw_ss32_T0();
1180 gen_op_pushl_ss16_T0();
1182 gen_op_pushw_ss16_T0();
1186 /* two step pop is necessary for precise exceptions */
1187 static void gen_pop_T0(DisasContext *s)
1197 gen_op_popl_ss32_T0();
1199 gen_op_popw_ss32_T0();
1203 gen_op_popl_ss16_T0();
1205 gen_op_popw_ss16_T0();
1209 static inline void gen_stack_update(DisasContext *s, int addend)
1213 gen_op_addl_ESP_2();
1214 else if (addend == 4)
1215 gen_op_addl_ESP_4();
1217 gen_op_addl_ESP_im(addend);
1220 gen_op_addw_ESP_2();
1221 else if (addend == 4)
1222 gen_op_addw_ESP_4();
1224 gen_op_addw_ESP_im(addend);
1228 static void gen_pop_update(DisasContext *s)
1230 gen_stack_update(s, 2 << s->dflag);
1233 static void gen_stack_A0(DisasContext *s)
1235 gen_op_movl_A0_ESP();
1237 gen_op_andl_A0_ffff();
1238 gen_op_movl_T1_A0();
1240 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1243 /* NOTE: wrap around in 16 bit not fully handled */
1244 static void gen_pusha(DisasContext *s)
1247 gen_op_movl_A0_ESP();
1248 gen_op_addl_A0_im(-16 << s->dflag);
1250 gen_op_andl_A0_ffff();
1251 gen_op_movl_T1_A0();
1253 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1254 for(i = 0;i < 8; i++) {
1255 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1256 gen_op_st_T0_A0[OT_WORD + s->dflag]();
1257 gen_op_addl_A0_im(2 << s->dflag);
1259 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1262 /* NOTE: wrap around in 16 bit not fully handled */
1263 static void gen_popa(DisasContext *s)
1266 gen_op_movl_A0_ESP();
1268 gen_op_andl_A0_ffff();
1269 gen_op_movl_T1_A0();
1270 gen_op_addl_T1_im(16 << s->dflag);
1272 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1273 for(i = 0;i < 8; i++) {
1274 /* ESP is not reloaded */
1276 gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1277 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1279 gen_op_addl_A0_im(2 << s->dflag);
1281 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1284 /* NOTE: wrap around in 16 bit not fully handled */
1285 /* XXX: check this */
1286 static void gen_enter(DisasContext *s, int esp_addend, int level)
1288 int ot, level1, addend, opsize;
1290 ot = s->dflag + OT_WORD;
1293 opsize = 2 << s->dflag;
1295 gen_op_movl_A0_ESP();
1296 gen_op_addl_A0_im(-opsize);
1298 gen_op_andl_A0_ffff();
1299 gen_op_movl_T1_A0();
1301 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1303 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1304 gen_op_st_T0_A0[ot]();
1307 gen_op_addl_A0_im(-opsize);
1308 gen_op_addl_T0_im(-opsize);
1309 gen_op_st_T0_A0[ot]();
1311 gen_op_addl_A0_im(-opsize);
1312 /* XXX: add st_T1_A0 ? */
1313 gen_op_movl_T0_T1();
1314 gen_op_st_T0_A0[ot]();
1316 gen_op_mov_reg_T1[ot][R_EBP]();
1317 addend = -esp_addend;
1319 addend -= opsize * (level1 + 1);
1320 gen_op_addl_T1_im(addend);
1321 gen_op_mov_reg_T1[ot][R_ESP]();
1324 static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1326 if (s->cc_op != CC_OP_DYNAMIC)
1327 gen_op_set_cc_op(s->cc_op);
1328 gen_op_jmp_im(cur_eip);
1329 gen_op_raise_exception(trapno);
1333 /* an interrupt is different from an exception because of the
1334 priviledge checks */
1335 static void gen_interrupt(DisasContext *s, int intno,
1336 unsigned int cur_eip, unsigned int next_eip)
1338 if (s->cc_op != CC_OP_DYNAMIC)
1339 gen_op_set_cc_op(s->cc_op);
1340 gen_op_jmp_im(cur_eip);
1341 gen_op_raise_interrupt(intno, next_eip);
1345 /* generate a jump to eip. No segment change must happen before as a
1346 direct call to the next block may occur */
1347 static void gen_jmp(DisasContext *s, unsigned int eip)
1349 TranslationBlock *tb = s->tb;
1351 if (s->cc_op != CC_OP_DYNAMIC)
1352 gen_op_set_cc_op(s->cc_op);
1353 gen_op_jmp_tb_next((long)tb, eip);
1357 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1358 is set to true if the instruction sets the PC (last instruction of
1360 long disas_insn(DisasContext *s, uint8_t *pc_start)
1362 int b, prefixes, aflag, dflag;
1364 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1365 unsigned int next_eip;
1375 /* check prefixes */
1378 prefixes |= PREFIX_REPZ;
1381 prefixes |= PREFIX_REPNZ;
1384 prefixes |= PREFIX_LOCK;
1405 prefixes |= PREFIX_DATA;
1408 prefixes |= PREFIX_ADR;
1412 if (prefixes & PREFIX_DATA)
1414 if (prefixes & PREFIX_ADR)
1417 s->prefix = prefixes;
1421 /* lock generation */
1422 if (prefixes & PREFIX_LOCK)
1425 /* now check op code */
1429 /**************************/
1430 /* extended op code */
1431 b = ldub(s->pc++) | 0x100;
1434 /**************************/
1452 ot = dflag ? OT_LONG : OT_WORD;
1455 case 0: /* OP Ev, Gv */
1456 modrm = ldub(s->pc++);
1457 reg = ((modrm >> 3) & 7) + OR_EAX;
1458 mod = (modrm >> 6) & 3;
1461 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1462 gen_op_ld_T0_A0[ot]();
1465 opreg = OR_EAX + rm;
1467 gen_op(s, op, ot, opreg, reg);
1468 if (mod != 3 && op != 7) {
1469 gen_op_st_T0_A0[ot]();
1472 case 1: /* OP Gv, Ev */
1473 modrm = ldub(s->pc++);
1474 mod = (modrm >> 6) & 3;
1475 reg = ((modrm >> 3) & 7) + OR_EAX;
1478 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1479 gen_op_ld_T1_A0[ot]();
1482 opreg = OR_EAX + rm;
1484 gen_op(s, op, ot, reg, opreg);
1486 case 2: /* OP A, Iv */
1487 val = insn_get(s, ot);
1488 gen_opi(s, op, ot, OR_EAX, val);
1494 case 0x80: /* GRP1 */
1503 ot = dflag ? OT_LONG : OT_WORD;
1505 modrm = ldub(s->pc++);
1506 mod = (modrm >> 6) & 3;
1508 op = (modrm >> 3) & 7;
1511 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1512 gen_op_ld_T0_A0[ot]();
1515 opreg = rm + OR_EAX;
1522 val = insn_get(s, ot);
1525 val = (int8_t)insn_get(s, OT_BYTE);
1529 gen_opi(s, op, ot, opreg, val);
1530 if (op != 7 && mod != 3) {
1531 gen_op_st_T0_A0[ot]();
1536 /**************************/
1537 /* inc, dec, and other misc arith */
1538 case 0x40 ... 0x47: /* inc Gv */
1539 ot = dflag ? OT_LONG : OT_WORD;
1540 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1542 case 0x48 ... 0x4f: /* dec Gv */
1543 ot = dflag ? OT_LONG : OT_WORD;
1544 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1546 case 0xf6: /* GRP3 */
1551 ot = dflag ? OT_LONG : OT_WORD;
1553 modrm = ldub(s->pc++);
1554 mod = (modrm >> 6) & 3;
1556 op = (modrm >> 3) & 7;
1558 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1559 gen_op_ld_T0_A0[ot]();
1561 gen_op_mov_TN_reg[ot][0][rm]();
1566 val = insn_get(s, ot);
1567 gen_op_movl_T1_im(val);
1568 gen_op_testl_T0_T1_cc();
1569 s->cc_op = CC_OP_LOGICB + ot;
1574 gen_op_st_T0_A0[ot]();
1576 gen_op_mov_reg_T0[ot][rm]();
1580 gen_op_negl_T0_cc();
1582 gen_op_st_T0_A0[ot]();
1584 gen_op_mov_reg_T0[ot][rm]();
1586 s->cc_op = CC_OP_SUBB + ot;
1591 gen_op_mulb_AL_T0();
1594 gen_op_mulw_AX_T0();
1598 gen_op_mull_EAX_T0();
1601 s->cc_op = CC_OP_MUL;
1606 gen_op_imulb_AL_T0();
1609 gen_op_imulw_AX_T0();
1613 gen_op_imull_EAX_T0();
1616 s->cc_op = CC_OP_MUL;
1621 gen_op_divb_AL_T0(pc_start - s->cs_base);
1624 gen_op_divw_AX_T0(pc_start - s->cs_base);
1628 gen_op_divl_EAX_T0(pc_start - s->cs_base);
1635 gen_op_idivb_AL_T0(pc_start - s->cs_base);
1638 gen_op_idivw_AX_T0(pc_start - s->cs_base);
1642 gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1651 case 0xfe: /* GRP4 */
1652 case 0xff: /* GRP5 */
1656 ot = dflag ? OT_LONG : OT_WORD;
1658 modrm = ldub(s->pc++);
1659 mod = (modrm >> 6) & 3;
1661 op = (modrm >> 3) & 7;
1662 if (op >= 2 && b == 0xfe) {
1666 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1667 if (op != 3 && op != 5)
1668 gen_op_ld_T0_A0[ot]();
1670 gen_op_mov_TN_reg[ot][0][rm]();
1674 case 0: /* inc Ev */
1675 gen_inc(s, ot, OR_TMP0, 1);
1677 gen_op_st_T0_A0[ot]();
1679 gen_op_mov_reg_T0[ot][rm]();
1681 case 1: /* dec Ev */
1682 gen_inc(s, ot, OR_TMP0, -1);
1684 gen_op_st_T0_A0[ot]();
1686 gen_op_mov_reg_T0[ot][rm]();
1688 case 2: /* call Ev */
1689 /* XXX: optimize if memory (no and is necessary) */
1691 gen_op_andl_T0_ffff();
1693 next_eip = s->pc - s->cs_base;
1694 gen_op_movl_T0_im(next_eip);
1698 case 3: /* lcall Ev */
1699 /* push return segment + offset */
1700 gen_op_movl_T0_seg(R_CS);
1702 next_eip = s->pc - s->cs_base;
1703 gen_op_movl_T0_im(next_eip);
1706 gen_op_ld_T1_A0[ot]();
1707 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1708 gen_op_lduw_T0_A0();
1709 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1710 gen_op_movl_T0_T1();
1714 case 4: /* jmp Ev */
1716 gen_op_andl_T0_ffff();
1720 case 5: /* ljmp Ev */
1721 gen_op_ld_T1_A0[ot]();
1722 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1723 gen_op_lduw_T0_A0();
1725 /* we compute EIP to handle the exception case */
1726 gen_op_jmp_im(pc_start - s->cs_base);
1727 gen_op_ljmp_T0_T1();
1729 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
1730 gen_op_movl_T0_T1();
1735 case 6: /* push Ev */
1743 case 0x84: /* test Ev, Gv */
1748 ot = dflag ? OT_LONG : OT_WORD;
1750 modrm = ldub(s->pc++);
1751 mod = (modrm >> 6) & 3;
1753 reg = (modrm >> 3) & 7;
1755 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1756 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1757 gen_op_testl_T0_T1_cc();
1758 s->cc_op = CC_OP_LOGICB + ot;
1761 case 0xa8: /* test eAX, Iv */
1766 ot = dflag ? OT_LONG : OT_WORD;
1767 val = insn_get(s, ot);
1769 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1770 gen_op_movl_T1_im(val);
1771 gen_op_testl_T0_T1_cc();
1772 s->cc_op = CC_OP_LOGICB + ot;
1775 case 0x98: /* CWDE/CBW */
1777 gen_op_movswl_EAX_AX();
1779 gen_op_movsbw_AX_AL();
1781 case 0x99: /* CDQ/CWD */
1783 gen_op_movslq_EDX_EAX();
1785 gen_op_movswl_DX_AX();
1787 case 0x1af: /* imul Gv, Ev */
1788 case 0x69: /* imul Gv, Ev, I */
1790 ot = dflag ? OT_LONG : OT_WORD;
1791 modrm = ldub(s->pc++);
1792 reg = ((modrm >> 3) & 7) + OR_EAX;
1793 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1795 val = insn_get(s, ot);
1796 gen_op_movl_T1_im(val);
1797 } else if (b == 0x6b) {
1798 val = insn_get(s, OT_BYTE);
1799 gen_op_movl_T1_im(val);
1801 gen_op_mov_TN_reg[ot][1][reg]();
1804 if (ot == OT_LONG) {
1805 gen_op_imull_T0_T1();
1807 gen_op_imulw_T0_T1();
1809 gen_op_mov_reg_T0[ot][reg]();
1810 s->cc_op = CC_OP_MUL;
1813 case 0x1c1: /* xadd Ev, Gv */
1817 ot = dflag ? OT_LONG : OT_WORD;
1818 modrm = ldub(s->pc++);
1819 reg = (modrm >> 3) & 7;
1820 mod = (modrm >> 6) & 3;
1823 gen_op_mov_TN_reg[ot][0][reg]();
1824 gen_op_mov_TN_reg[ot][1][rm]();
1825 gen_op_addl_T0_T1_cc();
1826 gen_op_mov_reg_T0[ot][rm]();
1827 gen_op_mov_reg_T1[ot][reg]();
1829 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1830 gen_op_mov_TN_reg[ot][0][reg]();
1831 gen_op_ld_T1_A0[ot]();
1832 gen_op_addl_T0_T1_cc();
1833 gen_op_st_T0_A0[ot]();
1834 gen_op_mov_reg_T1[ot][reg]();
1836 s->cc_op = CC_OP_ADDB + ot;
1839 case 0x1b1: /* cmpxchg Ev, Gv */
1843 ot = dflag ? OT_LONG : OT_WORD;
1844 modrm = ldub(s->pc++);
1845 reg = (modrm >> 3) & 7;
1846 mod = (modrm >> 6) & 3;
1847 gen_op_mov_TN_reg[ot][1][reg]();
1850 gen_op_mov_TN_reg[ot][0][rm]();
1851 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1852 gen_op_mov_reg_T0[ot][rm]();
1854 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1855 gen_op_ld_T0_A0[ot]();
1856 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1857 gen_op_st_T0_A0[ot]();
1859 s->cc_op = CC_OP_SUBB + ot;
1861 case 0x1c7: /* cmpxchg8b */
1862 modrm = ldub(s->pc++);
1863 mod = (modrm >> 6) & 3;
1866 if (s->cc_op != CC_OP_DYNAMIC)
1867 gen_op_set_cc_op(s->cc_op);
1868 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1870 s->cc_op = CC_OP_EFLAGS;
1873 /**************************/
1875 case 0x50 ... 0x57: /* push */
1876 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1879 case 0x58 ... 0x5f: /* pop */
1880 ot = dflag ? OT_LONG : OT_WORD;
1882 gen_op_mov_reg_T0[ot][b & 7]();
1885 case 0x60: /* pusha */
1888 case 0x61: /* popa */
1891 case 0x68: /* push Iv */
1893 ot = dflag ? OT_LONG : OT_WORD;
1895 val = insn_get(s, ot);
1897 val = (int8_t)insn_get(s, OT_BYTE);
1898 gen_op_movl_T0_im(val);
1901 case 0x8f: /* pop Ev */
1902 ot = dflag ? OT_LONG : OT_WORD;
1903 modrm = ldub(s->pc++);
1905 s->popl_esp_hack = 1;
1906 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1907 s->popl_esp_hack = 0;
1910 case 0xc8: /* enter */
1915 level = ldub(s->pc++);
1916 gen_enter(s, val, level);
1919 case 0xc9: /* leave */
1920 /* XXX: exception not precise (ESP is updated before potential exception) */
1922 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1923 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1925 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1926 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1929 ot = dflag ? OT_LONG : OT_WORD;
1930 gen_op_mov_reg_T0[ot][R_EBP]();
1933 case 0x06: /* push es */
1934 case 0x0e: /* push cs */
1935 case 0x16: /* push ss */
1936 case 0x1e: /* push ds */
1937 gen_op_movl_T0_seg(b >> 3);
1940 case 0x1a0: /* push fs */
1941 case 0x1a8: /* push gs */
1942 gen_op_movl_T0_seg((b >> 3) & 7);
1945 case 0x07: /* pop es */
1946 case 0x17: /* pop ss */
1947 case 0x1f: /* pop ds */
1949 gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
1952 case 0x1a1: /* pop fs */
1953 case 0x1a9: /* pop gs */
1955 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
1959 /**************************/
1962 case 0x89: /* mov Gv, Ev */
1966 ot = dflag ? OT_LONG : OT_WORD;
1967 modrm = ldub(s->pc++);
1968 reg = (modrm >> 3) & 7;
1970 /* generate a generic store */
1971 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
1974 case 0xc7: /* mov Ev, Iv */
1978 ot = dflag ? OT_LONG : OT_WORD;
1979 modrm = ldub(s->pc++);
1980 mod = (modrm >> 6) & 3;
1982 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1983 val = insn_get(s, ot);
1984 gen_op_movl_T0_im(val);
1986 gen_op_st_T0_A0[ot]();
1988 gen_op_mov_reg_T0[ot][modrm & 7]();
1991 case 0x8b: /* mov Ev, Gv */
1995 ot = dflag ? OT_LONG : OT_WORD;
1996 modrm = ldub(s->pc++);
1997 reg = (modrm >> 3) & 7;
1999 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2000 gen_op_mov_reg_T0[ot][reg]();
2002 case 0x8e: /* mov seg, Gv */
2003 ot = dflag ? OT_LONG : OT_WORD;
2004 modrm = ldub(s->pc++);
2005 reg = (modrm >> 3) & 7;
2006 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2007 if (reg >= 6 || reg == R_CS)
2009 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2011 case 0x8c: /* mov Gv, seg */
2012 ot = dflag ? OT_LONG : OT_WORD;
2013 modrm = ldub(s->pc++);
2014 reg = (modrm >> 3) & 7;
2017 gen_op_movl_T0_seg(reg);
2018 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2021 case 0x1b6: /* movzbS Gv, Eb */
2022 case 0x1b7: /* movzwS Gv, Eb */
2023 case 0x1be: /* movsbS Gv, Eb */
2024 case 0x1bf: /* movswS Gv, Eb */
2027 /* d_ot is the size of destination */
2028 d_ot = dflag + OT_WORD;
2029 /* ot is the size of source */
2030 ot = (b & 1) + OT_BYTE;
2031 modrm = ldub(s->pc++);
2032 reg = ((modrm >> 3) & 7) + OR_EAX;
2033 mod = (modrm >> 6) & 3;
2037 gen_op_mov_TN_reg[ot][0][rm]();
2038 switch(ot | (b & 8)) {
2040 gen_op_movzbl_T0_T0();
2043 gen_op_movsbl_T0_T0();
2046 gen_op_movzwl_T0_T0();
2050 gen_op_movswl_T0_T0();
2053 gen_op_mov_reg_T0[d_ot][reg]();
2055 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2057 gen_op_lds_T0_A0[ot]();
2059 gen_op_ldu_T0_A0[ot]();
2061 gen_op_mov_reg_T0[d_ot][reg]();
2066 case 0x8d: /* lea */
2067 ot = dflag ? OT_LONG : OT_WORD;
2068 modrm = ldub(s->pc++);
2069 reg = (modrm >> 3) & 7;
2070 /* we must ensure that no segment is added */
2074 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2076 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2079 case 0xa0: /* mov EAX, Ov */
2081 case 0xa2: /* mov Ov, EAX */
2086 ot = dflag ? OT_LONG : OT_WORD;
2088 offset_addr = insn_get(s, OT_LONG);
2090 offset_addr = insn_get(s, OT_WORD);
2091 gen_op_movl_A0_im(offset_addr);
2092 /* handle override */
2094 int override, must_add_seg;
2095 must_add_seg = s->addseg;
2096 if (s->override >= 0) {
2097 override = s->override;
2103 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2107 gen_op_ld_T0_A0[ot]();
2108 gen_op_mov_reg_T0[ot][R_EAX]();
2110 gen_op_mov_TN_reg[ot][0][R_EAX]();
2111 gen_op_st_T0_A0[ot]();
2114 case 0xd7: /* xlat */
2115 gen_op_movl_A0_reg[R_EBX]();
2116 gen_op_addl_A0_AL();
2118 gen_op_andl_A0_ffff();
2119 /* handle override */
2121 int override, must_add_seg;
2122 must_add_seg = s->addseg;
2124 if (s->override >= 0) {
2125 override = s->override;
2131 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2134 gen_op_ldub_T0_A0();
2135 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2137 case 0xb0 ... 0xb7: /* mov R, Ib */
2138 val = insn_get(s, OT_BYTE);
2139 gen_op_movl_T0_im(val);
2140 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2142 case 0xb8 ... 0xbf: /* mov R, Iv */
2143 ot = dflag ? OT_LONG : OT_WORD;
2144 val = insn_get(s, ot);
2145 reg = OR_EAX + (b & 7);
2146 gen_op_movl_T0_im(val);
2147 gen_op_mov_reg_T0[ot][reg]();
2150 case 0x91 ... 0x97: /* xchg R, EAX */
2151 ot = dflag ? OT_LONG : OT_WORD;
2156 case 0x87: /* xchg Ev, Gv */
2160 ot = dflag ? OT_LONG : OT_WORD;
2161 modrm = ldub(s->pc++);
2162 reg = (modrm >> 3) & 7;
2163 mod = (modrm >> 6) & 3;
2167 gen_op_mov_TN_reg[ot][0][reg]();
2168 gen_op_mov_TN_reg[ot][1][rm]();
2169 gen_op_mov_reg_T0[ot][rm]();
2170 gen_op_mov_reg_T1[ot][reg]();
2172 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2173 gen_op_mov_TN_reg[ot][0][reg]();
2174 /* for xchg, lock is implicit */
2175 if (!(prefixes & PREFIX_LOCK))
2177 gen_op_ld_T1_A0[ot]();
2178 gen_op_st_T0_A0[ot]();
2179 if (!(prefixes & PREFIX_LOCK))
2181 gen_op_mov_reg_T1[ot][reg]();
2184 case 0xc4: /* les Gv */
2187 case 0xc5: /* lds Gv */
2190 case 0x1b2: /* lss Gv */
2193 case 0x1b4: /* lfs Gv */
2196 case 0x1b5: /* lgs Gv */
2199 ot = dflag ? OT_LONG : OT_WORD;
2200 modrm = ldub(s->pc++);
2201 reg = (modrm >> 3) & 7;
2202 mod = (modrm >> 6) & 3;
2205 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2206 gen_op_ld_T1_A0[ot]();
2207 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2208 /* load the segment first to handle exceptions properly */
2209 gen_op_lduw_T0_A0();
2210 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2211 /* then put the data */
2212 gen_op_mov_reg_T1[ot][reg]();
2215 /************************/
2226 ot = dflag ? OT_LONG : OT_WORD;
2228 modrm = ldub(s->pc++);
2229 mod = (modrm >> 6) & 3;
2231 op = (modrm >> 3) & 7;
2234 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2235 gen_op_ld_T0_A0[ot]();
2238 opreg = rm + OR_EAX;
2243 gen_shift(s, op, ot, opreg, OR_ECX);
2246 shift = ldub(s->pc++);
2248 gen_shifti(s, op, ot, opreg, shift);
2252 gen_op_st_T0_A0[ot]();
2267 case 0x1a4: /* shld imm */
2271 case 0x1a5: /* shld cl */
2275 case 0x1ac: /* shrd imm */
2279 case 0x1ad: /* shrd cl */
2283 ot = dflag ? OT_LONG : OT_WORD;
2284 modrm = ldub(s->pc++);
2285 mod = (modrm >> 6) & 3;
2287 reg = (modrm >> 3) & 7;
2290 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2291 gen_op_ld_T0_A0[ot]();
2293 gen_op_mov_TN_reg[ot][0][rm]();
2295 gen_op_mov_TN_reg[ot][1][reg]();
2298 val = ldub(s->pc++);
2301 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2302 if (op == 0 && ot != OT_WORD)
2303 s->cc_op = CC_OP_SHLB + ot;
2305 s->cc_op = CC_OP_SARB + ot;
2308 if (s->cc_op != CC_OP_DYNAMIC)
2309 gen_op_set_cc_op(s->cc_op);
2310 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2311 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2314 gen_op_st_T0_A0[ot]();
2316 gen_op_mov_reg_T0[ot][rm]();
2320 /************************/
2323 modrm = ldub(s->pc++);
2324 mod = (modrm >> 6) & 3;
2326 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2330 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2332 case 0x00 ... 0x07: /* fxxxs */
2333 case 0x10 ... 0x17: /* fixxxl */
2334 case 0x20 ... 0x27: /* fxxxl */
2335 case 0x30 ... 0x37: /* fixxx */
2342 gen_op_flds_FT0_A0();
2345 gen_op_fildl_FT0_A0();
2348 gen_op_fldl_FT0_A0();
2352 gen_op_fild_FT0_A0();
2356 gen_op_fp_arith_ST0_FT0[op1]();
2358 /* fcomp needs pop */
2363 case 0x08: /* flds */
2364 case 0x0a: /* fsts */
2365 case 0x0b: /* fstps */
2366 case 0x18: /* fildl */
2367 case 0x1a: /* fistl */
2368 case 0x1b: /* fistpl */
2369 case 0x28: /* fldl */
2370 case 0x2a: /* fstl */
2371 case 0x2b: /* fstpl */
2372 case 0x38: /* filds */
2373 case 0x3a: /* fists */
2374 case 0x3b: /* fistps */
2381 gen_op_flds_ST0_A0();
2384 gen_op_fildl_ST0_A0();
2387 gen_op_fldl_ST0_A0();
2391 gen_op_fild_ST0_A0();
2398 gen_op_fsts_ST0_A0();
2401 gen_op_fistl_ST0_A0();
2404 gen_op_fstl_ST0_A0();
2408 gen_op_fist_ST0_A0();
2416 case 0x0c: /* fldenv mem */
2417 gen_op_fldenv_A0(s->dflag);
2419 case 0x0d: /* fldcw mem */
2422 case 0x0e: /* fnstenv mem */
2423 gen_op_fnstenv_A0(s->dflag);
2425 case 0x0f: /* fnstcw mem */
2428 case 0x1d: /* fldt mem */
2430 gen_op_fldt_ST0_A0();
2432 case 0x1f: /* fstpt mem */
2433 gen_op_fstt_ST0_A0();
2436 case 0x2c: /* frstor mem */
2437 gen_op_frstor_A0(s->dflag);
2439 case 0x2e: /* fnsave mem */
2440 gen_op_fnsave_A0(s->dflag);
2442 case 0x2f: /* fnstsw mem */
2445 case 0x3c: /* fbld */
2447 gen_op_fbld_ST0_A0();
2449 case 0x3e: /* fbstp */
2450 gen_op_fbst_ST0_A0();
2453 case 0x3d: /* fildll */
2455 gen_op_fildll_ST0_A0();
2457 case 0x3f: /* fistpll */
2458 gen_op_fistll_ST0_A0();
2465 /* register float ops */
2469 case 0x08: /* fld sti */
2471 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2473 case 0x09: /* fxchg sti */
2474 gen_op_fxchg_ST0_STN(opreg);
2476 case 0x0a: /* grp d9/2 */
2484 case 0x0c: /* grp d9/4 */
2494 gen_op_fcom_ST0_FT0();
2503 case 0x0d: /* grp d9/5 */
2512 gen_op_fldl2t_ST0();
2516 gen_op_fldl2e_ST0();
2524 gen_op_fldlg2_ST0();
2528 gen_op_fldln2_ST0();
2539 case 0x0e: /* grp d9/6 */
2550 case 3: /* fpatan */
2553 case 4: /* fxtract */
2556 case 5: /* fprem1 */
2559 case 6: /* fdecstp */
2563 case 7: /* fincstp */
2568 case 0x0f: /* grp d9/7 */
2573 case 1: /* fyl2xp1 */
2579 case 3: /* fsincos */
2582 case 5: /* fscale */
2585 case 4: /* frndint */
2597 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2598 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2599 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2605 gen_op_fp_arith_STN_ST0[op1](opreg);
2609 gen_op_fmov_FT0_STN(opreg);
2610 gen_op_fp_arith_ST0_FT0[op1]();
2614 case 0x02: /* fcom */
2615 gen_op_fmov_FT0_STN(opreg);
2616 gen_op_fcom_ST0_FT0();
2618 case 0x03: /* fcomp */
2619 gen_op_fmov_FT0_STN(opreg);
2620 gen_op_fcom_ST0_FT0();
2623 case 0x15: /* da/5 */
2625 case 1: /* fucompp */
2626 gen_op_fmov_FT0_STN(1);
2627 gen_op_fucom_ST0_FT0();
2637 case 0: /* feni (287 only, just do nop here) */
2639 case 1: /* fdisi (287 only, just do nop here) */
2644 case 3: /* fninit */
2647 case 4: /* fsetpm (287 only, just do nop here) */
2653 case 0x1d: /* fucomi */
2654 if (s->cc_op != CC_OP_DYNAMIC)
2655 gen_op_set_cc_op(s->cc_op);
2656 gen_op_fmov_FT0_STN(opreg);
2657 gen_op_fucomi_ST0_FT0();
2658 s->cc_op = CC_OP_EFLAGS;
2660 case 0x1e: /* fcomi */
2661 if (s->cc_op != CC_OP_DYNAMIC)
2662 gen_op_set_cc_op(s->cc_op);
2663 gen_op_fmov_FT0_STN(opreg);
2664 gen_op_fcomi_ST0_FT0();
2665 s->cc_op = CC_OP_EFLAGS;
2667 case 0x2a: /* fst sti */
2668 gen_op_fmov_STN_ST0(opreg);
2670 case 0x2b: /* fstp sti */
2671 gen_op_fmov_STN_ST0(opreg);
2674 case 0x2c: /* fucom st(i) */
2675 gen_op_fmov_FT0_STN(opreg);
2676 gen_op_fucom_ST0_FT0();
2678 case 0x2d: /* fucomp st(i) */
2679 gen_op_fmov_FT0_STN(opreg);
2680 gen_op_fucom_ST0_FT0();
2683 case 0x33: /* de/3 */
2685 case 1: /* fcompp */
2686 gen_op_fmov_FT0_STN(1);
2687 gen_op_fcom_ST0_FT0();
2695 case 0x3c: /* df/4 */
2698 gen_op_fnstsw_EAX();
2704 case 0x3d: /* fucomip */
2705 if (s->cc_op != CC_OP_DYNAMIC)
2706 gen_op_set_cc_op(s->cc_op);
2707 gen_op_fmov_FT0_STN(opreg);
2708 gen_op_fucomi_ST0_FT0();
2710 s->cc_op = CC_OP_EFLAGS;
2712 case 0x3e: /* fcomip */
2713 if (s->cc_op != CC_OP_DYNAMIC)
2714 gen_op_set_cc_op(s->cc_op);
2715 gen_op_fmov_FT0_STN(opreg);
2716 gen_op_fcomi_ST0_FT0();
2718 s->cc_op = CC_OP_EFLAGS;
2725 /************************/
2728 case 0xa4: /* movsS */
2733 ot = dflag ? OT_LONG : OT_WORD;
2735 if (prefixes & PREFIX_REPZ) {
2736 gen_string_ds(s, ot, gen_op_movs + 9);
2738 gen_string_ds(s, ot, gen_op_movs);
2742 case 0xaa: /* stosS */
2747 ot = dflag ? OT_LONG : OT_WORD;
2749 if (prefixes & PREFIX_REPZ) {
2750 gen_string_es(s, ot, gen_op_stos + 9);
2752 gen_string_es(s, ot, gen_op_stos);
2755 case 0xac: /* lodsS */
2760 ot = dflag ? OT_LONG : OT_WORD;
2761 if (prefixes & PREFIX_REPZ) {
2762 gen_string_ds(s, ot, gen_op_lods + 9);
2764 gen_string_ds(s, ot, gen_op_lods);
2767 case 0xae: /* scasS */
2772 ot = dflag ? OT_LONG : OT_WORD;
2773 if (prefixes & PREFIX_REPNZ) {
2774 if (s->cc_op != CC_OP_DYNAMIC)
2775 gen_op_set_cc_op(s->cc_op);
2776 gen_string_es(s, ot, gen_op_scas + 9 * 2);
2777 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2778 } else if (prefixes & PREFIX_REPZ) {
2779 if (s->cc_op != CC_OP_DYNAMIC)
2780 gen_op_set_cc_op(s->cc_op);
2781 gen_string_es(s, ot, gen_op_scas + 9);
2782 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2784 gen_string_es(s, ot, gen_op_scas);
2785 s->cc_op = CC_OP_SUBB + ot;
2789 case 0xa6: /* cmpsS */
2794 ot = dflag ? OT_LONG : OT_WORD;
2795 if (prefixes & PREFIX_REPNZ) {
2796 if (s->cc_op != CC_OP_DYNAMIC)
2797 gen_op_set_cc_op(s->cc_op);
2798 gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2799 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2800 } else if (prefixes & PREFIX_REPZ) {
2801 if (s->cc_op != CC_OP_DYNAMIC)
2802 gen_op_set_cc_op(s->cc_op);
2803 gen_string_ds(s, ot, gen_op_cmps + 9);
2804 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2806 gen_string_ds(s, ot, gen_op_cmps);
2807 s->cc_op = CC_OP_SUBB + ot;
2810 case 0x6c: /* insS */
2812 if (s->cpl > s->iopl || s->vm86) {
2813 /* NOTE: even for (E)CX = 0 the exception is raised */
2814 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2819 ot = dflag ? OT_LONG : OT_WORD;
2820 if (prefixes & PREFIX_REPZ) {
2821 gen_string_es(s, ot, gen_op_ins + 9);
2823 gen_string_es(s, ot, gen_op_ins);
2827 case 0x6e: /* outsS */
2829 if (s->cpl > s->iopl || s->vm86) {
2830 /* NOTE: even for (E)CX = 0 the exception is raised */
2831 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2836 ot = dflag ? OT_LONG : OT_WORD;
2837 if (prefixes & PREFIX_REPZ) {
2838 gen_string_ds(s, ot, gen_op_outs + 9);
2840 gen_string_ds(s, ot, gen_op_outs);
2845 /************************/
2849 if (s->cpl > s->iopl || s->vm86) {
2850 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2855 ot = dflag ? OT_LONG : OT_WORD;
2856 val = ldub(s->pc++);
2857 gen_op_movl_T0_im(val);
2859 gen_op_mov_reg_T1[ot][R_EAX]();
2864 if (s->cpl > s->iopl || s->vm86) {
2865 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2870 ot = dflag ? OT_LONG : OT_WORD;
2871 val = ldub(s->pc++);
2872 gen_op_movl_T0_im(val);
2873 gen_op_mov_TN_reg[ot][1][R_EAX]();
2879 if (s->cpl > s->iopl || s->vm86) {
2880 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2885 ot = dflag ? OT_LONG : OT_WORD;
2886 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2888 gen_op_mov_reg_T1[ot][R_EAX]();
2893 if (s->cpl > s->iopl || s->vm86) {
2894 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2899 ot = dflag ? OT_LONG : OT_WORD;
2900 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2901 gen_op_mov_TN_reg[ot][1][R_EAX]();
2906 /************************/
2908 case 0xc2: /* ret im */
2912 gen_stack_update(s, val + (2 << s->dflag));
2914 gen_op_andl_T0_ffff();
2918 case 0xc3: /* ret */
2922 gen_op_andl_T0_ffff();
2926 case 0xca: /* lret im */
2932 gen_op_ld_T0_A0[1 + s->dflag]();
2934 gen_op_andl_T0_ffff();
2935 /* NOTE: keeping EIP updated is not a problem in case of
2939 gen_op_addl_A0_im(2 << s->dflag);
2940 gen_op_ld_T0_A0[1 + s->dflag]();
2941 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2942 /* add stack offset */
2943 gen_stack_update(s, val + (4 << s->dflag));
2946 case 0xcb: /* lret */
2949 case 0xcf: /* iret */
2950 if (s->vm86 && s->iopl != 3) {
2951 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2953 if (s->cc_op != CC_OP_DYNAMIC)
2954 gen_op_set_cc_op(s->cc_op);
2955 gen_op_jmp_im(pc_start - s->cs_base);
2956 gen_op_iret_protected(s->dflag);
2957 s->cc_op = CC_OP_EFLAGS;
2961 case 0xe8: /* call im */
2963 unsigned int next_eip;
2964 ot = dflag ? OT_LONG : OT_WORD;
2965 val = insn_get(s, ot);
2966 next_eip = s->pc - s->cs_base;
2970 gen_op_movl_T0_im(next_eip);
2975 case 0x9a: /* lcall im */
2977 unsigned int selector, offset;
2978 /* XXX: not restartable */
2980 ot = dflag ? OT_LONG : OT_WORD;
2981 offset = insn_get(s, ot);
2982 selector = insn_get(s, OT_WORD);
2984 /* push return segment + offset */
2985 gen_op_movl_T0_seg(R_CS);
2987 next_eip = s->pc - s->cs_base;
2988 gen_op_movl_T0_im(next_eip);
2991 /* change cs and pc */
2992 gen_op_movl_T0_im(selector);
2993 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2994 gen_op_jmp_im((unsigned long)offset);
2998 case 0xe9: /* jmp */
2999 ot = dflag ? OT_LONG : OT_WORD;
3000 val = insn_get(s, ot);
3001 val += s->pc - s->cs_base;
3006 case 0xea: /* ljmp im */
3008 unsigned int selector, offset;
3010 ot = dflag ? OT_LONG : OT_WORD;
3011 offset = insn_get(s, ot);
3012 selector = insn_get(s, OT_WORD);
3014 /* change cs and pc */
3015 gen_op_movl_T0_im(selector);
3017 /* we compute EIP to handle the exception case */
3018 gen_op_jmp_im(pc_start - s->cs_base);
3019 gen_op_movl_T1_im(offset);
3020 gen_op_ljmp_T0_T1();
3022 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3023 gen_op_jmp_im((unsigned long)offset);
3028 case 0xeb: /* jmp Jb */
3029 val = (int8_t)insn_get(s, OT_BYTE);
3030 val += s->pc - s->cs_base;
3035 case 0x70 ... 0x7f: /* jcc Jb */
3036 val = (int8_t)insn_get(s, OT_BYTE);
3038 case 0x180 ... 0x18f: /* jcc Jv */
3040 val = insn_get(s, OT_LONG);
3042 val = (int16_t)insn_get(s, OT_WORD);
3045 next_eip = s->pc - s->cs_base;
3049 gen_jcc(s, b, val, next_eip);
3052 case 0x190 ... 0x19f: /* setcc Gv */
3053 modrm = ldub(s->pc++);
3055 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3057 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3058 ot = dflag ? OT_LONG : OT_WORD;
3059 modrm = ldub(s->pc++);
3060 reg = (modrm >> 3) & 7;
3061 mod = (modrm >> 6) & 3;
3064 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3065 gen_op_ld_T1_A0[ot]();
3068 gen_op_mov_TN_reg[ot][1][rm]();
3070 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3073 /************************/
3075 case 0x9c: /* pushf */
3076 if (s->vm86 && s->iopl != 3) {
3077 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3079 if (s->cc_op != CC_OP_DYNAMIC)
3080 gen_op_set_cc_op(s->cc_op);
3081 gen_op_movl_T0_eflags();
3085 case 0x9d: /* popf */
3086 if (s->vm86 && s->iopl != 3) {
3087 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3092 gen_op_movl_eflags_T0_cpl0();
3094 gen_op_movw_eflags_T0_cpl0();
3098 gen_op_movl_eflags_T0();
3100 gen_op_movw_eflags_T0();
3104 s->cc_op = CC_OP_EFLAGS;
3105 s->is_jmp = 2; /* abort translation because TF flag may change */
3108 case 0x9e: /* sahf */
3109 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3110 if (s->cc_op != CC_OP_DYNAMIC)
3111 gen_op_set_cc_op(s->cc_op);
3112 gen_op_movb_eflags_T0();
3113 s->cc_op = CC_OP_EFLAGS;
3115 case 0x9f: /* lahf */
3116 if (s->cc_op != CC_OP_DYNAMIC)
3117 gen_op_set_cc_op(s->cc_op);
3118 gen_op_movl_T0_eflags();
3119 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3121 case 0xf5: /* cmc */
3122 if (s->cc_op != CC_OP_DYNAMIC)
3123 gen_op_set_cc_op(s->cc_op);
3125 s->cc_op = CC_OP_EFLAGS;
3127 case 0xf8: /* clc */
3128 if (s->cc_op != CC_OP_DYNAMIC)
3129 gen_op_set_cc_op(s->cc_op);
3131 s->cc_op = CC_OP_EFLAGS;
3133 case 0xf9: /* stc */
3134 if (s->cc_op != CC_OP_DYNAMIC)
3135 gen_op_set_cc_op(s->cc_op);
3137 s->cc_op = CC_OP_EFLAGS;
3139 case 0xfc: /* cld */
3142 case 0xfd: /* std */
3146 /************************/
3147 /* bit operations */
3148 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3149 ot = dflag ? OT_LONG : OT_WORD;
3150 modrm = ldub(s->pc++);
3151 op = (modrm >> 3) & 7;
3152 mod = (modrm >> 6) & 3;
3155 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3156 gen_op_ld_T0_A0[ot]();
3158 gen_op_mov_TN_reg[ot][0][rm]();
3161 val = ldub(s->pc++);
3162 gen_op_movl_T1_im(val);
3166 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3167 s->cc_op = CC_OP_SARB + ot;
3170 gen_op_st_T0_A0[ot]();
3172 gen_op_mov_reg_T0[ot][rm]();
3175 case 0x1a3: /* bt Gv, Ev */
3178 case 0x1ab: /* bts */
3181 case 0x1b3: /* btr */
3184 case 0x1bb: /* btc */
3187 ot = dflag ? OT_LONG : OT_WORD;
3188 modrm = ldub(s->pc++);
3189 reg = (modrm >> 3) & 7;
3190 mod = (modrm >> 6) & 3;
3192 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3194 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3195 /* specific case: we need to add a displacement */
3197 gen_op_add_bitw_A0_T1();
3199 gen_op_add_bitl_A0_T1();
3200 gen_op_ld_T0_A0[ot]();
3202 gen_op_mov_TN_reg[ot][0][rm]();
3204 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3205 s->cc_op = CC_OP_SARB + ot;
3208 gen_op_st_T0_A0[ot]();
3210 gen_op_mov_reg_T0[ot][rm]();
3213 case 0x1bc: /* bsf */
3214 case 0x1bd: /* bsr */
3215 ot = dflag ? OT_LONG : OT_WORD;
3216 modrm = ldub(s->pc++);
3217 reg = (modrm >> 3) & 7;
3218 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3219 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3220 /* NOTE: we always write back the result. Intel doc says it is
3221 undefined if T0 == 0 */
3222 gen_op_mov_reg_T0[ot][reg]();
3223 s->cc_op = CC_OP_LOGICB + ot;
3225 /************************/
3227 case 0x27: /* daa */
3228 if (s->cc_op != CC_OP_DYNAMIC)
3229 gen_op_set_cc_op(s->cc_op);
3231 s->cc_op = CC_OP_EFLAGS;
3233 case 0x2f: /* das */
3234 if (s->cc_op != CC_OP_DYNAMIC)
3235 gen_op_set_cc_op(s->cc_op);
3237 s->cc_op = CC_OP_EFLAGS;
3239 case 0x37: /* aaa */
3240 if (s->cc_op != CC_OP_DYNAMIC)
3241 gen_op_set_cc_op(s->cc_op);
3243 s->cc_op = CC_OP_EFLAGS;
3245 case 0x3f: /* aas */
3246 if (s->cc_op != CC_OP_DYNAMIC)
3247 gen_op_set_cc_op(s->cc_op);
3249 s->cc_op = CC_OP_EFLAGS;
3251 case 0xd4: /* aam */
3252 val = ldub(s->pc++);
3254 s->cc_op = CC_OP_LOGICB;
3256 case 0xd5: /* aad */
3257 val = ldub(s->pc++);
3259 s->cc_op = CC_OP_LOGICB;
3261 /************************/
3263 case 0x90: /* nop */
3265 case 0x9b: /* fwait */
3267 case 0xcc: /* int3 */
3268 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3270 case 0xcd: /* int N */
3271 val = ldub(s->pc++);
3272 /* XXX: add error code for vm86 GPF */
3274 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3276 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3278 case 0xce: /* into */
3279 if (s->cc_op != CC_OP_DYNAMIC)
3280 gen_op_set_cc_op(s->cc_op);
3281 gen_op_into(s->pc - s->cs_base);
3283 case 0xfa: /* cli */
3285 if (s->cpl <= s->iopl) {
3288 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3294 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3298 case 0xfb: /* sti */
3300 if (s->cpl <= s->iopl) {
3303 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3309 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3313 case 0x62: /* bound */
3314 ot = dflag ? OT_LONG : OT_WORD;
3315 modrm = ldub(s->pc++);
3316 reg = (modrm >> 3) & 7;
3317 mod = (modrm >> 6) & 3;
3320 gen_op_mov_reg_T0[ot][reg]();
3321 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3323 gen_op_boundw(pc_start - s->cs_base);
3325 gen_op_boundl(pc_start - s->cs_base);
3327 case 0x1c8 ... 0x1cf: /* bswap reg */
3329 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3331 gen_op_mov_reg_T0[OT_LONG][reg]();
3333 case 0xd6: /* salc */
3334 if (s->cc_op != CC_OP_DYNAMIC)
3335 gen_op_set_cc_op(s->cc_op);
3338 case 0xe0: /* loopnz */
3339 case 0xe1: /* loopz */
3340 if (s->cc_op != CC_OP_DYNAMIC)
3341 gen_op_set_cc_op(s->cc_op);
3343 case 0xe2: /* loop */
3344 case 0xe3: /* jecxz */
3345 val = (int8_t)insn_get(s, OT_BYTE);
3346 next_eip = s->pc - s->cs_base;
3350 gen_op_loop[s->aflag][b & 3](val, next_eip);
3353 case 0x131: /* rdtsc */
3356 case 0x1a2: /* cpuid */
3359 case 0xf4: /* hlt */
3361 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3363 if (s->cc_op != CC_OP_DYNAMIC)
3364 gen_op_set_cc_op(s->cc_op);
3365 gen_op_jmp_im(s->pc - s->cs_base);
3371 modrm = ldub(s->pc++);
3372 mod = (modrm >> 6) & 3;
3373 op = (modrm >> 3) & 7;
3376 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3380 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3384 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3386 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3387 gen_op_jmp_im(pc_start - s->cs_base);
3392 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3396 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3400 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3402 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3403 gen_op_jmp_im(pc_start - s->cs_base);
3414 modrm = ldub(s->pc++);
3415 mod = (modrm >> 6) & 3;
3416 op = (modrm >> 3) & 7;
3422 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3424 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3426 gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3428 gen_op_addl_A0_im(2);
3430 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3432 gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3434 gen_op_andl_T0_im(0xffffff);
3442 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3444 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3445 gen_op_lduw_T1_A0();
3446 gen_op_addl_A0_im(2);
3449 gen_op_andl_T0_im(0xffffff);
3451 gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3452 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3454 gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3455 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3460 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
3461 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
3465 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3467 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3471 case 7: /* invlpg */
3473 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3477 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3485 case 0x102: /* lar */
3486 case 0x103: /* lsl */
3489 ot = dflag ? OT_LONG : OT_WORD;
3490 modrm = ldub(s->pc++);
3491 reg = (modrm >> 3) & 7;
3492 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3493 gen_op_mov_TN_reg[ot][1][reg]();
3494 if (s->cc_op != CC_OP_DYNAMIC)
3495 gen_op_set_cc_op(s->cc_op);
3500 s->cc_op = CC_OP_EFLAGS;
3501 gen_op_mov_reg_T1[ot][reg]();
3504 modrm = ldub(s->pc++);
3505 mod = (modrm >> 6) & 3;
3506 op = (modrm >> 3) & 7;
3508 case 0: /* prefetchnta */
3509 case 1: /* prefetchnt0 */
3510 case 2: /* prefetchnt0 */
3511 case 3: /* prefetchnt0 */
3514 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3515 /* nothing more to do */
3521 case 0x120: /* mov reg, crN */
3522 case 0x122: /* mov crN, reg */
3524 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3526 modrm = ldub(s->pc++);
3527 if ((modrm & 0xc0) != 0xc0)
3530 reg = (modrm >> 3) & 7;
3537 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3538 gen_op_movl_crN_T0(reg);
3541 gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3542 gen_op_mov_reg_T0[OT_LONG][rm]();
3550 case 0x121: /* mov reg, drN */
3551 case 0x123: /* mov drN, reg */
3553 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3555 modrm = ldub(s->pc++);
3556 if ((modrm & 0xc0) != 0xc0)
3559 reg = (modrm >> 3) & 7;
3560 /* XXX: do it dynamically with CR4.DE bit */
3561 if (reg == 4 || reg == 5)
3564 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3565 gen_op_movl_drN_T0(reg);
3568 gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
3569 gen_op_mov_reg_T0[OT_LONG][rm]();
3573 case 0x106: /* clts */
3575 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3583 /* lock generation */
3584 if (s->prefix & PREFIX_LOCK)
3588 /* XXX: ensure that no lock was generated */
3592 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3593 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3595 /* flags read by an operation */
3596 static uint16_t opc_read_flags[NB_OPS] = {
3597 [INDEX_op_aas] = CC_A,
3598 [INDEX_op_aaa] = CC_A,
3599 [INDEX_op_das] = CC_A | CC_C,
3600 [INDEX_op_daa] = CC_A | CC_C,
3602 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3603 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3604 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3605 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3606 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3607 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3609 /* subtle: due to the incl/decl implementation, C is used */
3610 [INDEX_op_incl_T0_cc] = CC_C,
3611 [INDEX_op_decl_T0_cc] = CC_C,
3613 [INDEX_op_into] = CC_O,
3615 [INDEX_op_jb_subb] = CC_C,
3616 [INDEX_op_jb_subw] = CC_C,
3617 [INDEX_op_jb_subl] = CC_C,
3619 [INDEX_op_jz_subb] = CC_Z,
3620 [INDEX_op_jz_subw] = CC_Z,
3621 [INDEX_op_jz_subl] = CC_Z,
3623 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3624 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3625 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3627 [INDEX_op_js_subb] = CC_S,
3628 [INDEX_op_js_subw] = CC_S,
3629 [INDEX_op_js_subl] = CC_S,
3631 [INDEX_op_jl_subb] = CC_O | CC_S,
3632 [INDEX_op_jl_subw] = CC_O | CC_S,
3633 [INDEX_op_jl_subl] = CC_O | CC_S,
3635 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3636 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3637 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3639 [INDEX_op_loopnzw] = CC_Z,
3640 [INDEX_op_loopnzl] = CC_Z,
3641 [INDEX_op_loopzw] = CC_Z,
3642 [INDEX_op_loopzl] = CC_Z,
3644 [INDEX_op_seto_T0_cc] = CC_O,
3645 [INDEX_op_setb_T0_cc] = CC_C,
3646 [INDEX_op_setz_T0_cc] = CC_Z,
3647 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3648 [INDEX_op_sets_T0_cc] = CC_S,
3649 [INDEX_op_setp_T0_cc] = CC_P,
3650 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3651 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3653 [INDEX_op_setb_T0_subb] = CC_C,
3654 [INDEX_op_setb_T0_subw] = CC_C,
3655 [INDEX_op_setb_T0_subl] = CC_C,
3657 [INDEX_op_setz_T0_subb] = CC_Z,
3658 [INDEX_op_setz_T0_subw] = CC_Z,
3659 [INDEX_op_setz_T0_subl] = CC_Z,
3661 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3662 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3663 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3665 [INDEX_op_sets_T0_subb] = CC_S,
3666 [INDEX_op_sets_T0_subw] = CC_S,
3667 [INDEX_op_sets_T0_subl] = CC_S,
3669 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3670 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3671 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3673 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3674 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3675 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3677 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3678 [INDEX_op_cmc] = CC_C,
3679 [INDEX_op_salc] = CC_C,
3681 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3682 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3683 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3684 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3685 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3686 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3689 /* flags written by an operation */
3690 static uint16_t opc_write_flags[NB_OPS] = {
3691 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3692 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3693 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3694 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3695 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3696 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3697 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3698 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3699 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3700 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3701 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3702 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3703 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3704 /* subtle: due to the incl/decl implementation, C is used */
3705 [INDEX_op_incl_T0_cc] = CC_OSZAPC,
3706 [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3707 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3709 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3710 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3711 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3712 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3713 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3714 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3715 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3716 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3719 [INDEX_op_aam] = CC_OSZAPC,
3720 [INDEX_op_aad] = CC_OSZAPC,
3721 [INDEX_op_aas] = CC_OSZAPC,
3722 [INDEX_op_aaa] = CC_OSZAPC,
3723 [INDEX_op_das] = CC_OSZAPC,
3724 [INDEX_op_daa] = CC_OSZAPC,
3726 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3727 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3728 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3729 [INDEX_op_clc] = CC_C,
3730 [INDEX_op_stc] = CC_C,
3731 [INDEX_op_cmc] = CC_C,
3733 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3734 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3735 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3736 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3737 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3738 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3740 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3741 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3742 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3743 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3744 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3745 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3747 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3748 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3749 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3751 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3752 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3753 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3755 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3756 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3757 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3759 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3760 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3761 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3762 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3764 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3765 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3766 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3767 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3769 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3770 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3771 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3772 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3773 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3774 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3775 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3776 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3778 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3779 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3780 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3781 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3784 #define STRINGOP(x) \
3785 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3786 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3787 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3788 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3789 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3790 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3791 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3792 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3793 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3797 STRINGOP(repnz_scas)
3800 STRINGOP(repnz_cmps)
3802 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3803 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3804 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3806 [INDEX_op_cmpxchg8b] = CC_Z,
3807 [INDEX_op_lar] = CC_Z,
3808 [INDEX_op_lsl] = CC_Z,
3809 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
3810 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
3813 /* simpler form of an operation if no flags need to be generated */
3814 static uint16_t opc_simpler[NB_OPS] = {
3815 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3816 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3817 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3818 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3819 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3820 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3821 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3822 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3824 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3825 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3826 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3828 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3829 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3830 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3832 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3833 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3834 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3836 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3837 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3838 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3840 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3841 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3842 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3845 static void optimize_flags_init(void)
3848 /* put default values in arrays */
3849 for(i = 0; i < NB_OPS; i++) {
3850 if (opc_simpler[i] == 0)
3855 /* CPU flags computation optimization: we move backward thru the
3856 generated code to see which flags are needed. The operation is
3857 modified if suitable */
3858 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3861 int live_flags, write_flags, op;
3863 opc_ptr = opc_buf + opc_buf_len;
3864 /* live_flags contains the flags needed by the next instructions
3865 in the code. At the end of the bloc, we consider that all the
3867 live_flags = CC_OSZAPC;
3868 while (opc_ptr > opc_buf) {
3870 /* if none of the flags written by the instruction is used,
3871 then we can try to find a simpler instruction */
3872 write_flags = opc_write_flags[op];
3873 if ((live_flags & write_flags) == 0) {
3874 *opc_ptr = opc_simpler[op];
3876 /* compute the live flags before the instruction */
3877 live_flags &= ~write_flags;
3878 live_flags |= opc_read_flags[op];
3882 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3883 basic block 'tb'. If search_pc is TRUE, also generate PC
3884 information for each intermediate instruction. */
3885 static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc)
3887 DisasContext dc1, *dc = &dc1;
3889 uint16_t *gen_opc_end;
3895 /* generate intermediate code */
3896 pc_start = (uint8_t *)tb->pc;
3897 cs_base = (uint8_t *)tb->cs_base;
3900 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3901 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3902 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3903 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3904 dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3905 dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3906 dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3907 dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3908 dc->cc_op = CC_OP_DYNAMIC;
3909 dc->cs_base = cs_base;
3911 dc->popl_esp_hack = 0;
3913 gen_opc_ptr = gen_opc_buf;
3914 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3915 gen_opparam_ptr = gen_opparam_buf;
3917 dc->is_jmp = DISAS_NEXT;
3922 j = gen_opc_ptr - gen_opc_buf;
3926 gen_opc_instr_start[lj++] = 0;
3927 gen_opc_pc[lj] = (uint32_t)pc_ptr;
3928 gen_opc_cc_op[lj] = dc->cc_op;
3929 gen_opc_instr_start[lj] = 1;
3932 ret = disas_insn(dc, pc_ptr);
3934 /* we trigger an illegal instruction operation only if it
3935 is the first instruction. Otherwise, we simply stop
3936 generating the code just before it */
3937 if (pc_ptr == pc_start)
3942 pc_ptr = (void *)ret;
3943 /* if single step mode, we generate only one instruction and
3944 generate an exception */
3947 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3948 (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3949 /* we must store the eflags state if it is not already done */
3950 if (dc->is_jmp != DISAS_TB_JUMP) {
3951 if (dc->cc_op != CC_OP_DYNAMIC)
3952 gen_op_set_cc_op(dc->cc_op);
3953 if (dc->is_jmp != DISAS_JUMP) {
3954 /* we add an additionnal jmp to update the simulated PC */
3955 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3959 gen_op_raise_exception(EXCP01_SSTP);
3961 if (dc->is_jmp != 3) {
3962 /* indicate that the hash table must be used to find the next TB */
3965 *gen_opc_ptr = INDEX_op_end;
3969 fprintf(logfile, "----------------\n");
3970 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3971 disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
3972 fprintf(logfile, "\n");
3974 fprintf(logfile, "OP:\n");
3975 dump_ops(gen_opc_buf, gen_opparam_buf);
3976 fprintf(logfile, "\n");
3980 /* optimize flag computations */
3981 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3985 fprintf(logfile, "AFTER FLAGS OPT:\n");
3986 dump_ops(gen_opc_buf, gen_opparam_buf);
3987 fprintf(logfile, "\n");
3991 tb->size = pc_ptr - pc_start;
3995 int gen_intermediate_code(TranslationBlock *tb)
3997 return gen_intermediate_code_internal(tb, 0);
4000 int gen_intermediate_code_pc(TranslationBlock *tb)
4002 return gen_intermediate_code_internal(tb, 1);
4005 CPUX86State *cpu_x86_init(void)
4013 env = malloc(sizeof(CPUX86State));
4016 memset(env, 0, sizeof(CPUX86State));
4017 /* basic FPU init */
4018 for(i = 0;i < 8; i++)
4021 /* flags setup : we activate the IRQs by default as in user mode */
4022 env->eflags = 0x2 | IF_MASK;
4024 /* init various static tables */
4027 optimize_flags_init();
4032 void cpu_x86_close(CPUX86State *env)
4037 /***********************************************************/
4040 /* called when cr3 or PG bit are modified */
4041 static int last_pg_state = -1;
4044 uint8_t *phys_ram_base;
4046 void cpu_x86_update_cr0(CPUX86State *env)
4052 printf("CR0 update: CR0=0x%08x\n", env->cr[0]);
4054 pg_state = env->cr[0] & CR0_PG_MASK;
4055 if (pg_state != last_pg_state) {
4057 /* we map the physical memory at address 0 */
4059 map_addr = mmap((void *)0, phys_ram_size, PROT_WRITE | PROT_READ,
4060 MAP_SHARED | MAP_FIXED, phys_ram_fd, 0);
4061 if (map_addr == MAP_FAILED) {
4063 "Could not map physical memory at host address 0x%08x\n",
4067 page_set_flags(0, phys_ram_size,
4068 PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC);
4070 /* we unmap the physical memory */
4071 munmap((void *)0, phys_ram_size);
4072 page_set_flags(0, phys_ram_size, 0);
4074 last_pg_state = pg_state;
4078 void cpu_x86_update_cr3(CPUX86State *env)
4080 if (env->cr[0] & CR0_PG_MASK) {
4082 printf("CR3 update: CR3=%08x\n", env->cr[3]);
4088 void cpu_x86_init_mmu(CPUX86State *env)
4091 cpu_x86_update_cr0(env);
4094 void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
4099 -1 = cannot handle fault
4100 0 = nothing more to do
4101 1 = generate PF fault
4103 int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
4105 uint8_t *pde_ptr, *pte_ptr;
4106 uint32_t pde, pte, virt_addr;
4107 int cpl, error_code, is_dirty, is_user, prot, page_size;
4110 cpl = env->segs[R_CS].selector & 3;
4111 is_user = (cpl == 3);
4114 printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n",
4115 addr, is_write, is_user, env->eip);
4118 if (env->user_mode_only) {
4119 /* user mode only emulation */
4124 if (!(env->cr[0] & CR0_PG_MASK))
4127 /* page directory entry */
4128 pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
4130 if (!(pde & PG_PRESENT_MASK)) {
4135 if (!(pde & PG_USER_MASK))
4136 goto do_fault_protect;
4137 if (is_write && !(pde & PG_RW_MASK))
4138 goto do_fault_protect;
4140 if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
4141 is_write && !(pde & PG_RW_MASK))
4142 goto do_fault_protect;
4144 /* if PSE bit is set, then we use a 4MB page */
4145 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
4146 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
4147 if (!(pde & PG_ACCESSED_MASK)) {
4148 pde |= PG_ACCESSED_MASK;
4150 pde |= PG_DIRTY_MASK;
4154 pte = pde & ~0x003ff000; /* align to 4MB */
4155 page_size = 4096 * 1024;
4156 virt_addr = addr & ~0x003fffff;
4158 if (!(pde & PG_ACCESSED_MASK)) {
4159 pde |= PG_ACCESSED_MASK;
4163 /* page directory entry */
4164 pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
4166 if (!(pte & PG_PRESENT_MASK)) {
4171 if (!(pte & PG_USER_MASK))
4172 goto do_fault_protect;
4173 if (is_write && !(pte & PG_RW_MASK))
4174 goto do_fault_protect;
4176 if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) &&
4177 is_write && !(pte & PG_RW_MASK))
4178 goto do_fault_protect;
4180 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
4181 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
4182 pte |= PG_ACCESSED_MASK;
4184 pte |= PG_DIRTY_MASK;
4188 virt_addr = addr & ~0xfff;
4190 /* the page can be put in the TLB */
4193 if (pte & PG_RW_MASK)
4196 if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) ||
4200 map_addr = mmap((void *)virt_addr, page_size, prot,
4201 MAP_SHARED | MAP_FIXED, phys_ram_fd, pte & ~0xfff);
4202 if (map_addr == MAP_FAILED) {
4204 "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
4205 pte & ~0xfff, virt_addr);
4208 page_set_flags(virt_addr, virt_addr + page_size,
4209 PAGE_VALID | PAGE_EXEC | prot);
4211 printf("mmaping 0x%08x to virt 0x%08x pse=%d\n",
4212 pte & ~0xfff, virt_addr, (page_size != 4096));
4216 error_code = PG_ERROR_P_MASK;
4219 env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
4221 env->error_code |= PG_ERROR_U_MASK;
4225 /***********************************************************/
4228 static const char *cc_op_str[] = {
4261 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4264 char cc_op_name[32];
4266 eflags = env->eflags;
4267 fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4268 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4269 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4270 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
4271 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
4273 eflags & DF_MASK ? 'D' : '-',
4274 eflags & CC_O ? 'O' : '-',
4275 eflags & CC_S ? 'S' : '-',
4276 eflags & CC_Z ? 'Z' : '-',
4277 eflags & CC_A ? 'A' : '-',
4278 eflags & CC_P ? 'P' : '-',
4279 eflags & CC_C ? 'C' : '-');
4280 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4281 env->segs[R_CS].selector,
4282 env->segs[R_SS].selector,
4283 env->segs[R_DS].selector,
4284 env->segs[R_ES].selector,
4285 env->segs[R_FS].selector,
4286 env->segs[R_GS].selector);
4287 if (flags & X86_DUMP_CCOP) {
4288 if ((unsigned)env->cc_op < CC_OP_NB)
4289 strcpy(cc_op_name, cc_op_str[env->cc_op]);
4291 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4292 fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4293 env->cc_src, env->cc_dst, cc_op_name);
4295 if (flags & X86_DUMP_FPU) {
4296 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
4297 (double)env->fpregs[0],
4298 (double)env->fpregs[1],
4299 (double)env->fpregs[2],
4300 (double)env->fpregs[3]);
4301 fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
4302 (double)env->fpregs[4],
4303 (double)env->fpregs[5],
4304 (double)env->fpregs[7],
4305 (double)env->fpregs[8]);