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 pe; /* protected mode */
56 int code32; /* 32 bit code segment */
57 int ss32; /* 32 bit stack segment */
58 int cc_op; /* current CC operation */
59 int addseg; /* non zero if either DS/ES/SS have a non zero base */
60 int f_st; /* currently unused */
61 int vm86; /* vm86 mode */
64 int tf; /* TF cpu flag */
65 struct TranslationBlock *tb;
66 int popl_esp_hack; /* for correct popl with esp base handling */
69 /* i386 arith/logic operations */
89 OP_SHL1, /* undocumented */
94 #define DEF(s, n, copy_size) INDEX_op_ ## s,
100 #include "gen-op-i386.h"
111 /* I386 int registers */
112 OR_EAX, /* MUST be even numbered */
120 OR_TMP0, /* temporary operand register */
122 OR_A0, /* temporary register used when doing address evaluation */
123 OR_ZERO, /* fixed zero register */
127 typedef void (GenOpFunc)(void);
128 typedef void (GenOpFunc1)(long);
129 typedef void (GenOpFunc2)(long, long);
130 typedef void (GenOpFunc3)(long, long, long);
132 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
165 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
198 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
221 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
291 static GenOpFunc *gen_op_movl_A0_reg[8] = {
302 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
314 gen_op_addl_A0_EAX_s1,
315 gen_op_addl_A0_ECX_s1,
316 gen_op_addl_A0_EDX_s1,
317 gen_op_addl_A0_EBX_s1,
318 gen_op_addl_A0_ESP_s1,
319 gen_op_addl_A0_EBP_s1,
320 gen_op_addl_A0_ESI_s1,
321 gen_op_addl_A0_EDI_s1,
324 gen_op_addl_A0_EAX_s2,
325 gen_op_addl_A0_ECX_s2,
326 gen_op_addl_A0_EDX_s2,
327 gen_op_addl_A0_EBX_s2,
328 gen_op_addl_A0_ESP_s2,
329 gen_op_addl_A0_EBP_s2,
330 gen_op_addl_A0_ESI_s2,
331 gen_op_addl_A0_EDI_s2,
334 gen_op_addl_A0_EAX_s3,
335 gen_op_addl_A0_ECX_s3,
336 gen_op_addl_A0_EDX_s3,
337 gen_op_addl_A0_EBX_s3,
338 gen_op_addl_A0_ESP_s3,
339 gen_op_addl_A0_EBP_s3,
340 gen_op_addl_A0_ESI_s3,
341 gen_op_addl_A0_EDI_s3,
345 static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
347 gen_op_cmovw_EAX_T1_T0,
348 gen_op_cmovw_ECX_T1_T0,
349 gen_op_cmovw_EDX_T1_T0,
350 gen_op_cmovw_EBX_T1_T0,
351 gen_op_cmovw_ESP_T1_T0,
352 gen_op_cmovw_EBP_T1_T0,
353 gen_op_cmovw_ESI_T1_T0,
354 gen_op_cmovw_EDI_T1_T0,
357 gen_op_cmovl_EAX_T1_T0,
358 gen_op_cmovl_ECX_T1_T0,
359 gen_op_cmovl_EDX_T1_T0,
360 gen_op_cmovl_EBX_T1_T0,
361 gen_op_cmovl_ESP_T1_T0,
362 gen_op_cmovl_EBP_T1_T0,
363 gen_op_cmovl_ESI_T1_T0,
364 gen_op_cmovl_EDI_T1_T0,
368 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
379 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
381 gen_op_adcb_T0_T1_cc,
382 gen_op_sbbb_T0_T1_cc,
385 gen_op_adcw_T0_T1_cc,
386 gen_op_sbbw_T0_T1_cc,
389 gen_op_adcl_T0_T1_cc,
390 gen_op_sbbl_T0_T1_cc,
394 static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3][2] = {
396 gen_op_adcb_mem_T0_T1_cc,
397 gen_op_sbbb_mem_T0_T1_cc,
400 gen_op_adcw_mem_T0_T1_cc,
401 gen_op_sbbw_mem_T0_T1_cc,
404 gen_op_adcl_mem_T0_T1_cc,
405 gen_op_sbbl_mem_T0_T1_cc,
409 static const int cc_op_arithb[8] = {
420 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
421 gen_op_cmpxchgb_T0_T1_EAX_cc,
422 gen_op_cmpxchgw_T0_T1_EAX_cc,
423 gen_op_cmpxchgl_T0_T1_EAX_cc,
426 static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3] = {
427 gen_op_cmpxchgb_mem_T0_T1_EAX_cc,
428 gen_op_cmpxchgw_mem_T0_T1_EAX_cc,
429 gen_op_cmpxchgl_mem_T0_T1_EAX_cc,
432 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
434 gen_op_rolb_T0_T1_cc,
435 gen_op_rorb_T0_T1_cc,
436 gen_op_rclb_T0_T1_cc,
437 gen_op_rcrb_T0_T1_cc,
438 gen_op_shlb_T0_T1_cc,
439 gen_op_shrb_T0_T1_cc,
440 gen_op_shlb_T0_T1_cc,
441 gen_op_sarb_T0_T1_cc,
444 gen_op_rolw_T0_T1_cc,
445 gen_op_rorw_T0_T1_cc,
446 gen_op_rclw_T0_T1_cc,
447 gen_op_rcrw_T0_T1_cc,
448 gen_op_shlw_T0_T1_cc,
449 gen_op_shrw_T0_T1_cc,
450 gen_op_shlw_T0_T1_cc,
451 gen_op_sarw_T0_T1_cc,
454 gen_op_roll_T0_T1_cc,
455 gen_op_rorl_T0_T1_cc,
456 gen_op_rcll_T0_T1_cc,
457 gen_op_rcrl_T0_T1_cc,
458 gen_op_shll_T0_T1_cc,
459 gen_op_shrl_T0_T1_cc,
460 gen_op_shll_T0_T1_cc,
461 gen_op_sarl_T0_T1_cc,
465 static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3][8] = {
467 gen_op_rolb_mem_T0_T1_cc,
468 gen_op_rorb_mem_T0_T1_cc,
469 gen_op_rclb_mem_T0_T1_cc,
470 gen_op_rcrb_mem_T0_T1_cc,
471 gen_op_shlb_mem_T0_T1_cc,
472 gen_op_shrb_mem_T0_T1_cc,
473 gen_op_shlb_mem_T0_T1_cc,
474 gen_op_sarb_mem_T0_T1_cc,
477 gen_op_rolw_mem_T0_T1_cc,
478 gen_op_rorw_mem_T0_T1_cc,
479 gen_op_rclw_mem_T0_T1_cc,
480 gen_op_rcrw_mem_T0_T1_cc,
481 gen_op_shlw_mem_T0_T1_cc,
482 gen_op_shrw_mem_T0_T1_cc,
483 gen_op_shlw_mem_T0_T1_cc,
484 gen_op_sarw_mem_T0_T1_cc,
487 gen_op_roll_mem_T0_T1_cc,
488 gen_op_rorl_mem_T0_T1_cc,
489 gen_op_rcll_mem_T0_T1_cc,
490 gen_op_rcrl_mem_T0_T1_cc,
491 gen_op_shll_mem_T0_T1_cc,
492 gen_op_shrl_mem_T0_T1_cc,
493 gen_op_shll_mem_T0_T1_cc,
494 gen_op_sarl_mem_T0_T1_cc,
498 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
500 gen_op_shldw_T0_T1_im_cc,
501 gen_op_shrdw_T0_T1_im_cc,
504 gen_op_shldl_T0_T1_im_cc,
505 gen_op_shrdl_T0_T1_im_cc,
509 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
511 gen_op_shldw_T0_T1_ECX_cc,
512 gen_op_shrdw_T0_T1_ECX_cc,
515 gen_op_shldl_T0_T1_ECX_cc,
516 gen_op_shrdl_T0_T1_ECX_cc,
520 static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[2][2] = {
522 gen_op_shldw_mem_T0_T1_im_cc,
523 gen_op_shrdw_mem_T0_T1_im_cc,
526 gen_op_shldl_mem_T0_T1_im_cc,
527 gen_op_shrdl_mem_T0_T1_im_cc,
531 static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[2][2] = {
533 gen_op_shldw_mem_T0_T1_ECX_cc,
534 gen_op_shrdw_mem_T0_T1_ECX_cc,
537 gen_op_shldl_mem_T0_T1_ECX_cc,
538 gen_op_shrdl_mem_T0_T1_ECX_cc,
542 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
545 gen_op_btsw_T0_T1_cc,
546 gen_op_btrw_T0_T1_cc,
547 gen_op_btcw_T0_T1_cc,
551 gen_op_btsl_T0_T1_cc,
552 gen_op_btrl_T0_T1_cc,
553 gen_op_btcl_T0_T1_cc,
557 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
568 static GenOpFunc *gen_op_lds_T0_A0[3] = {
573 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
578 /* sign does not matter */
579 static GenOpFunc *gen_op_ld_T0_A0[3] = {
585 static GenOpFunc *gen_op_ld_T1_A0[3] = {
591 static GenOpFunc *gen_op_st_T0_A0[3] = {
597 /* the _a32 and _a16 string operations use A0 as the base register. */
599 #define STRINGOP(x) \
600 gen_op_ ## x ## b_fast, \
601 gen_op_ ## x ## w_fast, \
602 gen_op_ ## x ## l_fast, \
603 gen_op_ ## x ## b_a32, \
604 gen_op_ ## x ## w_a32, \
605 gen_op_ ## x ## l_a32, \
606 gen_op_ ## x ## b_a16, \
607 gen_op_ ## x ## w_a16, \
608 gen_op_ ## x ## l_a16,
610 static GenOpFunc *gen_op_movs[9 * 2] = {
615 static GenOpFunc *gen_op_stos[9 * 2] = {
620 static GenOpFunc *gen_op_lods[9 * 2] = {
625 static GenOpFunc *gen_op_scas[9 * 3] = {
631 static GenOpFunc *gen_op_cmps[9 * 3] = {
637 static GenOpFunc *gen_op_ins[9 * 2] = {
643 static GenOpFunc *gen_op_outs[9 * 2] = {
649 static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
653 override = s->override;
656 if (s->addseg && override < 0)
659 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
667 gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
668 /* 16 address, always override */
674 static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
691 static GenOpFunc *gen_op_in[3] = {
697 static GenOpFunc *gen_op_out[3] = {
714 static GenOpFunc3 *gen_jcc_sub[3][8] = {
746 static GenOpFunc2 *gen_op_loop[2][4] = {
761 static GenOpFunc *gen_setcc_slow[8] = {
772 static GenOpFunc *gen_setcc_sub[3][8] = {
777 gen_op_setbe_T0_subb,
781 gen_op_setle_T0_subb,
787 gen_op_setbe_T0_subw,
791 gen_op_setle_T0_subw,
797 gen_op_setbe_T0_subl,
801 gen_op_setle_T0_subl,
805 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
811 gen_op_fsubr_ST0_FT0,
813 gen_op_fdivr_ST0_FT0,
816 /* NOTE the exception in "r" op ordering */
817 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
822 gen_op_fsubr_STN_ST0,
824 gen_op_fdivr_STN_ST0,
828 /* if d == OR_TMP0, it means memory operand (address in A0) */
829 static void gen_op(DisasContext *s1, int op, int ot, int d)
831 GenOpFunc *gen_update_cc;
834 gen_op_mov_TN_reg[ot][0][d]();
836 gen_op_ld_T0_A0[ot]();
841 if (s1->cc_op != CC_OP_DYNAMIC)
842 gen_op_set_cc_op(s1->cc_op);
844 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
845 gen_op_mov_reg_T0[ot][d]();
847 gen_op_arithc_mem_T0_T1_cc[ot][op - OP_ADCL]();
849 s1->cc_op = CC_OP_DYNAMIC;
853 s1->cc_op = CC_OP_ADDB + ot;
854 gen_update_cc = gen_op_update2_cc;
858 s1->cc_op = CC_OP_SUBB + ot;
859 gen_update_cc = gen_op_update2_cc;
865 gen_op_arith_T0_T1_cc[op]();
866 s1->cc_op = CC_OP_LOGICB + ot;
867 gen_update_cc = gen_op_update1_cc;
870 gen_op_cmpl_T0_T1_cc();
871 s1->cc_op = CC_OP_SUBB + ot;
872 gen_update_cc = NULL;
877 gen_op_mov_reg_T0[ot][d]();
879 gen_op_st_T0_A0[ot]();
881 /* the flags update must happen after the memory write (precise
882 exception support) */
888 /* if d == OR_TMP0, it means memory operand (address in A0) */
889 static void gen_inc(DisasContext *s1, int ot, int d, int c)
892 gen_op_mov_TN_reg[ot][0][d]();
894 gen_op_ld_T0_A0[ot]();
895 if (s1->cc_op != CC_OP_DYNAMIC)
896 gen_op_set_cc_op(s1->cc_op);
899 s1->cc_op = CC_OP_INCB + ot;
902 s1->cc_op = CC_OP_DECB + ot;
905 gen_op_mov_reg_T0[ot][d]();
907 gen_op_st_T0_A0[ot]();
908 gen_op_update_inc_cc();
911 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
914 gen_op_mov_TN_reg[ot][0][d]();
916 gen_op_ld_T0_A0[ot]();
918 gen_op_mov_TN_reg[ot][1][s]();
919 /* for zero counts, flags are not updated, so must do it dynamically */
920 if (s1->cc_op != CC_OP_DYNAMIC)
921 gen_op_set_cc_op(s1->cc_op);
924 gen_op_shift_T0_T1_cc[ot][op]();
926 gen_op_shift_mem_T0_T1_cc[ot][op]();
928 gen_op_mov_reg_T0[ot][d]();
929 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
932 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
934 /* currently not optimized */
935 gen_op_movl_T1_im(c);
936 gen_shift(s1, op, ot, d, OR_TMP1);
939 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
946 int mod, rm, code, override, must_add_seg;
948 override = s->override;
949 must_add_seg = s->addseg;
952 mod = (modrm >> 6) & 3;
964 code = ldub(s->pc++);
965 scale = (code >> 6) & 3;
966 index = (code >> 3) & 7;
981 disp = (int8_t)ldub(s->pc++);
991 /* for correct popl handling with esp */
992 if (base == 4 && s->popl_esp_hack)
993 disp += s->popl_esp_hack;
994 gen_op_movl_A0_reg[base]();
996 gen_op_addl_A0_im(disp);
998 gen_op_movl_A0_im(disp);
1000 /* XXX: index == 4 is always invalid */
1001 if (havesib && (index != 4 || scale != 0)) {
1002 gen_op_addl_A0_reg_sN[scale][index]();
1006 if (base == R_EBP || base == R_ESP)
1011 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1019 gen_op_movl_A0_im(disp);
1020 rm = 0; /* avoid SS override */
1027 disp = (int8_t)ldub(s->pc++);
1037 gen_op_movl_A0_reg[R_EBX]();
1038 gen_op_addl_A0_reg_sN[0][R_ESI]();
1041 gen_op_movl_A0_reg[R_EBX]();
1042 gen_op_addl_A0_reg_sN[0][R_EDI]();
1045 gen_op_movl_A0_reg[R_EBP]();
1046 gen_op_addl_A0_reg_sN[0][R_ESI]();
1049 gen_op_movl_A0_reg[R_EBP]();
1050 gen_op_addl_A0_reg_sN[0][R_EDI]();
1053 gen_op_movl_A0_reg[R_ESI]();
1056 gen_op_movl_A0_reg[R_EDI]();
1059 gen_op_movl_A0_reg[R_EBP]();
1063 gen_op_movl_A0_reg[R_EBX]();
1067 gen_op_addl_A0_im(disp);
1068 gen_op_andl_A0_ffff();
1072 if (rm == 2 || rm == 3 || rm == 6)
1077 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
1087 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1089 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1091 int mod, rm, opreg, disp;
1093 mod = (modrm >> 6) & 3;
1098 gen_op_mov_TN_reg[ot][0][reg]();
1099 gen_op_mov_reg_T0[ot][rm]();
1101 gen_op_mov_TN_reg[ot][0][rm]();
1103 gen_op_mov_reg_T0[ot][reg]();
1106 gen_lea_modrm(s, modrm, &opreg, &disp);
1109 gen_op_mov_TN_reg[ot][0][reg]();
1110 gen_op_st_T0_A0[ot]();
1112 gen_op_ld_T0_A0[ot]();
1114 gen_op_mov_reg_T0[ot][reg]();
1119 static inline uint32_t insn_get(DisasContext *s, int ot)
1141 static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1143 TranslationBlock *tb;
1148 jcc_op = (b >> 1) & 7;
1150 /* we optimize the cmp/jcc case */
1154 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1157 /* some jumps are easy to compute */
1184 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1187 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1199 if (s->cc_op != CC_OP_DYNAMIC)
1200 gen_op_set_cc_op(s->cc_op);
1203 gen_setcc_slow[jcc_op]();
1209 func((long)tb, val, next_eip);
1211 func((long)tb, next_eip, val);
1216 static void gen_setcc(DisasContext *s, int b)
1222 jcc_op = (b >> 1) & 7;
1224 /* we optimize the cmp/jcc case */
1228 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1233 /* some jumps are easy to compute */
1251 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1254 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1262 if (s->cc_op != CC_OP_DYNAMIC)
1263 gen_op_set_cc_op(s->cc_op);
1264 func = gen_setcc_slow[jcc_op];
1273 /* move T0 to seg_reg and compute if the CPU state may change */
1274 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1276 if (s->pe && !s->vm86)
1277 gen_op_movl_seg_T0(seg_reg, cur_eip);
1279 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1280 /* abort translation because the register may have a non zero base
1281 or because ss32 may change */
1282 if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1286 /* generate a push. It depends on ss32, addseg and dflag */
1287 static void gen_push_T0(DisasContext *s)
1297 gen_op_pushl_ss32_T0();
1299 gen_op_pushw_ss32_T0();
1303 gen_op_pushl_ss16_T0();
1305 gen_op_pushw_ss16_T0();
1309 /* two step pop is necessary for precise exceptions */
1310 static void gen_pop_T0(DisasContext *s)
1320 gen_op_popl_ss32_T0();
1322 gen_op_popw_ss32_T0();
1326 gen_op_popl_ss16_T0();
1328 gen_op_popw_ss16_T0();
1332 static inline void gen_stack_update(DisasContext *s, int addend)
1336 gen_op_addl_ESP_2();
1337 else if (addend == 4)
1338 gen_op_addl_ESP_4();
1340 gen_op_addl_ESP_im(addend);
1343 gen_op_addw_ESP_2();
1344 else if (addend == 4)
1345 gen_op_addw_ESP_4();
1347 gen_op_addw_ESP_im(addend);
1351 static void gen_pop_update(DisasContext *s)
1353 gen_stack_update(s, 2 << s->dflag);
1356 static void gen_stack_A0(DisasContext *s)
1358 gen_op_movl_A0_ESP();
1360 gen_op_andl_A0_ffff();
1361 gen_op_movl_T1_A0();
1363 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1366 /* NOTE: wrap around in 16 bit not fully handled */
1367 static void gen_pusha(DisasContext *s)
1370 gen_op_movl_A0_ESP();
1371 gen_op_addl_A0_im(-16 << s->dflag);
1373 gen_op_andl_A0_ffff();
1374 gen_op_movl_T1_A0();
1376 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1377 for(i = 0;i < 8; i++) {
1378 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1379 gen_op_st_T0_A0[OT_WORD + s->dflag]();
1380 gen_op_addl_A0_im(2 << s->dflag);
1382 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1385 /* NOTE: wrap around in 16 bit not fully handled */
1386 static void gen_popa(DisasContext *s)
1389 gen_op_movl_A0_ESP();
1391 gen_op_andl_A0_ffff();
1392 gen_op_movl_T1_A0();
1393 gen_op_addl_T1_im(16 << s->dflag);
1395 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1396 for(i = 0;i < 8; i++) {
1397 /* ESP is not reloaded */
1399 gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1400 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1402 gen_op_addl_A0_im(2 << s->dflag);
1404 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1407 /* NOTE: wrap around in 16 bit not fully handled */
1408 /* XXX: check this */
1409 static void gen_enter(DisasContext *s, int esp_addend, int level)
1411 int ot, level1, addend, opsize;
1413 ot = s->dflag + OT_WORD;
1416 opsize = 2 << s->dflag;
1418 gen_op_movl_A0_ESP();
1419 gen_op_addl_A0_im(-opsize);
1421 gen_op_andl_A0_ffff();
1422 gen_op_movl_T1_A0();
1424 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1426 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1427 gen_op_st_T0_A0[ot]();
1430 gen_op_addl_A0_im(-opsize);
1431 gen_op_addl_T0_im(-opsize);
1432 gen_op_st_T0_A0[ot]();
1434 gen_op_addl_A0_im(-opsize);
1435 /* XXX: add st_T1_A0 ? */
1436 gen_op_movl_T0_T1();
1437 gen_op_st_T0_A0[ot]();
1439 gen_op_mov_reg_T1[ot][R_EBP]();
1440 addend = -esp_addend;
1442 addend -= opsize * (level1 + 1);
1443 gen_op_addl_T1_im(addend);
1444 gen_op_mov_reg_T1[ot][R_ESP]();
1447 static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1449 if (s->cc_op != CC_OP_DYNAMIC)
1450 gen_op_set_cc_op(s->cc_op);
1451 gen_op_jmp_im(cur_eip);
1452 gen_op_raise_exception(trapno);
1456 /* an interrupt is different from an exception because of the
1457 priviledge checks */
1458 static void gen_interrupt(DisasContext *s, int intno,
1459 unsigned int cur_eip, unsigned int next_eip)
1461 if (s->cc_op != CC_OP_DYNAMIC)
1462 gen_op_set_cc_op(s->cc_op);
1463 gen_op_jmp_im(cur_eip);
1464 gen_op_raise_interrupt(intno, next_eip);
1468 static void gen_debug(DisasContext *s, unsigned int cur_eip)
1470 if (s->cc_op != CC_OP_DYNAMIC)
1471 gen_op_set_cc_op(s->cc_op);
1472 gen_op_jmp_im(cur_eip);
1477 /* generate a jump to eip. No segment change must happen before as a
1478 direct call to the next block may occur */
1479 static void gen_jmp(DisasContext *s, unsigned int eip)
1481 TranslationBlock *tb = s->tb;
1483 if (s->cc_op != CC_OP_DYNAMIC)
1484 gen_op_set_cc_op(s->cc_op);
1485 gen_op_jmp_tb_next((long)tb, eip);
1489 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1490 is set to true if the instruction sets the PC (last instruction of
1492 long disas_insn(DisasContext *s, uint8_t *pc_start)
1494 int b, prefixes, aflag, dflag;
1496 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1497 unsigned int next_eip;
1507 /* check prefixes */
1510 prefixes |= PREFIX_REPZ;
1513 prefixes |= PREFIX_REPNZ;
1516 prefixes |= PREFIX_LOCK;
1537 prefixes |= PREFIX_DATA;
1540 prefixes |= PREFIX_ADR;
1544 if (prefixes & PREFIX_DATA)
1546 if (prefixes & PREFIX_ADR)
1549 s->prefix = prefixes;
1553 /* lock generation */
1554 if (prefixes & PREFIX_LOCK)
1557 /* now check op code */
1561 /**************************/
1562 /* extended op code */
1563 b = ldub(s->pc++) | 0x100;
1566 /**************************/
1584 ot = dflag ? OT_LONG : OT_WORD;
1587 case 0: /* OP Ev, Gv */
1588 modrm = ldub(s->pc++);
1589 reg = ((modrm >> 3) & 7);
1590 mod = (modrm >> 6) & 3;
1593 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1595 } else if (op == OP_XORL && rm == reg) {
1597 /* xor reg, reg optimisation */
1599 s->cc_op = CC_OP_LOGICB + ot;
1600 gen_op_mov_reg_T0[ot][reg]();
1601 gen_op_update1_cc();
1606 gen_op_mov_TN_reg[ot][1][reg]();
1607 gen_op(s, op, ot, opreg);
1609 case 1: /* OP Gv, Ev */
1610 modrm = ldub(s->pc++);
1611 mod = (modrm >> 6) & 3;
1612 reg = ((modrm >> 3) & 7);
1615 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1616 gen_op_ld_T1_A0[ot]();
1617 } else if (op == OP_XORL && rm == reg) {
1620 gen_op_mov_TN_reg[ot][1][rm]();
1622 gen_op(s, op, ot, reg);
1624 case 2: /* OP A, Iv */
1625 val = insn_get(s, ot);
1626 gen_op_movl_T1_im(val);
1627 gen_op(s, op, ot, OR_EAX);
1633 case 0x80: /* GRP1 */
1642 ot = dflag ? OT_LONG : OT_WORD;
1644 modrm = ldub(s->pc++);
1645 mod = (modrm >> 6) & 3;
1647 op = (modrm >> 3) & 7;
1650 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1653 opreg = rm + OR_EAX;
1660 val = insn_get(s, ot);
1663 val = (int8_t)insn_get(s, OT_BYTE);
1666 gen_op_movl_T1_im(val);
1667 gen_op(s, op, ot, opreg);
1671 /**************************/
1672 /* inc, dec, and other misc arith */
1673 case 0x40 ... 0x47: /* inc Gv */
1674 ot = dflag ? OT_LONG : OT_WORD;
1675 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1677 case 0x48 ... 0x4f: /* dec Gv */
1678 ot = dflag ? OT_LONG : OT_WORD;
1679 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1681 case 0xf6: /* GRP3 */
1686 ot = dflag ? OT_LONG : OT_WORD;
1688 modrm = ldub(s->pc++);
1689 mod = (modrm >> 6) & 3;
1691 op = (modrm >> 3) & 7;
1693 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1694 gen_op_ld_T0_A0[ot]();
1696 gen_op_mov_TN_reg[ot][0][rm]();
1701 val = insn_get(s, ot);
1702 gen_op_movl_T1_im(val);
1703 gen_op_testl_T0_T1_cc();
1704 s->cc_op = CC_OP_LOGICB + ot;
1709 gen_op_st_T0_A0[ot]();
1711 gen_op_mov_reg_T0[ot][rm]();
1717 gen_op_st_T0_A0[ot]();
1719 gen_op_mov_reg_T0[ot][rm]();
1721 gen_op_update_neg_cc();
1722 s->cc_op = CC_OP_SUBB + ot;
1727 gen_op_mulb_AL_T0();
1730 gen_op_mulw_AX_T0();
1734 gen_op_mull_EAX_T0();
1737 s->cc_op = CC_OP_MUL;
1742 gen_op_imulb_AL_T0();
1745 gen_op_imulw_AX_T0();
1749 gen_op_imull_EAX_T0();
1752 s->cc_op = CC_OP_MUL;
1757 gen_op_divb_AL_T0(pc_start - s->cs_base);
1760 gen_op_divw_AX_T0(pc_start - s->cs_base);
1764 gen_op_divl_EAX_T0(pc_start - s->cs_base);
1771 gen_op_idivb_AL_T0(pc_start - s->cs_base);
1774 gen_op_idivw_AX_T0(pc_start - s->cs_base);
1778 gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1787 case 0xfe: /* GRP4 */
1788 case 0xff: /* GRP5 */
1792 ot = dflag ? OT_LONG : OT_WORD;
1794 modrm = ldub(s->pc++);
1795 mod = (modrm >> 6) & 3;
1797 op = (modrm >> 3) & 7;
1798 if (op >= 2 && b == 0xfe) {
1802 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1803 if (op >= 2 && op != 3 && op != 5)
1804 gen_op_ld_T0_A0[ot]();
1806 gen_op_mov_TN_reg[ot][0][rm]();
1810 case 0: /* inc Ev */
1815 gen_inc(s, ot, opreg, 1);
1817 case 1: /* dec Ev */
1822 gen_inc(s, ot, opreg, -1);
1824 case 2: /* call Ev */
1825 /* XXX: optimize if memory (no and is necessary) */
1827 gen_op_andl_T0_ffff();
1829 next_eip = s->pc - s->cs_base;
1830 gen_op_movl_T0_im(next_eip);
1834 case 3: /* lcall Ev */
1835 /* push return segment + offset */
1836 gen_op_movl_T0_seg(R_CS);
1838 next_eip = s->pc - s->cs_base;
1839 gen_op_movl_T0_im(next_eip);
1842 gen_op_ld_T1_A0[ot]();
1843 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1844 gen_op_lduw_T0_A0();
1845 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1846 gen_op_movl_T0_T1();
1850 case 4: /* jmp Ev */
1852 gen_op_andl_T0_ffff();
1856 case 5: /* ljmp Ev */
1857 gen_op_ld_T1_A0[ot]();
1858 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1859 gen_op_lduw_T0_A0();
1860 if (s->pe && !s->vm86) {
1861 /* we compute EIP to handle the exception case */
1862 gen_op_jmp_im(pc_start - s->cs_base);
1863 gen_op_ljmp_T0_T1();
1865 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
1866 gen_op_movl_T0_T1();
1871 case 6: /* push Ev */
1879 case 0x84: /* test Ev, Gv */
1884 ot = dflag ? OT_LONG : OT_WORD;
1886 modrm = ldub(s->pc++);
1887 mod = (modrm >> 6) & 3;
1889 reg = (modrm >> 3) & 7;
1891 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1892 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1893 gen_op_testl_T0_T1_cc();
1894 s->cc_op = CC_OP_LOGICB + ot;
1897 case 0xa8: /* test eAX, Iv */
1902 ot = dflag ? OT_LONG : OT_WORD;
1903 val = insn_get(s, ot);
1905 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1906 gen_op_movl_T1_im(val);
1907 gen_op_testl_T0_T1_cc();
1908 s->cc_op = CC_OP_LOGICB + ot;
1911 case 0x98: /* CWDE/CBW */
1913 gen_op_movswl_EAX_AX();
1915 gen_op_movsbw_AX_AL();
1917 case 0x99: /* CDQ/CWD */
1919 gen_op_movslq_EDX_EAX();
1921 gen_op_movswl_DX_AX();
1923 case 0x1af: /* imul Gv, Ev */
1924 case 0x69: /* imul Gv, Ev, I */
1926 ot = dflag ? OT_LONG : OT_WORD;
1927 modrm = ldub(s->pc++);
1928 reg = ((modrm >> 3) & 7) + OR_EAX;
1929 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1931 val = insn_get(s, ot);
1932 gen_op_movl_T1_im(val);
1933 } else if (b == 0x6b) {
1934 val = insn_get(s, OT_BYTE);
1935 gen_op_movl_T1_im(val);
1937 gen_op_mov_TN_reg[ot][1][reg]();
1940 if (ot == OT_LONG) {
1941 gen_op_imull_T0_T1();
1943 gen_op_imulw_T0_T1();
1945 gen_op_mov_reg_T0[ot][reg]();
1946 s->cc_op = CC_OP_MUL;
1949 case 0x1c1: /* xadd Ev, Gv */
1953 ot = dflag ? OT_LONG : OT_WORD;
1954 modrm = ldub(s->pc++);
1955 reg = (modrm >> 3) & 7;
1956 mod = (modrm >> 6) & 3;
1959 gen_op_mov_TN_reg[ot][0][reg]();
1960 gen_op_mov_TN_reg[ot][1][rm]();
1961 gen_op_addl_T0_T1();
1962 gen_op_mov_reg_T0[ot][rm]();
1963 gen_op_mov_reg_T1[ot][reg]();
1965 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1966 gen_op_mov_TN_reg[ot][0][reg]();
1967 gen_op_ld_T1_A0[ot]();
1968 gen_op_addl_T0_T1();
1969 gen_op_st_T0_A0[ot]();
1970 gen_op_mov_reg_T1[ot][reg]();
1972 gen_op_update2_cc();
1973 s->cc_op = CC_OP_ADDB + ot;
1976 case 0x1b1: /* cmpxchg Ev, Gv */
1980 ot = dflag ? OT_LONG : OT_WORD;
1981 modrm = ldub(s->pc++);
1982 reg = (modrm >> 3) & 7;
1983 mod = (modrm >> 6) & 3;
1984 gen_op_mov_TN_reg[ot][1][reg]();
1987 gen_op_mov_TN_reg[ot][0][rm]();
1988 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1989 gen_op_mov_reg_T0[ot][rm]();
1991 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1992 gen_op_ld_T0_A0[ot]();
1993 gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot]();
1995 s->cc_op = CC_OP_SUBB + ot;
1997 case 0x1c7: /* cmpxchg8b */
1998 modrm = ldub(s->pc++);
1999 mod = (modrm >> 6) & 3;
2002 if (s->cc_op != CC_OP_DYNAMIC)
2003 gen_op_set_cc_op(s->cc_op);
2004 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2006 s->cc_op = CC_OP_EFLAGS;
2009 /**************************/
2011 case 0x50 ... 0x57: /* push */
2012 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
2015 case 0x58 ... 0x5f: /* pop */
2016 ot = dflag ? OT_LONG : OT_WORD;
2018 gen_op_mov_reg_T0[ot][b & 7]();
2021 case 0x60: /* pusha */
2024 case 0x61: /* popa */
2027 case 0x68: /* push Iv */
2029 ot = dflag ? OT_LONG : OT_WORD;
2031 val = insn_get(s, ot);
2033 val = (int8_t)insn_get(s, OT_BYTE);
2034 gen_op_movl_T0_im(val);
2037 case 0x8f: /* pop Ev */
2038 ot = dflag ? OT_LONG : OT_WORD;
2039 modrm = ldub(s->pc++);
2041 s->popl_esp_hack = 2 << dflag;
2042 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2043 s->popl_esp_hack = 0;
2046 case 0xc8: /* enter */
2051 level = ldub(s->pc++);
2052 gen_enter(s, val, level);
2055 case 0xc9: /* leave */
2056 /* XXX: exception not precise (ESP is updated before potential exception) */
2058 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
2059 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
2061 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
2062 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
2065 ot = dflag ? OT_LONG : OT_WORD;
2066 gen_op_mov_reg_T0[ot][R_EBP]();
2069 case 0x06: /* push es */
2070 case 0x0e: /* push cs */
2071 case 0x16: /* push ss */
2072 case 0x1e: /* push ds */
2073 gen_op_movl_T0_seg(b >> 3);
2076 case 0x1a0: /* push fs */
2077 case 0x1a8: /* push gs */
2078 gen_op_movl_T0_seg((b >> 3) & 7);
2081 case 0x07: /* pop es */
2082 case 0x17: /* pop ss */
2083 case 0x1f: /* pop ds */
2085 gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
2087 /* XXX: if reg == SS, inhibit interrupts/trace */
2089 case 0x1a1: /* pop fs */
2090 case 0x1a9: /* pop gs */
2092 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2096 /**************************/
2099 case 0x89: /* mov Gv, Ev */
2103 ot = dflag ? OT_LONG : OT_WORD;
2104 modrm = ldub(s->pc++);
2105 reg = (modrm >> 3) & 7;
2107 /* generate a generic store */
2108 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2111 case 0xc7: /* mov Ev, Iv */
2115 ot = dflag ? OT_LONG : OT_WORD;
2116 modrm = ldub(s->pc++);
2117 mod = (modrm >> 6) & 3;
2119 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2120 val = insn_get(s, ot);
2121 gen_op_movl_T0_im(val);
2123 gen_op_st_T0_A0[ot]();
2125 gen_op_mov_reg_T0[ot][modrm & 7]();
2128 case 0x8b: /* mov Ev, Gv */
2132 ot = dflag ? OT_LONG : OT_WORD;
2133 modrm = ldub(s->pc++);
2134 reg = (modrm >> 3) & 7;
2136 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2137 gen_op_mov_reg_T0[ot][reg]();
2139 case 0x8e: /* mov seg, Gv */
2140 modrm = ldub(s->pc++);
2141 reg = (modrm >> 3) & 7;
2142 if (reg >= 6 || reg == R_CS)
2144 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
2145 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2146 /* XXX: if reg == SS, inhibit interrupts/trace */
2148 case 0x8c: /* mov Gv, seg */
2149 modrm = ldub(s->pc++);
2150 reg = (modrm >> 3) & 7;
2151 mod = (modrm >> 6) & 3;
2154 gen_op_movl_T0_seg(reg);
2156 if (mod == 3 && dflag)
2158 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2161 case 0x1b6: /* movzbS Gv, Eb */
2162 case 0x1b7: /* movzwS Gv, Eb */
2163 case 0x1be: /* movsbS Gv, Eb */
2164 case 0x1bf: /* movswS Gv, Eb */
2167 /* d_ot is the size of destination */
2168 d_ot = dflag + OT_WORD;
2169 /* ot is the size of source */
2170 ot = (b & 1) + OT_BYTE;
2171 modrm = ldub(s->pc++);
2172 reg = ((modrm >> 3) & 7) + OR_EAX;
2173 mod = (modrm >> 6) & 3;
2177 gen_op_mov_TN_reg[ot][0][rm]();
2178 switch(ot | (b & 8)) {
2180 gen_op_movzbl_T0_T0();
2183 gen_op_movsbl_T0_T0();
2186 gen_op_movzwl_T0_T0();
2190 gen_op_movswl_T0_T0();
2193 gen_op_mov_reg_T0[d_ot][reg]();
2195 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2197 gen_op_lds_T0_A0[ot]();
2199 gen_op_ldu_T0_A0[ot]();
2201 gen_op_mov_reg_T0[d_ot][reg]();
2206 case 0x8d: /* lea */
2207 ot = dflag ? OT_LONG : OT_WORD;
2208 modrm = ldub(s->pc++);
2209 reg = (modrm >> 3) & 7;
2210 /* we must ensure that no segment is added */
2214 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2216 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2219 case 0xa0: /* mov EAX, Ov */
2221 case 0xa2: /* mov Ov, EAX */
2226 ot = dflag ? OT_LONG : OT_WORD;
2228 offset_addr = insn_get(s, OT_LONG);
2230 offset_addr = insn_get(s, OT_WORD);
2231 gen_op_movl_A0_im(offset_addr);
2232 /* handle override */
2234 int override, must_add_seg;
2235 must_add_seg = s->addseg;
2236 if (s->override >= 0) {
2237 override = s->override;
2243 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2247 gen_op_ld_T0_A0[ot]();
2248 gen_op_mov_reg_T0[ot][R_EAX]();
2250 gen_op_mov_TN_reg[ot][0][R_EAX]();
2251 gen_op_st_T0_A0[ot]();
2254 case 0xd7: /* xlat */
2255 gen_op_movl_A0_reg[R_EBX]();
2256 gen_op_addl_A0_AL();
2258 gen_op_andl_A0_ffff();
2259 /* handle override */
2261 int override, must_add_seg;
2262 must_add_seg = s->addseg;
2264 if (s->override >= 0) {
2265 override = s->override;
2271 gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2274 gen_op_ldub_T0_A0();
2275 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2277 case 0xb0 ... 0xb7: /* mov R, Ib */
2278 val = insn_get(s, OT_BYTE);
2279 gen_op_movl_T0_im(val);
2280 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2282 case 0xb8 ... 0xbf: /* mov R, Iv */
2283 ot = dflag ? OT_LONG : OT_WORD;
2284 val = insn_get(s, ot);
2285 reg = OR_EAX + (b & 7);
2286 gen_op_movl_T0_im(val);
2287 gen_op_mov_reg_T0[ot][reg]();
2290 case 0x91 ... 0x97: /* xchg R, EAX */
2291 ot = dflag ? OT_LONG : OT_WORD;
2296 case 0x87: /* xchg Ev, Gv */
2300 ot = dflag ? OT_LONG : OT_WORD;
2301 modrm = ldub(s->pc++);
2302 reg = (modrm >> 3) & 7;
2303 mod = (modrm >> 6) & 3;
2307 gen_op_mov_TN_reg[ot][0][reg]();
2308 gen_op_mov_TN_reg[ot][1][rm]();
2309 gen_op_mov_reg_T0[ot][rm]();
2310 gen_op_mov_reg_T1[ot][reg]();
2312 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2313 gen_op_mov_TN_reg[ot][0][reg]();
2314 /* for xchg, lock is implicit */
2315 if (!(prefixes & PREFIX_LOCK))
2317 gen_op_ld_T1_A0[ot]();
2318 gen_op_st_T0_A0[ot]();
2319 if (!(prefixes & PREFIX_LOCK))
2321 gen_op_mov_reg_T1[ot][reg]();
2324 case 0xc4: /* les Gv */
2327 case 0xc5: /* lds Gv */
2330 case 0x1b2: /* lss Gv */
2333 case 0x1b4: /* lfs Gv */
2336 case 0x1b5: /* lgs Gv */
2339 ot = dflag ? OT_LONG : OT_WORD;
2340 modrm = ldub(s->pc++);
2341 reg = (modrm >> 3) & 7;
2342 mod = (modrm >> 6) & 3;
2345 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2346 gen_op_ld_T1_A0[ot]();
2347 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2348 /* load the segment first to handle exceptions properly */
2349 gen_op_lduw_T0_A0();
2350 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2351 /* then put the data */
2352 gen_op_mov_reg_T1[ot][reg]();
2355 /************************/
2366 ot = dflag ? OT_LONG : OT_WORD;
2368 modrm = ldub(s->pc++);
2369 mod = (modrm >> 6) & 3;
2371 op = (modrm >> 3) & 7;
2374 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2377 opreg = rm + OR_EAX;
2382 gen_shift(s, op, ot, opreg, OR_ECX);
2385 shift = ldub(s->pc++);
2387 gen_shifti(s, op, ot, opreg, shift);
2402 case 0x1a4: /* shld imm */
2406 case 0x1a5: /* shld cl */
2410 case 0x1ac: /* shrd imm */
2414 case 0x1ad: /* shrd cl */
2418 ot = dflag ? OT_LONG : OT_WORD;
2419 modrm = ldub(s->pc++);
2420 mod = (modrm >> 6) & 3;
2422 reg = (modrm >> 3) & 7;
2425 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2426 gen_op_ld_T0_A0[ot]();
2428 gen_op_mov_TN_reg[ot][0][rm]();
2430 gen_op_mov_TN_reg[ot][1][reg]();
2433 val = ldub(s->pc++);
2437 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2439 gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val);
2440 if (op == 0 && ot != OT_WORD)
2441 s->cc_op = CC_OP_SHLB + ot;
2443 s->cc_op = CC_OP_SARB + ot;
2446 if (s->cc_op != CC_OP_DYNAMIC)
2447 gen_op_set_cc_op(s->cc_op);
2449 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2451 gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op]();
2452 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2455 gen_op_mov_reg_T0[ot][rm]();
2459 /************************/
2462 modrm = ldub(s->pc++);
2463 mod = (modrm >> 6) & 3;
2465 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2469 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2471 case 0x00 ... 0x07: /* fxxxs */
2472 case 0x10 ... 0x17: /* fixxxl */
2473 case 0x20 ... 0x27: /* fxxxl */
2474 case 0x30 ... 0x37: /* fixxx */
2481 gen_op_flds_FT0_A0();
2484 gen_op_fildl_FT0_A0();
2487 gen_op_fldl_FT0_A0();
2491 gen_op_fild_FT0_A0();
2495 gen_op_fp_arith_ST0_FT0[op1]();
2497 /* fcomp needs pop */
2502 case 0x08: /* flds */
2503 case 0x0a: /* fsts */
2504 case 0x0b: /* fstps */
2505 case 0x18: /* fildl */
2506 case 0x1a: /* fistl */
2507 case 0x1b: /* fistpl */
2508 case 0x28: /* fldl */
2509 case 0x2a: /* fstl */
2510 case 0x2b: /* fstpl */
2511 case 0x38: /* filds */
2512 case 0x3a: /* fists */
2513 case 0x3b: /* fistps */
2519 gen_op_flds_ST0_A0();
2522 gen_op_fildl_ST0_A0();
2525 gen_op_fldl_ST0_A0();
2529 gen_op_fild_ST0_A0();
2536 gen_op_fsts_ST0_A0();
2539 gen_op_fistl_ST0_A0();
2542 gen_op_fstl_ST0_A0();
2546 gen_op_fist_ST0_A0();
2554 case 0x0c: /* fldenv mem */
2555 gen_op_fldenv_A0(s->dflag);
2557 case 0x0d: /* fldcw mem */
2560 case 0x0e: /* fnstenv mem */
2561 gen_op_fnstenv_A0(s->dflag);
2563 case 0x0f: /* fnstcw mem */
2566 case 0x1d: /* fldt mem */
2567 gen_op_fldt_ST0_A0();
2569 case 0x1f: /* fstpt mem */
2570 gen_op_fstt_ST0_A0();
2573 case 0x2c: /* frstor mem */
2574 gen_op_frstor_A0(s->dflag);
2576 case 0x2e: /* fnsave mem */
2577 gen_op_fnsave_A0(s->dflag);
2579 case 0x2f: /* fnstsw mem */
2582 case 0x3c: /* fbld */
2583 gen_op_fbld_ST0_A0();
2585 case 0x3e: /* fbstp */
2586 gen_op_fbst_ST0_A0();
2589 case 0x3d: /* fildll */
2590 gen_op_fildll_ST0_A0();
2592 case 0x3f: /* fistpll */
2593 gen_op_fistll_ST0_A0();
2600 /* register float ops */
2604 case 0x08: /* fld sti */
2606 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2608 case 0x09: /* fxchg sti */
2609 gen_op_fxchg_ST0_STN(opreg);
2611 case 0x0a: /* grp d9/2 */
2619 case 0x0c: /* grp d9/4 */
2629 gen_op_fcom_ST0_FT0();
2638 case 0x0d: /* grp d9/5 */
2647 gen_op_fldl2t_ST0();
2651 gen_op_fldl2e_ST0();
2659 gen_op_fldlg2_ST0();
2663 gen_op_fldln2_ST0();
2674 case 0x0e: /* grp d9/6 */
2685 case 3: /* fpatan */
2688 case 4: /* fxtract */
2691 case 5: /* fprem1 */
2694 case 6: /* fdecstp */
2698 case 7: /* fincstp */
2703 case 0x0f: /* grp d9/7 */
2708 case 1: /* fyl2xp1 */
2714 case 3: /* fsincos */
2717 case 5: /* fscale */
2720 case 4: /* frndint */
2732 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2733 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2734 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2740 gen_op_fp_arith_STN_ST0[op1](opreg);
2744 gen_op_fmov_FT0_STN(opreg);
2745 gen_op_fp_arith_ST0_FT0[op1]();
2749 case 0x02: /* fcom */
2750 gen_op_fmov_FT0_STN(opreg);
2751 gen_op_fcom_ST0_FT0();
2753 case 0x03: /* fcomp */
2754 gen_op_fmov_FT0_STN(opreg);
2755 gen_op_fcom_ST0_FT0();
2758 case 0x15: /* da/5 */
2760 case 1: /* fucompp */
2761 gen_op_fmov_FT0_STN(1);
2762 gen_op_fucom_ST0_FT0();
2772 case 0: /* feni (287 only, just do nop here) */
2774 case 1: /* fdisi (287 only, just do nop here) */
2779 case 3: /* fninit */
2782 case 4: /* fsetpm (287 only, just do nop here) */
2788 case 0x1d: /* fucomi */
2789 if (s->cc_op != CC_OP_DYNAMIC)
2790 gen_op_set_cc_op(s->cc_op);
2791 gen_op_fmov_FT0_STN(opreg);
2792 gen_op_fucomi_ST0_FT0();
2793 s->cc_op = CC_OP_EFLAGS;
2795 case 0x1e: /* fcomi */
2796 if (s->cc_op != CC_OP_DYNAMIC)
2797 gen_op_set_cc_op(s->cc_op);
2798 gen_op_fmov_FT0_STN(opreg);
2799 gen_op_fcomi_ST0_FT0();
2800 s->cc_op = CC_OP_EFLAGS;
2802 case 0x2a: /* fst sti */
2803 gen_op_fmov_STN_ST0(opreg);
2805 case 0x2b: /* fstp sti */
2806 gen_op_fmov_STN_ST0(opreg);
2809 case 0x2c: /* fucom st(i) */
2810 gen_op_fmov_FT0_STN(opreg);
2811 gen_op_fucom_ST0_FT0();
2813 case 0x2d: /* fucomp st(i) */
2814 gen_op_fmov_FT0_STN(opreg);
2815 gen_op_fucom_ST0_FT0();
2818 case 0x33: /* de/3 */
2820 case 1: /* fcompp */
2821 gen_op_fmov_FT0_STN(1);
2822 gen_op_fcom_ST0_FT0();
2830 case 0x3c: /* df/4 */
2833 gen_op_fnstsw_EAX();
2839 case 0x3d: /* fucomip */
2840 if (s->cc_op != CC_OP_DYNAMIC)
2841 gen_op_set_cc_op(s->cc_op);
2842 gen_op_fmov_FT0_STN(opreg);
2843 gen_op_fucomi_ST0_FT0();
2845 s->cc_op = CC_OP_EFLAGS;
2847 case 0x3e: /* fcomip */
2848 if (s->cc_op != CC_OP_DYNAMIC)
2849 gen_op_set_cc_op(s->cc_op);
2850 gen_op_fmov_FT0_STN(opreg);
2851 gen_op_fcomi_ST0_FT0();
2853 s->cc_op = CC_OP_EFLAGS;
2860 /************************/
2863 case 0xa4: /* movsS */
2868 ot = dflag ? OT_LONG : OT_WORD;
2870 if (prefixes & PREFIX_REPZ) {
2871 gen_string_ds(s, ot, gen_op_movs + 9);
2873 gen_string_ds(s, ot, gen_op_movs);
2877 case 0xaa: /* stosS */
2882 ot = dflag ? OT_LONG : OT_WORD;
2884 if (prefixes & PREFIX_REPZ) {
2885 gen_string_es(s, ot, gen_op_stos + 9);
2887 gen_string_es(s, ot, gen_op_stos);
2890 case 0xac: /* lodsS */
2895 ot = dflag ? OT_LONG : OT_WORD;
2896 if (prefixes & PREFIX_REPZ) {
2897 gen_string_ds(s, ot, gen_op_lods + 9);
2899 gen_string_ds(s, ot, gen_op_lods);
2902 case 0xae: /* scasS */
2907 ot = dflag ? OT_LONG : OT_WORD;
2908 if (prefixes & PREFIX_REPNZ) {
2909 if (s->cc_op != CC_OP_DYNAMIC)
2910 gen_op_set_cc_op(s->cc_op);
2911 gen_string_es(s, ot, gen_op_scas + 9 * 2);
2912 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2913 } else if (prefixes & PREFIX_REPZ) {
2914 if (s->cc_op != CC_OP_DYNAMIC)
2915 gen_op_set_cc_op(s->cc_op);
2916 gen_string_es(s, ot, gen_op_scas + 9);
2917 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2919 gen_string_es(s, ot, gen_op_scas);
2920 s->cc_op = CC_OP_SUBB + ot;
2924 case 0xa6: /* cmpsS */
2929 ot = dflag ? OT_LONG : OT_WORD;
2930 if (prefixes & PREFIX_REPNZ) {
2931 if (s->cc_op != CC_OP_DYNAMIC)
2932 gen_op_set_cc_op(s->cc_op);
2933 gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2934 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2935 } else if (prefixes & PREFIX_REPZ) {
2936 if (s->cc_op != CC_OP_DYNAMIC)
2937 gen_op_set_cc_op(s->cc_op);
2938 gen_string_ds(s, ot, gen_op_cmps + 9);
2939 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2941 gen_string_ds(s, ot, gen_op_cmps);
2942 s->cc_op = CC_OP_SUBB + ot;
2945 case 0x6c: /* insS */
2947 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2948 /* NOTE: even for (E)CX = 0 the exception is raised */
2949 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2954 ot = dflag ? OT_LONG : OT_WORD;
2955 if (prefixes & PREFIX_REPZ) {
2956 gen_string_es(s, ot, gen_op_ins + 9);
2958 gen_string_es(s, ot, gen_op_ins);
2962 case 0x6e: /* outsS */
2964 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2965 /* NOTE: even for (E)CX = 0 the exception is raised */
2966 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2971 ot = dflag ? OT_LONG : OT_WORD;
2972 if (prefixes & PREFIX_REPZ) {
2973 gen_string_ds(s, ot, gen_op_outs + 9);
2975 gen_string_ds(s, ot, gen_op_outs);
2980 /************************/
2984 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
2985 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2990 ot = dflag ? OT_LONG : OT_WORD;
2991 val = ldub(s->pc++);
2992 gen_op_movl_T0_im(val);
2994 gen_op_mov_reg_T1[ot][R_EAX]();
2999 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3000 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3005 ot = dflag ? OT_LONG : OT_WORD;
3006 val = ldub(s->pc++);
3007 gen_op_movl_T0_im(val);
3008 gen_op_mov_TN_reg[ot][1][R_EAX]();
3014 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3015 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3020 ot = dflag ? OT_LONG : OT_WORD;
3021 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3023 gen_op_mov_reg_T1[ot][R_EAX]();
3028 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
3029 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3034 ot = dflag ? OT_LONG : OT_WORD;
3035 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
3036 gen_op_mov_TN_reg[ot][1][R_EAX]();
3041 /************************/
3043 case 0xc2: /* ret im */
3047 gen_stack_update(s, val + (2 << s->dflag));
3049 gen_op_andl_T0_ffff();
3053 case 0xc3: /* ret */
3057 gen_op_andl_T0_ffff();
3061 case 0xca: /* lret im */
3067 gen_op_ld_T0_A0[1 + s->dflag]();
3069 gen_op_andl_T0_ffff();
3070 /* NOTE: keeping EIP updated is not a problem in case of
3074 gen_op_addl_A0_im(2 << s->dflag);
3075 gen_op_ld_T0_A0[1 + s->dflag]();
3076 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3077 /* add stack offset */
3078 gen_stack_update(s, val + (4 << s->dflag));
3081 case 0xcb: /* lret */
3084 case 0xcf: /* iret */
3087 gen_op_iret_real(s->dflag);
3088 s->cc_op = CC_OP_EFLAGS;
3089 } else if (s->vm86 && s->iopl != 3) {
3090 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3092 if (s->cc_op != CC_OP_DYNAMIC)
3093 gen_op_set_cc_op(s->cc_op);
3094 gen_op_jmp_im(pc_start - s->cs_base);
3095 gen_op_iret_protected(s->dflag);
3096 s->cc_op = CC_OP_EFLAGS;
3100 case 0xe8: /* call im */
3102 unsigned int next_eip;
3103 ot = dflag ? OT_LONG : OT_WORD;
3104 val = insn_get(s, ot);
3105 next_eip = s->pc - s->cs_base;
3109 gen_op_movl_T0_im(next_eip);
3114 case 0x9a: /* lcall im */
3116 unsigned int selector, offset;
3117 /* XXX: not restartable */
3119 ot = dflag ? OT_LONG : OT_WORD;
3120 offset = insn_get(s, ot);
3121 selector = insn_get(s, OT_WORD);
3123 /* push return segment + offset */
3124 gen_op_movl_T0_seg(R_CS);
3126 next_eip = s->pc - s->cs_base;
3127 gen_op_movl_T0_im(next_eip);
3130 /* change cs and pc */
3131 gen_op_movl_T0_im(selector);
3132 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3133 gen_op_jmp_im((unsigned long)offset);
3137 case 0xe9: /* jmp */
3138 ot = dflag ? OT_LONG : OT_WORD;
3139 val = insn_get(s, ot);
3140 val += s->pc - s->cs_base;
3145 case 0xea: /* ljmp im */
3147 unsigned int selector, offset;
3149 ot = dflag ? OT_LONG : OT_WORD;
3150 offset = insn_get(s, ot);
3151 selector = insn_get(s, OT_WORD);
3153 /* change cs and pc */
3154 gen_op_movl_T0_im(selector);
3155 if (s->pe && !s->vm86) {
3156 /* we compute EIP to handle the exception case */
3157 gen_op_jmp_im(pc_start - s->cs_base);
3158 gen_op_movl_T1_im(offset);
3159 gen_op_ljmp_T0_T1();
3161 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3162 gen_op_jmp_im((unsigned long)offset);
3167 case 0xeb: /* jmp Jb */
3168 val = (int8_t)insn_get(s, OT_BYTE);
3169 val += s->pc - s->cs_base;
3174 case 0x70 ... 0x7f: /* jcc Jb */
3175 val = (int8_t)insn_get(s, OT_BYTE);
3177 case 0x180 ... 0x18f: /* jcc Jv */
3179 val = insn_get(s, OT_LONG);
3181 val = (int16_t)insn_get(s, OT_WORD);
3184 next_eip = s->pc - s->cs_base;
3188 gen_jcc(s, b, val, next_eip);
3191 case 0x190 ... 0x19f: /* setcc Gv */
3192 modrm = ldub(s->pc++);
3194 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3196 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3197 ot = dflag ? OT_LONG : OT_WORD;
3198 modrm = ldub(s->pc++);
3199 reg = (modrm >> 3) & 7;
3200 mod = (modrm >> 6) & 3;
3203 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3204 gen_op_ld_T1_A0[ot]();
3207 gen_op_mov_TN_reg[ot][1][rm]();
3209 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3212 /************************/
3214 case 0x9c: /* pushf */
3215 if (s->vm86 && s->iopl != 3) {
3216 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3218 if (s->cc_op != CC_OP_DYNAMIC)
3219 gen_op_set_cc_op(s->cc_op);
3220 gen_op_movl_T0_eflags();
3224 case 0x9d: /* popf */
3225 if (s->vm86 && s->iopl != 3) {
3226 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3231 gen_op_movl_eflags_T0_cpl0();
3233 gen_op_movw_eflags_T0_cpl0();
3237 gen_op_movl_eflags_T0();
3239 gen_op_movw_eflags_T0();
3243 s->cc_op = CC_OP_EFLAGS;
3244 s->is_jmp = 2; /* abort translation because TF flag may change */
3247 case 0x9e: /* sahf */
3248 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3249 if (s->cc_op != CC_OP_DYNAMIC)
3250 gen_op_set_cc_op(s->cc_op);
3251 gen_op_movb_eflags_T0();
3252 s->cc_op = CC_OP_EFLAGS;
3254 case 0x9f: /* lahf */
3255 if (s->cc_op != CC_OP_DYNAMIC)
3256 gen_op_set_cc_op(s->cc_op);
3257 gen_op_movl_T0_eflags();
3258 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3260 case 0xf5: /* cmc */
3261 if (s->cc_op != CC_OP_DYNAMIC)
3262 gen_op_set_cc_op(s->cc_op);
3264 s->cc_op = CC_OP_EFLAGS;
3266 case 0xf8: /* clc */
3267 if (s->cc_op != CC_OP_DYNAMIC)
3268 gen_op_set_cc_op(s->cc_op);
3270 s->cc_op = CC_OP_EFLAGS;
3272 case 0xf9: /* stc */
3273 if (s->cc_op != CC_OP_DYNAMIC)
3274 gen_op_set_cc_op(s->cc_op);
3276 s->cc_op = CC_OP_EFLAGS;
3278 case 0xfc: /* cld */
3281 case 0xfd: /* std */
3285 /************************/
3286 /* bit operations */
3287 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3288 ot = dflag ? OT_LONG : OT_WORD;
3289 modrm = ldub(s->pc++);
3290 op = (modrm >> 3) & 7;
3291 mod = (modrm >> 6) & 3;
3294 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3295 gen_op_ld_T0_A0[ot]();
3297 gen_op_mov_TN_reg[ot][0][rm]();
3300 val = ldub(s->pc++);
3301 gen_op_movl_T1_im(val);
3305 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3306 s->cc_op = CC_OP_SARB + ot;
3309 gen_op_st_T0_A0[ot]();
3311 gen_op_mov_reg_T0[ot][rm]();
3312 gen_op_update_bt_cc();
3315 case 0x1a3: /* bt Gv, Ev */
3318 case 0x1ab: /* bts */
3321 case 0x1b3: /* btr */
3324 case 0x1bb: /* btc */
3327 ot = dflag ? OT_LONG : OT_WORD;
3328 modrm = ldub(s->pc++);
3329 reg = (modrm >> 3) & 7;
3330 mod = (modrm >> 6) & 3;
3332 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3334 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3335 /* specific case: we need to add a displacement */
3337 gen_op_add_bitw_A0_T1();
3339 gen_op_add_bitl_A0_T1();
3340 gen_op_ld_T0_A0[ot]();
3342 gen_op_mov_TN_reg[ot][0][rm]();
3344 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3345 s->cc_op = CC_OP_SARB + ot;
3348 gen_op_st_T0_A0[ot]();
3350 gen_op_mov_reg_T0[ot][rm]();
3351 gen_op_update_bt_cc();
3354 case 0x1bc: /* bsf */
3355 case 0x1bd: /* bsr */
3356 ot = dflag ? OT_LONG : OT_WORD;
3357 modrm = ldub(s->pc++);
3358 reg = (modrm >> 3) & 7;
3359 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3360 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3361 /* NOTE: we always write back the result. Intel doc says it is
3362 undefined if T0 == 0 */
3363 gen_op_mov_reg_T0[ot][reg]();
3364 s->cc_op = CC_OP_LOGICB + ot;
3366 /************************/
3368 case 0x27: /* daa */
3369 if (s->cc_op != CC_OP_DYNAMIC)
3370 gen_op_set_cc_op(s->cc_op);
3372 s->cc_op = CC_OP_EFLAGS;
3374 case 0x2f: /* das */
3375 if (s->cc_op != CC_OP_DYNAMIC)
3376 gen_op_set_cc_op(s->cc_op);
3378 s->cc_op = CC_OP_EFLAGS;
3380 case 0x37: /* aaa */
3381 if (s->cc_op != CC_OP_DYNAMIC)
3382 gen_op_set_cc_op(s->cc_op);
3384 s->cc_op = CC_OP_EFLAGS;
3386 case 0x3f: /* aas */
3387 if (s->cc_op != CC_OP_DYNAMIC)
3388 gen_op_set_cc_op(s->cc_op);
3390 s->cc_op = CC_OP_EFLAGS;
3392 case 0xd4: /* aam */
3393 val = ldub(s->pc++);
3395 s->cc_op = CC_OP_LOGICB;
3397 case 0xd5: /* aad */
3398 val = ldub(s->pc++);
3400 s->cc_op = CC_OP_LOGICB;
3402 /************************/
3404 case 0x90: /* nop */
3406 case 0x9b: /* fwait */
3408 case 0xcc: /* int3 */
3409 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3411 case 0xcd: /* int N */
3412 val = ldub(s->pc++);
3413 /* XXX: add error code for vm86 GPF */
3415 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3417 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3419 case 0xce: /* into */
3420 if (s->cc_op != CC_OP_DYNAMIC)
3421 gen_op_set_cc_op(s->cc_op);
3422 gen_op_into(s->pc - s->cs_base);
3424 case 0xf1: /* icebp (undocumented, exits to external debugger) */
3425 gen_debug(s, pc_start - s->cs_base);
3427 case 0xfa: /* cli */
3429 if (s->cpl <= s->iopl) {
3432 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3438 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3442 case 0xfb: /* sti */
3444 if (s->cpl <= s->iopl) {
3446 s->is_jmp = 2; /* give a chance to handle pending irqs */
3448 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3453 s->is_jmp = 2; /* give a chance to handle pending irqs */
3455 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3458 /* XXX: interruptions are enabled only the first insn after sti */
3460 case 0x62: /* bound */
3461 ot = dflag ? OT_LONG : OT_WORD;
3462 modrm = ldub(s->pc++);
3463 reg = (modrm >> 3) & 7;
3464 mod = (modrm >> 6) & 3;
3467 gen_op_mov_reg_T0[ot][reg]();
3468 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3470 gen_op_boundw(pc_start - s->cs_base);
3472 gen_op_boundl(pc_start - s->cs_base);
3474 case 0x1c8 ... 0x1cf: /* bswap reg */
3476 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3478 gen_op_mov_reg_T0[OT_LONG][reg]();
3480 case 0xd6: /* salc */
3481 if (s->cc_op != CC_OP_DYNAMIC)
3482 gen_op_set_cc_op(s->cc_op);
3485 case 0xe0: /* loopnz */
3486 case 0xe1: /* loopz */
3487 if (s->cc_op != CC_OP_DYNAMIC)
3488 gen_op_set_cc_op(s->cc_op);
3490 case 0xe2: /* loop */
3491 case 0xe3: /* jecxz */
3492 val = (int8_t)insn_get(s, OT_BYTE);
3493 next_eip = s->pc - s->cs_base;
3497 gen_op_loop[s->aflag][b & 3](val, next_eip);
3500 case 0x130: /* wrmsr */
3501 case 0x132: /* rdmsr */
3503 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3511 case 0x131: /* rdtsc */
3514 case 0x1a2: /* cpuid */
3517 case 0xf4: /* hlt */
3519 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3521 if (s->cc_op != CC_OP_DYNAMIC)
3522 gen_op_set_cc_op(s->cc_op);
3523 gen_op_jmp_im(s->pc - s->cs_base);
3529 modrm = ldub(s->pc++);
3530 mod = (modrm >> 6) & 3;
3531 op = (modrm >> 3) & 7;
3534 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3538 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3542 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3544 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3545 gen_op_jmp_im(pc_start - s->cs_base);
3550 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3554 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3558 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3560 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3561 gen_op_jmp_im(pc_start - s->cs_base);
3572 modrm = ldub(s->pc++);
3573 mod = (modrm >> 6) & 3;
3574 op = (modrm >> 3) & 7;
3580 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3582 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
3584 gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
3586 gen_op_addl_A0_im(2);
3588 gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
3590 gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
3592 gen_op_andl_T0_im(0xffffff);
3600 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3602 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3603 gen_op_lduw_T1_A0();
3604 gen_op_addl_A0_im(2);
3607 gen_op_andl_T0_im(0xffffff);
3609 gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
3610 gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
3612 gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
3613 gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
3618 gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
3619 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
3623 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3625 gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
3629 case 7: /* invlpg */
3631 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3635 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3643 case 0x102: /* lar */
3644 case 0x103: /* lsl */
3645 if (!s->pe || s->vm86)
3647 ot = dflag ? OT_LONG : OT_WORD;
3648 modrm = ldub(s->pc++);
3649 reg = (modrm >> 3) & 7;
3650 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3651 gen_op_mov_TN_reg[ot][1][reg]();
3652 if (s->cc_op != CC_OP_DYNAMIC)
3653 gen_op_set_cc_op(s->cc_op);
3658 s->cc_op = CC_OP_EFLAGS;
3659 gen_op_mov_reg_T1[ot][reg]();
3662 modrm = ldub(s->pc++);
3663 mod = (modrm >> 6) & 3;
3664 op = (modrm >> 3) & 7;
3666 case 0: /* prefetchnta */
3667 case 1: /* prefetchnt0 */
3668 case 2: /* prefetchnt0 */
3669 case 3: /* prefetchnt0 */
3672 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3673 /* nothing more to do */
3679 case 0x120: /* mov reg, crN */
3680 case 0x122: /* mov crN, reg */
3682 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3684 modrm = ldub(s->pc++);
3685 if ((modrm & 0xc0) != 0xc0)
3688 reg = (modrm >> 3) & 7;
3695 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3696 gen_op_movl_crN_T0(reg);
3699 gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3700 gen_op_mov_reg_T0[OT_LONG][rm]();
3708 case 0x121: /* mov reg, drN */
3709 case 0x123: /* mov drN, reg */
3711 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3713 modrm = ldub(s->pc++);
3714 if ((modrm & 0xc0) != 0xc0)
3717 reg = (modrm >> 3) & 7;
3718 /* XXX: do it dynamically with CR4.DE bit */
3719 if (reg == 4 || reg == 5)
3722 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3723 gen_op_movl_drN_T0(reg);
3726 gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
3727 gen_op_mov_reg_T0[OT_LONG][rm]();
3731 case 0x106: /* clts */
3733 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3741 /* lock generation */
3742 if (s->prefix & PREFIX_LOCK)
3746 /* XXX: ensure that no lock was generated */
3750 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3751 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3753 /* flags read by an operation */
3754 static uint16_t opc_read_flags[NB_OPS] = {
3755 [INDEX_op_aas] = CC_A,
3756 [INDEX_op_aaa] = CC_A,
3757 [INDEX_op_das] = CC_A | CC_C,
3758 [INDEX_op_daa] = CC_A | CC_C,
3760 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3761 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3762 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3763 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3764 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3765 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3767 [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
3768 [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
3769 [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
3770 [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
3771 [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
3772 [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
3774 /* subtle: due to the incl/decl implementation, C is used */
3775 [INDEX_op_update_inc_cc] = CC_C,
3777 [INDEX_op_into] = CC_O,
3779 [INDEX_op_jb_subb] = CC_C,
3780 [INDEX_op_jb_subw] = CC_C,
3781 [INDEX_op_jb_subl] = CC_C,
3783 [INDEX_op_jz_subb] = CC_Z,
3784 [INDEX_op_jz_subw] = CC_Z,
3785 [INDEX_op_jz_subl] = CC_Z,
3787 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3788 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3789 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3791 [INDEX_op_js_subb] = CC_S,
3792 [INDEX_op_js_subw] = CC_S,
3793 [INDEX_op_js_subl] = CC_S,
3795 [INDEX_op_jl_subb] = CC_O | CC_S,
3796 [INDEX_op_jl_subw] = CC_O | CC_S,
3797 [INDEX_op_jl_subl] = CC_O | CC_S,
3799 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3800 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3801 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3803 [INDEX_op_loopnzw] = CC_Z,
3804 [INDEX_op_loopnzl] = CC_Z,
3805 [INDEX_op_loopzw] = CC_Z,
3806 [INDEX_op_loopzl] = CC_Z,
3808 [INDEX_op_seto_T0_cc] = CC_O,
3809 [INDEX_op_setb_T0_cc] = CC_C,
3810 [INDEX_op_setz_T0_cc] = CC_Z,
3811 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3812 [INDEX_op_sets_T0_cc] = CC_S,
3813 [INDEX_op_setp_T0_cc] = CC_P,
3814 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3815 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3817 [INDEX_op_setb_T0_subb] = CC_C,
3818 [INDEX_op_setb_T0_subw] = CC_C,
3819 [INDEX_op_setb_T0_subl] = CC_C,
3821 [INDEX_op_setz_T0_subb] = CC_Z,
3822 [INDEX_op_setz_T0_subw] = CC_Z,
3823 [INDEX_op_setz_T0_subl] = CC_Z,
3825 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3826 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3827 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3829 [INDEX_op_sets_T0_subb] = CC_S,
3830 [INDEX_op_sets_T0_subw] = CC_S,
3831 [INDEX_op_sets_T0_subl] = CC_S,
3833 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3834 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3835 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3837 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3838 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3839 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3841 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3842 [INDEX_op_cmc] = CC_C,
3843 [INDEX_op_salc] = CC_C,
3845 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3846 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3847 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3848 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3849 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3850 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3852 [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
3853 [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
3854 [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
3855 [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
3856 [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
3857 [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
3860 /* flags written by an operation */
3861 static uint16_t opc_write_flags[NB_OPS] = {
3862 [INDEX_op_update2_cc] = CC_OSZAPC,
3863 [INDEX_op_update1_cc] = CC_OSZAPC,
3864 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3865 [INDEX_op_update_neg_cc] = CC_OSZAPC,
3866 /* subtle: due to the incl/decl implementation, C is used */
3867 [INDEX_op_update_inc_cc] = CC_OSZAPC,
3868 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3870 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3871 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3872 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3873 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3874 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3875 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3877 [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
3878 [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
3879 [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
3880 [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
3881 [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
3882 [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
3884 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3885 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3886 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3887 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3888 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3889 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3890 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3891 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3894 [INDEX_op_aam] = CC_OSZAPC,
3895 [INDEX_op_aad] = CC_OSZAPC,
3896 [INDEX_op_aas] = CC_OSZAPC,
3897 [INDEX_op_aaa] = CC_OSZAPC,
3898 [INDEX_op_das] = CC_OSZAPC,
3899 [INDEX_op_daa] = CC_OSZAPC,
3901 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3902 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3903 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3904 [INDEX_op_clc] = CC_C,
3905 [INDEX_op_stc] = CC_C,
3906 [INDEX_op_cmc] = CC_C,
3908 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3909 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3910 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3911 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3912 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3913 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3915 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3916 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3917 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3918 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3919 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3920 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3922 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3923 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3924 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3926 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3927 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3928 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3930 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3931 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3932 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3934 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3935 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3936 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3937 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3939 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3940 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3941 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3942 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3944 [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
3945 [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
3946 [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
3947 [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
3948 [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
3949 [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
3951 [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
3952 [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
3953 [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
3954 [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
3955 [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
3956 [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
3958 [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
3959 [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
3960 [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
3962 [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
3963 [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
3964 [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
3966 [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
3967 [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
3968 [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
3970 [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3971 [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3972 [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
3973 [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
3975 [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3976 [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
3977 [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
3978 [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
3980 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3981 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3982 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3983 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3984 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3985 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3986 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3987 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3989 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3990 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3991 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3992 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3995 #define STRINGOP(x) \
3996 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3997 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3998 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3999 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
4000 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
4001 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
4002 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
4003 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
4004 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
4008 STRINGOP(repnz_scas)
4011 STRINGOP(repnz_cmps)
4013 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4014 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4015 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
4017 [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4018 [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4019 [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
4021 [INDEX_op_cmpxchg8b] = CC_Z,
4022 [INDEX_op_lar] = CC_Z,
4023 [INDEX_op_lsl] = CC_Z,
4024 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4025 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
4028 /* simpler form of an operation if no flags need to be generated */
4029 static uint16_t opc_simpler[NB_OPS] = {
4030 [INDEX_op_update2_cc] = INDEX_op_nop,
4031 [INDEX_op_update1_cc] = INDEX_op_nop,
4032 [INDEX_op_update_neg_cc] = INDEX_op_nop,
4034 /* broken: CC_OP logic must be rewritten */
4035 [INDEX_op_update_inc_cc] = INDEX_op_nop,
4037 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
4038 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
4039 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
4041 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
4042 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
4043 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
4045 [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
4046 [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
4047 [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
4049 [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
4050 [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
4051 [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
4053 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
4054 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
4055 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
4057 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
4058 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
4059 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
4061 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
4062 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
4063 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
4066 static void optimize_flags_init(void)
4069 /* put default values in arrays */
4070 for(i = 0; i < NB_OPS; i++) {
4071 if (opc_simpler[i] == 0)
4076 /* CPU flags computation optimization: we move backward thru the
4077 generated code to see which flags are needed. The operation is
4078 modified if suitable */
4079 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
4082 int live_flags, write_flags, op;
4084 opc_ptr = opc_buf + opc_buf_len;
4085 /* live_flags contains the flags needed by the next instructions
4086 in the code. At the end of the bloc, we consider that all the
4088 live_flags = CC_OSZAPC;
4089 while (opc_ptr > opc_buf) {
4091 /* if none of the flags written by the instruction is used,
4092 then we can try to find a simpler instruction */
4093 write_flags = opc_write_flags[op];
4094 if ((live_flags & write_flags) == 0) {
4095 *opc_ptr = opc_simpler[op];
4097 /* compute the live flags before the instruction */
4098 live_flags &= ~write_flags;
4099 live_flags |= opc_read_flags[op];
4103 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4104 basic block 'tb'. If search_pc is TRUE, also generate PC
4105 information for each intermediate instruction. */
4106 static inline int gen_intermediate_code_internal(CPUState *env,
4107 TranslationBlock *tb,
4110 DisasContext dc1, *dc = &dc1;
4112 uint16_t *gen_opc_end;
4118 /* generate intermediate code */
4119 pc_start = (uint8_t *)tb->pc;
4120 cs_base = (uint8_t *)tb->cs_base;
4123 dc->pe = env->cr[0] & CR0_PE_MASK;
4124 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
4125 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
4126 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
4127 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
4128 dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
4129 /* CPL is implicit if real mode or vm86 mode */
4135 dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
4136 dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
4137 dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
4138 dc->cc_op = CC_OP_DYNAMIC;
4139 dc->cs_base = cs_base;
4141 dc->popl_esp_hack = 0;
4143 gen_opc_ptr = gen_opc_buf;
4144 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4145 gen_opparam_ptr = gen_opparam_buf;
4147 dc->is_jmp = DISAS_NEXT;
4151 if (env->nb_breakpoints > 0) {
4152 for(j = 0; j < env->nb_breakpoints; j++) {
4153 if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4154 gen_debug(dc, pc_ptr - dc->cs_base);
4160 j = gen_opc_ptr - gen_opc_buf;
4164 gen_opc_instr_start[lj++] = 0;
4166 gen_opc_pc[lj] = (uint32_t)pc_ptr;
4167 gen_opc_cc_op[lj] = dc->cc_op;
4168 gen_opc_instr_start[lj] = 1;
4170 ret = disas_insn(dc, pc_ptr);
4172 /* we trigger an illegal instruction operation only if it
4173 is the first instruction. Otherwise, we simply stop
4174 generating the code just before it */
4175 if (pc_ptr == pc_start)
4180 pc_ptr = (void *)ret;
4181 /* if single step mode, we generate only one instruction and
4182 generate an exception */
4185 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
4186 (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
4187 if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
4188 gen_jmp(dc, ret - (unsigned long)dc->cs_base);
4191 /* we must store the eflags state if it is not already done */
4192 if (dc->is_jmp != DISAS_TB_JUMP) {
4193 if (dc->cc_op != CC_OP_DYNAMIC)
4194 gen_op_set_cc_op(dc->cc_op);
4195 if (dc->is_jmp != DISAS_JUMP) {
4196 /* we add an additionnal jmp to update the simulated PC */
4197 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
4201 gen_op_raise_exception(EXCP01_SSTP);
4204 if (dc->is_jmp != DISAS_TB_JUMP) {
4205 /* indicate that the hash table must be used to find the next TB */
4209 *gen_opc_ptr = INDEX_op_end;
4210 /* we don't forget to fill the last values */
4212 j = gen_opc_ptr - gen_opc_buf;
4215 gen_opc_instr_start[lj++] = 0;
4220 fprintf(logfile, "----------------\n");
4221 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
4222 disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
4223 fprintf(logfile, "\n");
4225 fprintf(logfile, "OP:\n");
4226 dump_ops(gen_opc_buf, gen_opparam_buf);
4227 fprintf(logfile, "\n");
4231 /* optimize flag computations */
4232 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
4236 fprintf(logfile, "AFTER FLAGS OPT:\n");
4237 dump_ops(gen_opc_buf, gen_opparam_buf);
4238 fprintf(logfile, "\n");
4242 tb->size = pc_ptr - pc_start;
4246 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
4248 return gen_intermediate_code_internal(env, tb, 0);
4251 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
4253 return gen_intermediate_code_internal(env, tb, 1);
4256 CPUX86State *cpu_x86_init(void)
4264 env = malloc(sizeof(CPUX86State));
4267 memset(env, 0, sizeof(CPUX86State));
4268 /* basic FPU init */
4269 for(i = 0;i < 8; i++)
4272 /* flags setup : we activate the IRQs by default as in user mode */
4273 env->eflags = 0x2 | IF_MASK;
4275 /* init various static tables */
4278 optimize_flags_init();
4283 void cpu_x86_close(CPUX86State *env)
4288 /***********************************************************/
4290 /* XXX: add PGE support */
4292 /* called when cr3 or PG bit are modified */
4293 static int last_pg_state = -1;
4294 static int last_pe_state = 0;
4297 uint8_t *phys_ram_base;
4299 void cpu_x86_update_cr0(CPUX86State *env)
4301 int pg_state, pe_state;
4305 printf("CR0 update: CR0=0x%08x\n", env->cr[0]);
4307 pg_state = env->cr[0] & CR0_PG_MASK;
4308 if (pg_state != last_pg_state) {
4310 /* we map the physical memory at address 0 */
4312 map_addr = mmap((void *)0, phys_ram_size, PROT_WRITE | PROT_READ,
4313 MAP_SHARED | MAP_FIXED, phys_ram_fd, 0);
4314 if (map_addr == MAP_FAILED) {
4316 "Could not map physical memory at host address 0x%08x\n",
4320 page_set_flags(0, phys_ram_size,
4321 PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC);
4323 /* we unmap the physical memory */
4324 munmap((void *)0, phys_ram_size);
4325 page_set_flags(0, phys_ram_size, 0);
4327 last_pg_state = pg_state;
4329 pe_state = env->cr[0] & CR0_PE_MASK;
4330 if (last_pe_state != pe_state) {
4332 last_pe_state = pe_state;
4336 void cpu_x86_update_cr3(CPUX86State *env)
4338 if (env->cr[0] & CR0_PG_MASK) {
4339 #if defined(DEBUG_MMU)
4340 printf("CR3 update: CR3=%08x\n", env->cr[3]);
4346 void cpu_x86_init_mmu(CPUX86State *env)
4349 cpu_x86_update_cr0(env);
4352 /* XXX: also flush 4MB pages */
4353 void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr)
4356 unsigned long virt_addr;
4358 flags = page_get_flags(addr);
4359 if (flags & PAGE_VALID) {
4360 virt_addr = addr & ~0xfff;
4361 munmap((void *)virt_addr, 4096);
4362 page_set_flags(virt_addr, virt_addr + 4096, 0);
4367 -1 = cannot handle fault
4368 0 = nothing more to do
4369 1 = generate PF fault
4371 int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write)
4373 uint8_t *pde_ptr, *pte_ptr;
4374 uint32_t pde, pte, virt_addr;
4375 int cpl, error_code, is_dirty, is_user, prot, page_size;
4378 cpl = env->segs[R_CS].selector & 3;
4379 is_user = (cpl == 3);
4382 printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n",
4383 addr, is_write, is_user, env->eip);
4386 if (env->user_mode_only) {
4387 /* user mode only emulation */
4392 if (!(env->cr[0] & CR0_PG_MASK))
4395 /* page directory entry */
4396 pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3));
4398 if (!(pde & PG_PRESENT_MASK)) {
4403 if (!(pde & PG_USER_MASK))
4404 goto do_fault_protect;
4405 if (is_write && !(pde & PG_RW_MASK))
4406 goto do_fault_protect;
4408 if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
4409 is_write && !(pde & PG_RW_MASK))
4410 goto do_fault_protect;
4412 /* if PSE bit is set, then we use a 4MB page */
4413 if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
4414 is_dirty = is_write && !(pde & PG_DIRTY_MASK);
4415 if (!(pde & PG_ACCESSED_MASK)) {
4416 pde |= PG_ACCESSED_MASK;
4418 pde |= PG_DIRTY_MASK;
4422 pte = pde & ~0x003ff000; /* align to 4MB */
4423 page_size = 4096 * 1024;
4424 virt_addr = addr & ~0x003fffff;
4426 if (!(pde & PG_ACCESSED_MASK)) {
4427 pde |= PG_ACCESSED_MASK;
4431 /* page directory entry */
4432 pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc));
4434 if (!(pte & PG_PRESENT_MASK)) {
4439 if (!(pte & PG_USER_MASK))
4440 goto do_fault_protect;
4441 if (is_write && !(pte & PG_RW_MASK))
4442 goto do_fault_protect;
4444 if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) &&
4445 is_write && !(pte & PG_RW_MASK))
4446 goto do_fault_protect;
4448 is_dirty = is_write && !(pte & PG_DIRTY_MASK);
4449 if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
4450 pte |= PG_ACCESSED_MASK;
4452 pte |= PG_DIRTY_MASK;
4456 virt_addr = addr & ~0xfff;
4458 /* the page can be put in the TLB */
4461 if (pte & PG_RW_MASK)
4464 if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) ||
4468 map_addr = mmap((void *)virt_addr, page_size, prot,
4469 MAP_SHARED | MAP_FIXED, phys_ram_fd, pte & ~0xfff);
4470 if (map_addr == MAP_FAILED) {
4472 "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
4473 pte & ~0xfff, virt_addr);
4476 page_set_flags(virt_addr, virt_addr + page_size,
4477 PAGE_VALID | PAGE_EXEC | prot);
4479 printf("mmaping 0x%08x to virt 0x%08x pse=%d\n",
4480 pte & ~0xfff, virt_addr, (page_size != 4096));
4484 error_code = PG_ERROR_P_MASK;
4487 env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;
4489 env->error_code |= PG_ERROR_U_MASK;
4493 /***********************************************************/
4496 static const char *cc_op_str[] = {
4529 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4532 char cc_op_name[32];
4534 eflags = env->eflags;
4535 fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4536 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4537 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4538 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
4539 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
4541 eflags & DF_MASK ? 'D' : '-',
4542 eflags & CC_O ? 'O' : '-',
4543 eflags & CC_S ? 'S' : '-',
4544 eflags & CC_Z ? 'Z' : '-',
4545 eflags & CC_A ? 'A' : '-',
4546 eflags & CC_P ? 'P' : '-',
4547 eflags & CC_C ? 'C' : '-');
4548 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4549 env->segs[R_CS].selector,
4550 env->segs[R_SS].selector,
4551 env->segs[R_DS].selector,
4552 env->segs[R_ES].selector,
4553 env->segs[R_FS].selector,
4554 env->segs[R_GS].selector);
4555 if (flags & X86_DUMP_CCOP) {
4556 if ((unsigned)env->cc_op < CC_OP_NB)
4557 strcpy(cc_op_name, cc_op_str[env->cc_op]);
4559 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4560 fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4561 env->cc_src, env->cc_dst, cc_op_name);
4563 if (flags & X86_DUMP_FPU) {
4564 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
4565 (double)env->fpregs[0],
4566 (double)env->fpregs[1],
4567 (double)env->fpregs[2],
4568 (double)env->fpregs[3]);
4569 fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
4570 (double)env->fpregs[4],
4571 (double)env->fpregs[5],
4572 (double)env->fpregs[7],
4573 (double)env->fpregs[8]);