#include <inttypes.h>
#include <signal.h>
#include <assert.h>
-#include <sys/mman.h>
#include "cpu.h"
#include "exec-all.h"
int singlestep_enabled; /* "hardware" single step enabled */
int jmp_opt; /* use direct block chaining for direct jumps */
int mem_index; /* select memory access functions */
+ int flags; /* all execution flags */
struct TranslationBlock *tb;
int popl_esp_hack; /* for correct popl with esp base handling */
} DisasContext;
NB_OREGS,
};
-typedef void (GenOpFunc)(void);
-typedef void (GenOpFunc1)(long);
-typedef void (GenOpFunc2)(long, long);
-typedef void (GenOpFunc3)(long, long, long);
-
static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
[OT_BYTE] = {
gen_op_movb_EAX_T0,
NULL,
};
-static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
- [OT_BYTE] = {
- gen_op_adcb_T0_T1_cc,
- gen_op_sbbb_T0_T1_cc,
- },
- [OT_WORD] = {
- gen_op_adcw_T0_T1_cc,
- gen_op_sbbw_T0_T1_cc,
- },
- [OT_LONG] = {
- gen_op_adcl_T0_T1_cc,
- gen_op_sbbl_T0_T1_cc,
+#define DEF_ARITHC(SUFFIX)\
+ {\
+ gen_op_adcb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_sbbb ## SUFFIX ## _T0_T1_cc,\
+ },\
+ {\
+ gen_op_adcw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_sbbw ## SUFFIX ## _T0_T1_cc,\
+ },\
+ {\
+ gen_op_adcl ## SUFFIX ## _T0_T1_cc,\
+ gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\
},
+
+static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
+ DEF_ARITHC( )
};
-static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3][2] = {
- [OT_BYTE] = {
- gen_op_adcb_mem_T0_T1_cc,
- gen_op_sbbb_mem_T0_T1_cc,
- },
- [OT_WORD] = {
- gen_op_adcw_mem_T0_T1_cc,
- gen_op_sbbw_mem_T0_T1_cc,
- },
- [OT_LONG] = {
- gen_op_adcl_mem_T0_T1_cc,
- gen_op_sbbl_mem_T0_T1_cc,
- },
+static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[9][2] = {
+ DEF_ARITHC(_raw)
+#ifndef CONFIG_USER_ONLY
+ DEF_ARITHC(_kernel)
+ DEF_ARITHC(_user)
+#endif
};
static const int cc_op_arithb[8] = {
CC_OP_SUBB,
};
+#define DEF_CMPXCHG(SUFFIX)\
+ gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\
+ gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\
+ gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,
+
+
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
- gen_op_cmpxchgb_T0_T1_EAX_cc,
- gen_op_cmpxchgw_T0_T1_EAX_cc,
- gen_op_cmpxchgl_T0_T1_EAX_cc,
+ DEF_CMPXCHG( )
};
-static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3] = {
- gen_op_cmpxchgb_mem_T0_T1_EAX_cc,
- gen_op_cmpxchgw_mem_T0_T1_EAX_cc,
- gen_op_cmpxchgl_mem_T0_T1_EAX_cc,
+static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[9] = {
+ DEF_CMPXCHG(_raw)
+#ifndef CONFIG_USER_ONLY
+ DEF_CMPXCHG(_kernel)
+ DEF_CMPXCHG(_user)
+#endif
};
-static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
- [OT_BYTE] = {
- gen_op_rolb_T0_T1_cc,
- gen_op_rorb_T0_T1_cc,
- gen_op_rclb_T0_T1_cc,
- gen_op_rcrb_T0_T1_cc,
- gen_op_shlb_T0_T1_cc,
- gen_op_shrb_T0_T1_cc,
- gen_op_shlb_T0_T1_cc,
- gen_op_sarb_T0_T1_cc,
- },
- [OT_WORD] = {
- gen_op_rolw_T0_T1_cc,
- gen_op_rorw_T0_T1_cc,
- gen_op_rclw_T0_T1_cc,
- gen_op_rcrw_T0_T1_cc,
- gen_op_shlw_T0_T1_cc,
- gen_op_shrw_T0_T1_cc,
- gen_op_shlw_T0_T1_cc,
- gen_op_sarw_T0_T1_cc,
- },
- [OT_LONG] = {
- gen_op_roll_T0_T1_cc,
- gen_op_rorl_T0_T1_cc,
- gen_op_rcll_T0_T1_cc,
- gen_op_rcrl_T0_T1_cc,
- gen_op_shll_T0_T1_cc,
- gen_op_shrl_T0_T1_cc,
- gen_op_shll_T0_T1_cc,
- gen_op_sarl_T0_T1_cc,
+#define DEF_SHIFT(SUFFIX)\
+ {\
+ gen_op_rolb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rorb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rclb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rcrb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shrb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shlb ## SUFFIX ## _T0_T1_cc,\
+ gen_op_sarb ## SUFFIX ## _T0_T1_cc,\
+ },\
+ {\
+ gen_op_rolw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rorw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rclw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rcrw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shrw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shlw ## SUFFIX ## _T0_T1_cc,\
+ gen_op_sarw ## SUFFIX ## _T0_T1_cc,\
+ },\
+ {\
+ gen_op_roll ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rorl ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rcll ## SUFFIX ## _T0_T1_cc,\
+ gen_op_rcrl ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shll ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shrl ## SUFFIX ## _T0_T1_cc,\
+ gen_op_shll ## SUFFIX ## _T0_T1_cc,\
+ gen_op_sarl ## SUFFIX ## _T0_T1_cc,\
},
+
+static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
+ DEF_SHIFT( )
};
-static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3][8] = {
- [OT_BYTE] = {
- gen_op_rolb_mem_T0_T1_cc,
- gen_op_rorb_mem_T0_T1_cc,
- gen_op_rclb_mem_T0_T1_cc,
- gen_op_rcrb_mem_T0_T1_cc,
- gen_op_shlb_mem_T0_T1_cc,
- gen_op_shrb_mem_T0_T1_cc,
- gen_op_shlb_mem_T0_T1_cc,
- gen_op_sarb_mem_T0_T1_cc,
- },
- [OT_WORD] = {
- gen_op_rolw_mem_T0_T1_cc,
- gen_op_rorw_mem_T0_T1_cc,
- gen_op_rclw_mem_T0_T1_cc,
- gen_op_rcrw_mem_T0_T1_cc,
- gen_op_shlw_mem_T0_T1_cc,
- gen_op_shrw_mem_T0_T1_cc,
- gen_op_shlw_mem_T0_T1_cc,
- gen_op_sarw_mem_T0_T1_cc,
- },
- [OT_LONG] = {
- gen_op_roll_mem_T0_T1_cc,
- gen_op_rorl_mem_T0_T1_cc,
- gen_op_rcll_mem_T0_T1_cc,
- gen_op_rcrl_mem_T0_T1_cc,
- gen_op_shll_mem_T0_T1_cc,
- gen_op_shrl_mem_T0_T1_cc,
- gen_op_shll_mem_T0_T1_cc,
- gen_op_sarl_mem_T0_T1_cc,
- },
+static GenOpFunc *gen_op_shift_mem_T0_T1_cc[9][8] = {
+ DEF_SHIFT(_raw)
+#ifndef CONFIG_USER_ONLY
+ DEF_SHIFT(_kernel)
+ DEF_SHIFT(_user)
+#endif
};
-static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
- [0] = {
- gen_op_shldw_T0_T1_im_cc,
- gen_op_shrdw_T0_T1_im_cc,
- },
- [1] = {
- gen_op_shldl_T0_T1_im_cc,
- gen_op_shrdl_T0_T1_im_cc,
+#define DEF_SHIFTD(SUFFIX, op)\
+ {\
+ NULL,\
+ NULL,\
+ },\
+ {\
+ gen_op_shldw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
+ gen_op_shrdw ## SUFFIX ## _T0_T1_ ## op ## _cc,\
+ },\
+ {\
+ gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
+ gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\
},
+
+
+static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[3][2] = {
+ DEF_SHIFTD(, im)
};
-static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
- [0] = {
- gen_op_shldw_T0_T1_ECX_cc,
- gen_op_shrdw_T0_T1_ECX_cc,
- },
- [1] = {
- gen_op_shldl_T0_T1_ECX_cc,
- gen_op_shrdl_T0_T1_ECX_cc,
- },
+static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[3][2] = {
+ DEF_SHIFTD(, ECX)
};
-static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[2][2] = {
- [0] = {
- gen_op_shldw_mem_T0_T1_im_cc,
- gen_op_shrdw_mem_T0_T1_im_cc,
- },
- [1] = {
- gen_op_shldl_mem_T0_T1_im_cc,
- gen_op_shrdl_mem_T0_T1_im_cc,
- },
+static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[9][2] = {
+ DEF_SHIFTD(_raw, im)
+#ifndef CONFIG_USER_ONLY
+ DEF_SHIFTD(_kernel, im)
+ DEF_SHIFTD(_user, im)
+#endif
};
-static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[2][2] = {
- [0] = {
- gen_op_shldw_mem_T0_T1_ECX_cc,
- gen_op_shrdw_mem_T0_T1_ECX_cc,
- },
- [1] = {
- gen_op_shldl_mem_T0_T1_ECX_cc,
- gen_op_shrdl_mem_T0_T1_ECX_cc,
- },
+static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[9][2] = {
+ DEF_SHIFTD(_raw, ECX)
+#ifndef CONFIG_USER_ONLY
+ DEF_SHIFTD(_kernel, ECX)
+ DEF_SHIFTD(_user, ECX)
+#endif
};
static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
#endif
};
+static GenOpFunc *gen_op_st_T1_A0[3 * 3] = {
+ NULL,
+ gen_op_stw_raw_T1_A0,
+ gen_op_stl_raw_T1_A0,
+
+#ifndef CONFIG_USER_ONLY
+ NULL,
+ gen_op_stw_kernel_T1_A0,
+ gen_op_stl_kernel_T1_A0,
+
+ NULL,
+ gen_op_stw_user_T1_A0,
+ gen_op_stl_user_T1_A0,
+#endif
+};
+
static inline void gen_string_movl_A0_ESI(DisasContext *s)
{
int override;
gen_op_decl_ECX,
};
-static GenOpFunc1 *gen_op_string_jnz_sub[2][3] = {
+#ifdef USE_DIRECT_JUMP
+typedef GenOpFunc GenOpFuncTB2;
+#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot]()
+#else
+typedef GenOpFunc1 GenOpFuncTB2;
+#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot](tb)
+#endif
+
+static GenOpFuncTB2 *gen_op_string_jnz_sub2[2][3] = {
{
gen_op_string_jnz_subb,
gen_op_string_jnz_subw,
if (!s->jmp_opt) \
gen_op_string_jnz_sub_im[nz][ot](next_eip); \
else \
- gen_op_string_jnz_sub[nz][ot]((long)s->tb); \
+ gen_op_string_jnz_sub(nz, ot, (long)s->tb); \
if (!s->jmp_opt) \
gen_op_jz_ecx_im[s->aflag](next_eip); \
gen_jmp(s, cur_eip); \
gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
gen_op_mov_reg_T0[ot][d]();
} else {
- gen_op_arithc_mem_T0_T1_cc[ot][op - OP_ADCL]();
+ gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL]();
}
s1->cc_op = CC_OP_DYNAMIC;
goto the_end;
if (d != OR_TMP0)
gen_op_shift_T0_T1_cc[ot][op]();
else
- gen_op_shift_mem_T0_T1_cc[ot][op]();
+ gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op]();
if (d != OR_TMP0)
gen_op_mov_reg_T0[ot][d]();
s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
call this function with seg_reg == R_CS */
static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
{
- if (s->pe && !s->vm86)
- gen_op_movl_seg_T0(seg_reg, cur_eip);
- else
+ if (s->pe && !s->vm86) {
+ /* XXX: optimize by finding processor state dynamically */
+ if (s->cc_op != CC_OP_DYNAMIC)
+ gen_op_set_cc_op(s->cc_op);
+ gen_op_jmp_im(cur_eip);
+ gen_op_movl_seg_T0(seg_reg);
+ /* abort translation because the addseg value may change or
+ because ss32 may change. For R_SS, translation must always
+ stop as a special handling must be done to disable hardware
+ interrupts for the next instruction */
+ if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
+ s->is_jmp = 3;
+ } else {
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
- /* abort translation because the register may have a non zero base
- or because ss32 may change. For R_SS, translation must always
- stop as a special handling must be done to disable hardware
- interrupts for the next instruction */
- if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
- s->is_jmp = 3;
+ if (seg_reg == R_SS)
+ s->is_jmp = 3;
+ }
+}
+
+static inline void gen_stack_update(DisasContext *s, int addend)
+{
+ if (s->ss32) {
+ if (addend == 2)
+ gen_op_addl_ESP_2();
+ else if (addend == 4)
+ gen_op_addl_ESP_4();
+ else
+ gen_op_addl_ESP_im(addend);
+ } else {
+ if (addend == 2)
+ gen_op_addw_ESP_2();
+ else if (addend == 4)
+ gen_op_addw_ESP_4();
+ else
+ gen_op_addw_ESP_im(addend);
+ }
}
/* generate a push. It depends on ss32, addseg and dflag */
static void gen_push_T0(DisasContext *s)
{
+ gen_op_movl_A0_reg[R_ESP]();
+ if (!s->dflag)
+ gen_op_subl_A0_2();
+ else
+ gen_op_subl_A0_4();
if (s->ss32) {
- if (!s->addseg) {
- if (s->dflag)
- gen_op_pushl_T0();
- else
- gen_op_pushw_T0();
- } else {
- if (s->dflag)
- gen_op_pushl_ss32_T0();
- else
- gen_op_pushw_ss32_T0();
+ if (s->addseg) {
+ gen_op_movl_T1_A0();
+ gen_op_addl_A0_SS();
}
} else {
- if (s->dflag)
- gen_op_pushl_ss16_T0();
- else
- gen_op_pushw_ss16_T0();
+ gen_op_andl_A0_ffff();
+ gen_op_movl_T1_A0();
+ gen_op_addl_A0_SS();
}
+ gen_op_st_T0_A0[s->dflag + 1 + s->mem_index]();
+ if (s->ss32 && !s->addseg)
+ gen_op_movl_ESP_A0();
+ else
+ gen_op_mov_reg_T1[s->ss32 + 1][R_ESP]();
}
-/* two step pop is necessary for precise exceptions */
-static void gen_pop_T0(DisasContext *s)
+/* generate a push. It depends on ss32, addseg and dflag */
+/* slower version for T1, only used for call Ev */
+static void gen_push_T1(DisasContext *s)
{
+ gen_op_movl_A0_reg[R_ESP]();
+ if (!s->dflag)
+ gen_op_subl_A0_2();
+ else
+ gen_op_subl_A0_4();
if (s->ss32) {
- if (!s->addseg) {
- if (s->dflag)
- gen_op_popl_T0();
- else
- gen_op_popw_T0();
- } else {
- if (s->dflag)
- gen_op_popl_ss32_T0();
- else
- gen_op_popw_ss32_T0();
+ if (s->addseg) {
+ gen_op_addl_A0_SS();
}
} else {
- if (s->dflag)
- gen_op_popl_ss16_T0();
- else
- gen_op_popw_ss16_T0();
+ gen_op_andl_A0_ffff();
+ gen_op_addl_A0_SS();
}
+ gen_op_st_T1_A0[s->dflag + 1 + s->mem_index]();
+
+ if (s->ss32 && !s->addseg)
+ gen_op_movl_ESP_A0();
+ else
+ gen_stack_update(s, (-2) << s->dflag);
}
-static inline void gen_stack_update(DisasContext *s, int addend)
+/* two step pop is necessary for precise exceptions */
+static void gen_pop_T0(DisasContext *s)
{
+ gen_op_movl_A0_reg[R_ESP]();
if (s->ss32) {
- if (addend == 2)
- gen_op_addl_ESP_2();
- else if (addend == 4)
- gen_op_addl_ESP_4();
- else
- gen_op_addl_ESP_im(addend);
+ if (s->addseg)
+ gen_op_addl_A0_SS();
} else {
- if (addend == 2)
- gen_op_addw_ESP_2();
- else if (addend == 4)
- gen_op_addw_ESP_4();
- else
- gen_op_addw_ESP_im(addend);
+ gen_op_andl_A0_ffff();
+ gen_op_addl_A0_SS();
}
+ gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index]();
}
static void gen_pop_update(DisasContext *s)
gen_op_st_T0_A0[ot + s->mem_index]();
}
gen_op_addl_A0_im(-opsize);
- /* XXX: add st_T1_A0 ? */
- gen_op_movl_T0_T1();
- gen_op_st_T0_A0[ot + s->mem_index]();
+ gen_op_st_T1_A0[ot + s->mem_index]();
}
gen_op_mov_reg_T1[ot][R_EBP]();
addend = -esp_addend;
case 0x80: /* GRP1 */
case 0x81:
+ case 0x82:
case 0x83:
{
int val;
default:
case 0x80:
case 0x81:
+ case 0x82:
val = insn_get(s, ot);
break;
case 0x83:
gen_inc(s, ot, opreg, -1);
break;
case 2: /* call Ev */
- /* XXX: optimize if memory (no and is necessary) */
+ /* XXX: optimize if memory (no 'and' is necessary) */
if (s->dflag == 0)
gen_op_andl_T0_ffff();
- gen_op_jmp_T0();
next_eip = s->pc - s->cs_base;
- gen_op_movl_T0_im(next_eip);
- gen_push_T0(s);
+ gen_op_movl_T1_im(next_eip);
+ gen_push_T1(s);
+ gen_op_jmp_T0();
gen_eob(s);
break;
case 3: /* lcall Ev */
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
gen_op_jmp_im(pc_start - s->cs_base);
- gen_op_ljmp_protected_T0_T1();
+ gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base);
} else {
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
gen_op_movl_T0_T1();
val = insn_get(s, ot);
gen_op_movl_T1_im(val);
} else if (b == 0x6b) {
- val = insn_get(s, OT_BYTE);
+ val = (int8_t)insn_get(s, OT_BYTE);
gen_op_movl_T1_im(val);
} else {
gen_op_mov_TN_reg[ot][1][reg]();
gen_op_mov_TN_reg[ot][0][reg]();
gen_op_mov_TN_reg[ot][1][rm]();
gen_op_addl_T0_T1();
- gen_op_mov_reg_T0[ot][rm]();
gen_op_mov_reg_T1[ot][reg]();
+ gen_op_mov_reg_T0[ot][rm]();
} else {
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
gen_op_mov_TN_reg[ot][0][reg]();
} else {
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
gen_op_ld_T0_A0[ot + s->mem_index]();
- gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot]();
+ gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index]();
}
s->cc_op = CC_OP_SUBB + ot;
break;
case 0x8d: /* lea */
ot = dflag ? OT_LONG : OT_WORD;
modrm = ldub_code(s->pc++);
+ mod = (modrm >> 6) & 3;
+ if (mod == 3)
+ goto illegal_op;
reg = (modrm >> 3) & 7;
/* we must ensure that no segment is added */
s->override = -1;
val &= 0x1f;
if (val) {
if (mod == 3)
- gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
+ gen_op_shiftd_T0_T1_im_cc[ot][op](val);
else
- gen_op_shiftd_mem_T0_T1_im_cc[ot - OT_WORD][op](val);
+ gen_op_shiftd_mem_T0_T1_im_cc[ot + s->mem_index][op](val);
if (op == 0 && ot != OT_WORD)
s->cc_op = CC_OP_SHLB + ot;
else
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
if (mod == 3)
- gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
+ gen_op_shiftd_T0_T1_ECX_cc[ot][op]();
else
- gen_op_shiftd_mem_T0_T1_ECX_cc[ot - OT_WORD][op]();
+ gen_op_shiftd_mem_T0_T1_ECX_cc[ot + s->mem_index][op]();
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
}
if (mod == 3) {
/************************/
/* floats */
case 0xd8 ... 0xdf:
+ if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
+ /* if CR0.EM or CR0.TS are set, generate an FPU exception */
+ /* XXX: what to do if illegal op ? */
+ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
+ break;
+ }
modrm = ldub_code(s->pc++);
mod = (modrm >> 6) & 3;
rm = modrm & 7;
op = ((b & 7) << 3) | ((modrm >> 3) & 7);
-
if (mod != 3) {
/* memory op */
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
case 0x0a: /* grp d9/2 */
switch(rm) {
case 0: /* fnop */
+ /* check exceptions (FreeBSD FPU probe) */
+ if (s->cc_op != CC_OP_DYNAMIC)
+ gen_op_set_cc_op(s->cc_op);
+ gen_op_jmp_im(pc_start - s->cs_base);
+ gen_op_fwait();
break;
default:
goto illegal_op;
gen_op_fcomi_ST0_FT0();
s->cc_op = CC_OP_EFLAGS;
break;
+ case 0x28: /* ffree sti */
+ gen_op_ffree_STN(opreg);
+ break;
case 0x2a: /* fst sti */
gen_op_fmov_STN_ST0(opreg);
break;
goto illegal_op;
}
}
+#ifdef USE_CODE_COPY
+ s->tb->cflags |= CF_TB_FP_USED;
+#endif
break;
/************************/
/* string ops */
else
ot = dflag ? OT_LONG : OT_WORD;
gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
+ gen_op_andl_T0_ffff();
gen_check_io(s, ot, 0, pc_start - s->cs_base);
gen_op_in[ot]();
gen_op_mov_reg_T1[ot][R_EAX]();
else
ot = dflag ? OT_LONG : OT_WORD;
gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
+ gen_op_andl_T0_ffff();
gen_check_io(s, ot, 0, pc_start - s->cs_base);
gen_op_mov_TN_reg[ot][1][R_EAX]();
gen_op_out[ot]();
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
gen_op_jmp_im(pc_start - s->cs_base);
- gen_op_iret_protected(s->dflag);
+ gen_op_iret_protected(s->dflag, s->pc - s->cs_base);
s->cc_op = CC_OP_EFLAGS;
}
gen_eob(s);
modrm = ldub_code(s->pc++);
reg = (modrm >> 3) & 7;
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+ /* NOTE: in order to handle the 0 case, we must load the
+ result. It could be optimized with a generated jump */
+ gen_op_mov_TN_reg[ot][1][reg]();
gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
- /* NOTE: we always write back the result. Intel doc says it is
- undefined if T0 == 0 */
- gen_op_mov_reg_T0[ot][reg]();
+ gen_op_mov_reg_T1[ot][reg]();
s->cc_op = CC_OP_LOGICB + ot;
break;
/************************/
/************************/
/* misc */
case 0x90: /* nop */
+ /* XXX: correct lock test for all insn */
+ if (prefixes & PREFIX_LOCK)
+ goto illegal_op;
break;
case 0x9b: /* fwait */
+ if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
+ (HF_MP_MASK | HF_TS_MASK)) {
+ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
+ } else {
+ if (s->cc_op != CC_OP_DYNAMIC)
+ gen_op_set_cc_op(s->cc_op);
+ gen_op_jmp_im(pc_start - s->cs_base);
+ gen_op_fwait();
+ }
break;
case 0xcc: /* int3 */
gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
mod = (modrm >> 6) & 3;
if (mod == 3)
goto illegal_op;
- gen_op_mov_reg_T0[ot][reg]();
+ gen_op_mov_TN_reg[ot][0][reg]();
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
if (ot == OT_WORD)
gen_op_boundw(pc_start - s->cs_base);
case 0x131: /* rdtsc */
gen_op_rdtsc();
break;
+ case 0x134: /* sysenter */
+ if (!s->pe) {
+ gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+ } else {
+ if (s->cc_op != CC_OP_DYNAMIC) {
+ gen_op_set_cc_op(s->cc_op);
+ s->cc_op = CC_OP_DYNAMIC;
+ }
+ gen_op_jmp_im(pc_start - s->cs_base);
+ gen_op_sysenter();
+ gen_eob(s);
+ }
+ break;
+ case 0x135: /* sysexit */
+ if (!s->pe) {
+ gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+ } else {
+ if (s->cc_op != CC_OP_DYNAMIC) {
+ gen_op_set_cc_op(s->cc_op);
+ s->cc_op = CC_OP_DYNAMIC;
+ }
+ gen_op_jmp_im(pc_start - s->cs_base);
+ gen_op_sysexit();
+ gen_eob(s);
+ }
+ break;
case 0x1a2: /* cpuid */
gen_op_cpuid();
break;
goto illegal_op;
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
gen_op_invlpg_A0();
+ gen_op_jmp_im(s->pc - s->cs_base);
+ gen_eob(s);
}
break;
default:
goto illegal_op;
}
break;
+ case 0x108: /* invd */
+ case 0x109: /* wbinvd */
+ if (s->cpl != 0) {
+ gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+ } else {
+ /* nothing to do */
+ }
+ break;
case 0x63: /* arpl */
if (!s->pe || s->vm86)
goto illegal_op;
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else {
gen_op_clts();
+ /* abort block because static cpu state changed */
+ gen_op_jmp_im(s->pc - s->cs_base);
+ gen_eob(s);
}
break;
default:
gen_op_unlock();
return s->pc;
illegal_op:
+ if (s->prefix & PREFIX_LOCK)
+ gen_op_unlock();
/* XXX: ensure that no lock was generated */
gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
return s->pc;
[INDEX_op_das] = CC_A | CC_C,
[INDEX_op_daa] = CC_A | CC_C,
- [INDEX_op_adcb_T0_T1_cc] = CC_C,
- [INDEX_op_adcw_T0_T1_cc] = CC_C,
- [INDEX_op_adcl_T0_T1_cc] = CC_C,
- [INDEX_op_sbbb_T0_T1_cc] = CC_C,
- [INDEX_op_sbbw_T0_T1_cc] = CC_C,
- [INDEX_op_sbbl_T0_T1_cc] = CC_C,
-
- [INDEX_op_adcb_mem_T0_T1_cc] = CC_C,
- [INDEX_op_adcw_mem_T0_T1_cc] = CC_C,
- [INDEX_op_adcl_mem_T0_T1_cc] = CC_C,
- [INDEX_op_sbbb_mem_T0_T1_cc] = CC_C,
- [INDEX_op_sbbw_mem_T0_T1_cc] = CC_C,
- [INDEX_op_sbbl_mem_T0_T1_cc] = CC_C,
-
/* subtle: due to the incl/decl implementation, C is used */
[INDEX_op_update_inc_cc] = CC_C,
[INDEX_op_cmc] = CC_C,
[INDEX_op_salc] = CC_C,
- [INDEX_op_rclb_T0_T1_cc] = CC_C,
- [INDEX_op_rclw_T0_T1_cc] = CC_C,
- [INDEX_op_rcll_T0_T1_cc] = CC_C,
- [INDEX_op_rcrb_T0_T1_cc] = CC_C,
- [INDEX_op_rcrw_T0_T1_cc] = CC_C,
- [INDEX_op_rcrl_T0_T1_cc] = CC_C,
-
- [INDEX_op_rclb_mem_T0_T1_cc] = CC_C,
- [INDEX_op_rclw_mem_T0_T1_cc] = CC_C,
- [INDEX_op_rcll_mem_T0_T1_cc] = CC_C,
- [INDEX_op_rcrb_mem_T0_T1_cc] = CC_C,
- [INDEX_op_rcrw_mem_T0_T1_cc] = CC_C,
- [INDEX_op_rcrl_mem_T0_T1_cc] = CC_C,
+ /* needed for correct flag optimisation before string ops */
+ [INDEX_op_jz_ecxw] = CC_OSZAPC,
+ [INDEX_op_jz_ecxl] = CC_OSZAPC,
+ [INDEX_op_jz_ecxw_im] = CC_OSZAPC,
+ [INDEX_op_jz_ecxl_im] = CC_OSZAPC,
+
+#define DEF_READF(SUFFIX)\
+ [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\
+\
+ [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\
+ [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,
+
+
+ DEF_READF( )
+ DEF_READF(_raw)
+#ifndef CONFIG_USER_ONLY
+ DEF_READF(_kernel)
+ DEF_READF(_user)
+#endif
};
/* flags written by an operation */
[INDEX_op_update_inc_cc] = CC_OSZAPC,
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
-
- [INDEX_op_adcb_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_adcw_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_adcl_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sbbb_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sbbw_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sbbl_mem_T0_T1_cc] = CC_OSZAPC,
-
[INDEX_op_mulb_AL_T0] = CC_OSZAPC,
[INDEX_op_imulb_AL_T0] = CC_OSZAPC,
[INDEX_op_mulw_AX_T0] = CC_OSZAPC,
[INDEX_op_stc] = CC_C,
[INDEX_op_cmc] = CC_C,
- [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
-
- [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
-
- [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
-
- [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
-
- [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
-
- [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
- [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
-
- [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
- [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
-
- [INDEX_op_rolb_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rolw_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_roll_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rorb_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rorw_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rorl_mem_T0_T1_cc] = CC_O | CC_C,
-
- [INDEX_op_rclb_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rclw_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcll_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcrb_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcrw_mem_T0_T1_cc] = CC_O | CC_C,
- [INDEX_op_rcrl_mem_T0_T1_cc] = CC_O | CC_C,
-
- [INDEX_op_shlb_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shlw_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shll_mem_T0_T1_cc] = CC_OSZAPC,
-
- [INDEX_op_shrb_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shrw_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_shrl_mem_T0_T1_cc] = CC_OSZAPC,
-
- [INDEX_op_sarb_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sarw_mem_T0_T1_cc] = CC_OSZAPC,
- [INDEX_op_sarl_mem_T0_T1_cc] = CC_OSZAPC,
-
- [INDEX_op_shldw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shldl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shldw_mem_T0_T1_im_cc] = CC_OSZAPC,
- [INDEX_op_shldl_mem_T0_T1_im_cc] = CC_OSZAPC,
-
- [INDEX_op_shrdw_mem_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shrdl_mem_T0_T1_ECX_cc] = CC_OSZAPC,
- [INDEX_op_shrdw_mem_T0_T1_im_cc] = CC_OSZAPC,
- [INDEX_op_shrdl_mem_T0_T1_im_cc] = CC_OSZAPC,
-
[INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
- [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc] = CC_OSZAPC,
- [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc] = CC_OSZAPC,
- [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc] = CC_OSZAPC,
-
[INDEX_op_cmpxchg8b] = CC_Z,
[INDEX_op_lar] = CC_Z,
[INDEX_op_lsl] = CC_Z,
[INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
[INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
+
+#define DEF_WRITEF(SUFFIX)\
+ [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+\
+ [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+\
+ [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+ [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\
+\
+ [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+\
+ [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+\
+ [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+ [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\
+\
+ [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
+ [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
+ [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
+ [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
+\
+ [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
+ [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\
+ [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
+ [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\
+\
+ [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
+ [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\
+ [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,
+
+
+ DEF_WRITEF( )
+ DEF_WRITEF(_raw)
+#ifndef CONFIG_USER_ONLY
+ DEF_WRITEF(_kernel)
+ DEF_WRITEF(_user)
+#endif
};
/* simpler form of an operation if no flags need to be generated */
/* broken: CC_OP logic must be rewritten */
[INDEX_op_update_inc_cc] = INDEX_op_nop,
#endif
- [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
- [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
- [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
-
- [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
- [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
- [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
-
- [INDEX_op_rolb_mem_T0_T1_cc] = INDEX_op_rolb_mem_T0_T1,
- [INDEX_op_rolw_mem_T0_T1_cc] = INDEX_op_rolw_mem_T0_T1,
- [INDEX_op_roll_mem_T0_T1_cc] = INDEX_op_roll_mem_T0_T1,
-
- [INDEX_op_rorb_mem_T0_T1_cc] = INDEX_op_rorb_mem_T0_T1,
- [INDEX_op_rorw_mem_T0_T1_cc] = INDEX_op_rorw_mem_T0_T1,
- [INDEX_op_rorl_mem_T0_T1_cc] = INDEX_op_rorl_mem_T0_T1,
[INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
[INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
[INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
[INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
[INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
+
+#define DEF_SIMPLER(SUFFIX)\
+ [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\
+ [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\
+ [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\
+\
+ [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\
+ [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\
+ [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,
+
+ DEF_SIMPLER( )
+ DEF_SIMPLER(_raw)
+#ifndef CONFIG_USER_ONLY
+ DEF_SIMPLER(_kernel)
+ DEF_SIMPLER(_user)
+#endif
};
void optimize_flags_init(void)
DisasContext dc1, *dc = &dc1;
uint8_t *pc_ptr;
uint16_t *gen_opc_end;
- int flags, j, lj;
+ int flags, j, lj, cflags;
uint8_t *pc_start;
uint8_t *cs_base;
pc_start = (uint8_t *)tb->pc;
cs_base = (uint8_t *)tb->cs_base;
flags = tb->flags;
-
- dc->pe = env->cr[0] & CR0_PE_MASK;
+ cflags = tb->cflags;
+
+ dc->pe = (flags >> HF_PE_SHIFT) & 1;
dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
else
dc->mem_index = 3;
}
+ dc->flags = flags;
dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
(flags & HF_INHIBIT_IRQ_MASK)
#ifndef CONFIG_SOFTMMU
|| (flags & HF_SOFTMMU_MASK)
#endif
);
+#if 0
+ /* check addseg logic */
+ if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
+ printf("ERROR addseg\n");
+#endif
+
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
the flag and abort the translation to give the irqs a
change to be happen */
if (dc->tf || dc->singlestep_enabled ||
- (flags & HF_INHIBIT_IRQ_MASK)) {
+ (flags & HF_INHIBIT_IRQ_MASK) ||
+ (cflags & CF_SINGLE_INSN)) {
gen_op_jmp_im(pc_ptr - dc->cs_base);
gen_eob(dc);
break;
}
#ifdef DEBUG_DISAS
- if (loglevel) {
+ if (loglevel & CPU_LOG_TB_CPU) {
+ cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
+ }
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "----------------\n");
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32);
fprintf(logfile, "\n");
-
- fprintf(logfile, "OP:\n");
- dump_ops(gen_opc_buf, gen_opparam_buf);
- fprintf(logfile, "\n");
+ if (loglevel & CPU_LOG_TB_OP) {
+ fprintf(logfile, "OP:\n");
+ dump_ops(gen_opc_buf, gen_opparam_buf);
+ fprintf(logfile, "\n");
+ }
}
#endif
optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
#ifdef DEBUG_DISAS
- if (loglevel) {
+ if (loglevel & CPU_LOG_TB_OP_OPT) {
fprintf(logfile, "AFTER FLAGS OPT:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");