mirror of https://github.com/proxmox/mirror_qemu
converted string OPs and LOOP insns to TCG
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4494 c046a42c-6fe2-441c-8c8c-71466251a162master
parent
cd31fefaf2
commit
6e0d8677cb
|
@ -263,55 +263,6 @@ void OPPROTO op_cmpxchg8b(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* string ops helpers */
|
|
||||||
|
|
||||||
void OPPROTO op_addl_ESI_T0(void)
|
|
||||||
{
|
|
||||||
ESI = (uint32_t)(ESI + T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_addw_ESI_T0(void)
|
|
||||||
{
|
|
||||||
ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_addl_EDI_T0(void)
|
|
||||||
{
|
|
||||||
EDI = (uint32_t)(EDI + T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_addw_EDI_T0(void)
|
|
||||||
{
|
|
||||||
EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_decl_ECX(void)
|
|
||||||
{
|
|
||||||
ECX = (uint32_t)(ECX - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_decw_ECX(void)
|
|
||||||
{
|
|
||||||
ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
void OPPROTO op_addq_ESI_T0(void)
|
|
||||||
{
|
|
||||||
ESI = (ESI + T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_addq_EDI_T0(void)
|
|
||||||
{
|
|
||||||
EDI = (EDI + T0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO op_decq_ECX(void)
|
|
||||||
{
|
|
||||||
ECX--;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* bcd */
|
/* bcd */
|
||||||
|
|
||||||
void OPPROTO op_aam(void)
|
void OPPROTO op_aam(void)
|
||||||
|
@ -460,13 +411,6 @@ void OPPROTO op_jnz_T0_label(void)
|
||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_jz_T0_label(void)
|
|
||||||
{
|
|
||||||
if (!T0)
|
|
||||||
GOTO_LABEL_PARAM(1);
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* slow set cases (compute x86 flags) */
|
/* slow set cases (compute x86 flags) */
|
||||||
void OPPROTO op_seto_T0_cc(void)
|
void OPPROTO op_seto_T0_cc(void)
|
||||||
{
|
{
|
||||||
|
@ -527,11 +471,6 @@ void OPPROTO op_xor_T0_1(void)
|
||||||
T0 ^= 1;
|
T0 ^= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_mov_T0_cc(void)
|
|
||||||
{
|
|
||||||
T0 = cc_table[CC_OP].compute_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: clear VIF/VIP in all ops ? */
|
/* XXX: clear VIF/VIP in all ops ? */
|
||||||
|
|
||||||
void OPPROTO op_movl_eflags_T0(void)
|
void OPPROTO op_movl_eflags_T0(void)
|
||||||
|
|
|
@ -118,40 +118,6 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void)
|
||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* oldies */
|
|
||||||
|
|
||||||
#if DATA_BITS >= 16
|
|
||||||
|
|
||||||
void OPPROTO glue(op_loopnz, SUFFIX)(void)
|
|
||||||
{
|
|
||||||
if ((DATA_TYPE)ECX != 0 && !(T0 & CC_Z))
|
|
||||||
GOTO_LABEL_PARAM(1);
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO glue(op_loopz, SUFFIX)(void)
|
|
||||||
{
|
|
||||||
if ((DATA_TYPE)ECX != 0 && (T0 & CC_Z))
|
|
||||||
GOTO_LABEL_PARAM(1);
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
|
|
||||||
{
|
|
||||||
if ((DATA_TYPE)ECX == 0)
|
|
||||||
GOTO_LABEL_PARAM(1);
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OPPROTO glue(op_jnz_ecx, SUFFIX)(void)
|
|
||||||
{
|
|
||||||
if ((DATA_TYPE)ECX != 0)
|
|
||||||
GOTO_LABEL_PARAM(1);
|
|
||||||
FORCE_RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* various optimized set cases */
|
/* various optimized set cases */
|
||||||
|
|
||||||
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
|
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
|
||||||
|
@ -200,13 +166,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
|
||||||
T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
|
T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* string operations */
|
|
||||||
|
|
||||||
void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
|
|
||||||
{
|
|
||||||
T0 = DF << SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef DATA_BITS
|
#undef DATA_BITS
|
||||||
#undef SHIFT_MASK
|
#undef SHIFT_MASK
|
||||||
#undef SHIFT1_MASK
|
#undef SHIFT1_MASK
|
||||||
|
|
|
@ -402,31 +402,57 @@ static inline void gen_op_jmp_T0(void)
|
||||||
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip));
|
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_op_addw_ESP_im(int32_t val)
|
static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
|
||||||
{
|
{
|
||||||
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
|
switch(size) {
|
||||||
tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
|
case 0:
|
||||||
tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]) + REG_W_OFFSET);
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
|
tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
|
||||||
|
tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
|
tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
|
tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff);
|
||||||
|
#endif
|
||||||
|
tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
|
break;
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
|
case 2:
|
||||||
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
|
tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
|
||||||
|
tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_op_addl_ESP_im(int32_t val)
|
static inline void gen_op_add_reg_T0(int size, int reg)
|
||||||
{
|
{
|
||||||
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
|
switch(size) {
|
||||||
tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
|
case 0:
|
||||||
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
|
tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]);
|
||||||
|
tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
|
tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]);
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff);
|
tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff);
|
||||||
#endif
|
#endif
|
||||||
tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
|
tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
}
|
break;
|
||||||
|
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
static inline void gen_op_addq_ESP_im(int32_t val)
|
case 2:
|
||||||
{
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
|
tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]);
|
||||||
tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val);
|
tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]));
|
||||||
tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]));
|
break;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void gen_op_set_cc_op(int32_t val)
|
static inline void gen_op_set_cc_op(int32_t val)
|
||||||
{
|
{
|
||||||
|
@ -663,30 +689,59 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GenOpFunc *gen_op_movl_T0_Dshift[4] = {
|
static inline void gen_op_movl_T0_Dshift(int ot)
|
||||||
gen_op_movl_T0_Dshiftb,
|
{
|
||||||
gen_op_movl_T0_Dshiftw,
|
tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUState, df));
|
||||||
gen_op_movl_T0_Dshiftl,
|
tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
|
||||||
X86_64_ONLY(gen_op_movl_T0_Dshiftq),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static GenOpFunc1 *gen_op_jnz_ecx[3] = {
|
static void gen_extu(int ot, TCGv reg)
|
||||||
gen_op_jnz_ecxw,
|
{
|
||||||
gen_op_jnz_ecxl,
|
switch(ot) {
|
||||||
X86_64_ONLY(gen_op_jnz_ecxq),
|
case OT_BYTE:
|
||||||
};
|
tcg_gen_ext8u_tl(reg, reg);
|
||||||
|
break;
|
||||||
|
case OT_WORD:
|
||||||
|
tcg_gen_ext16u_tl(reg, reg);
|
||||||
|
break;
|
||||||
|
case OT_LONG:
|
||||||
|
tcg_gen_ext32u_tl(reg, reg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GenOpFunc1 *gen_op_jz_ecx[3] = {
|
static void gen_exts(int ot, TCGv reg)
|
||||||
gen_op_jz_ecxw,
|
{
|
||||||
gen_op_jz_ecxl,
|
switch(ot) {
|
||||||
X86_64_ONLY(gen_op_jz_ecxq),
|
case OT_BYTE:
|
||||||
};
|
tcg_gen_ext8s_tl(reg, reg);
|
||||||
|
break;
|
||||||
|
case OT_WORD:
|
||||||
|
tcg_gen_ext16s_tl(reg, reg);
|
||||||
|
break;
|
||||||
|
case OT_LONG:
|
||||||
|
tcg_gen_ext32s_tl(reg, reg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GenOpFunc *gen_op_dec_ECX[3] = {
|
static inline void gen_op_jnz_ecx(int size, int label1)
|
||||||
gen_op_decw_ECX,
|
{
|
||||||
gen_op_decl_ECX,
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX]));
|
||||||
X86_64_ONLY(gen_op_decq_ECX),
|
gen_extu(size + 1, cpu_tmp0);
|
||||||
};
|
tcg_gen_brcond_tl(TCG_COND_NE, cpu_tmp0, tcg_const_tl(0), label1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gen_op_jz_ecx(int size, int label1)
|
||||||
|
{
|
||||||
|
tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX]));
|
||||||
|
gen_extu(size + 1, cpu_tmp0);
|
||||||
|
tcg_gen_brcond_tl(TCG_COND_EQ, cpu_tmp0, tcg_const_tl(0), label1);
|
||||||
|
}
|
||||||
|
|
||||||
static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
|
static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = {
|
||||||
{
|
{
|
||||||
|
@ -760,20 +815,9 @@ static inline void gen_movs(DisasContext *s, int ot)
|
||||||
gen_op_ld_T0_A0(ot + s->mem_index);
|
gen_op_ld_T0_A0(ot + s->mem_index);
|
||||||
gen_string_movl_A0_EDI(s);
|
gen_string_movl_A0_EDI(s);
|
||||||
gen_op_st_T0_A0(ot + s->mem_index);
|
gen_op_st_T0_A0(ot + s->mem_index);
|
||||||
gen_op_movl_T0_Dshift[ot]();
|
gen_op_movl_T0_Dshift(ot);
|
||||||
#ifdef TARGET_X86_64
|
gen_op_add_reg_T0(s->aflag, R_ESI);
|
||||||
if (s->aflag == 2) {
|
gen_op_add_reg_T0(s->aflag, R_EDI);
|
||||||
gen_op_addq_ESI_T0();
|
|
||||||
gen_op_addq_EDI_T0();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s->aflag) {
|
|
||||||
gen_op_addl_ESI_T0();
|
|
||||||
gen_op_addl_EDI_T0();
|
|
||||||
} else {
|
|
||||||
gen_op_addw_ESI_T0();
|
|
||||||
gen_op_addw_EDI_T0();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_update_cc_op(DisasContext *s)
|
static inline void gen_update_cc_op(DisasContext *s)
|
||||||
|
@ -822,7 +866,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
|
||||||
|
|
||||||
l1 = gen_new_label();
|
l1 = gen_new_label();
|
||||||
l2 = gen_new_label();
|
l2 = gen_new_label();
|
||||||
gen_op_jnz_ecx[s->aflag](l1);
|
gen_op_jnz_ecx(s->aflag, l1);
|
||||||
gen_set_label(l2);
|
gen_set_label(l2);
|
||||||
gen_jmp_tb(s, next_eip, 1);
|
gen_jmp_tb(s, next_eip, 1);
|
||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
|
@ -834,17 +878,8 @@ static inline void gen_stos(DisasContext *s, int ot)
|
||||||
gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
|
gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
|
||||||
gen_string_movl_A0_EDI(s);
|
gen_string_movl_A0_EDI(s);
|
||||||
gen_op_st_T0_A0(ot + s->mem_index);
|
gen_op_st_T0_A0(ot + s->mem_index);
|
||||||
gen_op_movl_T0_Dshift[ot]();
|
gen_op_movl_T0_Dshift(ot);
|
||||||
#ifdef TARGET_X86_64
|
gen_op_add_reg_T0(s->aflag, R_EDI);
|
||||||
if (s->aflag == 2) {
|
|
||||||
gen_op_addq_EDI_T0();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s->aflag) {
|
|
||||||
gen_op_addl_EDI_T0();
|
|
||||||
} else {
|
|
||||||
gen_op_addw_EDI_T0();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_lods(DisasContext *s, int ot)
|
static inline void gen_lods(DisasContext *s, int ot)
|
||||||
|
@ -852,17 +887,8 @@ static inline void gen_lods(DisasContext *s, int ot)
|
||||||
gen_string_movl_A0_ESI(s);
|
gen_string_movl_A0_ESI(s);
|
||||||
gen_op_ld_T0_A0(ot + s->mem_index);
|
gen_op_ld_T0_A0(ot + s->mem_index);
|
||||||
gen_op_mov_reg_T0(ot, R_EAX);
|
gen_op_mov_reg_T0(ot, R_EAX);
|
||||||
gen_op_movl_T0_Dshift[ot]();
|
gen_op_movl_T0_Dshift(ot);
|
||||||
#ifdef TARGET_X86_64
|
gen_op_add_reg_T0(s->aflag, R_ESI);
|
||||||
if (s->aflag == 2) {
|
|
||||||
gen_op_addq_ESI_T0();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s->aflag) {
|
|
||||||
gen_op_addl_ESI_T0();
|
|
||||||
} else {
|
|
||||||
gen_op_addw_ESI_T0();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_scas(DisasContext *s, int ot)
|
static inline void gen_scas(DisasContext *s, int ot)
|
||||||
|
@ -871,17 +897,8 @@ static inline void gen_scas(DisasContext *s, int ot)
|
||||||
gen_string_movl_A0_EDI(s);
|
gen_string_movl_A0_EDI(s);
|
||||||
gen_op_ld_T1_A0(ot + s->mem_index);
|
gen_op_ld_T1_A0(ot + s->mem_index);
|
||||||
gen_op_cmpl_T0_T1_cc();
|
gen_op_cmpl_T0_T1_cc();
|
||||||
gen_op_movl_T0_Dshift[ot]();
|
gen_op_movl_T0_Dshift(ot);
|
||||||
#ifdef TARGET_X86_64
|
gen_op_add_reg_T0(s->aflag, R_EDI);
|
||||||
if (s->aflag == 2) {
|
|
||||||
gen_op_addq_EDI_T0();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s->aflag) {
|
|
||||||
gen_op_addl_EDI_T0();
|
|
||||||
} else {
|
|
||||||
gen_op_addw_EDI_T0();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_cmps(DisasContext *s, int ot)
|
static inline void gen_cmps(DisasContext *s, int ot)
|
||||||
|
@ -891,25 +908,16 @@ static inline void gen_cmps(DisasContext *s, int ot)
|
||||||
gen_string_movl_A0_EDI(s);
|
gen_string_movl_A0_EDI(s);
|
||||||
gen_op_ld_T1_A0(ot + s->mem_index);
|
gen_op_ld_T1_A0(ot + s->mem_index);
|
||||||
gen_op_cmpl_T0_T1_cc();
|
gen_op_cmpl_T0_T1_cc();
|
||||||
gen_op_movl_T0_Dshift[ot]();
|
gen_op_movl_T0_Dshift(ot);
|
||||||
#ifdef TARGET_X86_64
|
gen_op_add_reg_T0(s->aflag, R_ESI);
|
||||||
if (s->aflag == 2) {
|
gen_op_add_reg_T0(s->aflag, R_EDI);
|
||||||
gen_op_addq_ESI_T0();
|
|
||||||
gen_op_addq_EDI_T0();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s->aflag) {
|
|
||||||
gen_op_addl_ESI_T0();
|
|
||||||
gen_op_addl_EDI_T0();
|
|
||||||
} else {
|
|
||||||
gen_op_addw_ESI_T0();
|
|
||||||
gen_op_addw_EDI_T0();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_ins(DisasContext *s, int ot)
|
static inline void gen_ins(DisasContext *s, int ot)
|
||||||
{
|
{
|
||||||
gen_string_movl_A0_EDI(s);
|
gen_string_movl_A0_EDI(s);
|
||||||
|
/* Note: we must do this dummy write first to be restartable in
|
||||||
|
case of page fault. */
|
||||||
gen_op_movl_T0_0();
|
gen_op_movl_T0_0();
|
||||||
gen_op_st_T0_A0(ot + s->mem_index);
|
gen_op_st_T0_A0(ot + s->mem_index);
|
||||||
gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
|
gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
|
||||||
|
@ -917,17 +925,8 @@ static inline void gen_ins(DisasContext *s, int ot)
|
||||||
tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
|
tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
|
||||||
tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[0], cpu_tmp2_i32);
|
tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[0], cpu_tmp2_i32);
|
||||||
gen_op_st_T0_A0(ot + s->mem_index);
|
gen_op_st_T0_A0(ot + s->mem_index);
|
||||||
gen_op_movl_T0_Dshift[ot]();
|
gen_op_movl_T0_Dshift(ot);
|
||||||
#ifdef TARGET_X86_64
|
gen_op_add_reg_T0(s->aflag, R_EDI);
|
||||||
if (s->aflag == 2) {
|
|
||||||
gen_op_addq_EDI_T0();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s->aflag) {
|
|
||||||
gen_op_addl_EDI_T0();
|
|
||||||
} else {
|
|
||||||
gen_op_addw_EDI_T0();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_outs(DisasContext *s, int ot)
|
static inline void gen_outs(DisasContext *s, int ot)
|
||||||
|
@ -941,17 +940,8 @@ static inline void gen_outs(DisasContext *s, int ot)
|
||||||
tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
|
tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
|
||||||
tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32);
|
tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32);
|
||||||
|
|
||||||
gen_op_movl_T0_Dshift[ot]();
|
gen_op_movl_T0_Dshift(ot);
|
||||||
#ifdef TARGET_X86_64
|
gen_op_add_reg_T0(s->aflag, R_ESI);
|
||||||
if (s->aflag == 2) {
|
|
||||||
gen_op_addq_ESI_T0();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s->aflag) {
|
|
||||||
gen_op_addl_ESI_T0();
|
|
||||||
} else {
|
|
||||||
gen_op_addw_ESI_T0();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* same method as Valgrind : we generate jumps to current or next
|
/* same method as Valgrind : we generate jumps to current or next
|
||||||
|
@ -964,11 +954,11 @@ static inline void gen_repz_ ## op(DisasContext *s, int ot, \
|
||||||
gen_update_cc_op(s); \
|
gen_update_cc_op(s); \
|
||||||
l2 = gen_jz_ecx_string(s, next_eip); \
|
l2 = gen_jz_ecx_string(s, next_eip); \
|
||||||
gen_ ## op(s, ot); \
|
gen_ ## op(s, ot); \
|
||||||
gen_op_dec_ECX[s->aflag](); \
|
gen_op_add_reg_im(s->aflag, R_ECX, -1); \
|
||||||
/* a loop would cause two single step exceptions if ECX = 1 \
|
/* a loop would cause two single step exceptions if ECX = 1 \
|
||||||
before rep string_insn */ \
|
before rep string_insn */ \
|
||||||
if (!s->jmp_opt) \
|
if (!s->jmp_opt) \
|
||||||
gen_op_jz_ecx[s->aflag](l2); \
|
gen_op_jz_ecx(s->aflag, l2); \
|
||||||
gen_jmp(s, cur_eip); \
|
gen_jmp(s, cur_eip); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,11 +972,11 @@ static inline void gen_repz_ ## op(DisasContext *s, int ot, \
|
||||||
gen_update_cc_op(s); \
|
gen_update_cc_op(s); \
|
||||||
l2 = gen_jz_ecx_string(s, next_eip); \
|
l2 = gen_jz_ecx_string(s, next_eip); \
|
||||||
gen_ ## op(s, ot); \
|
gen_ ## op(s, ot); \
|
||||||
gen_op_dec_ECX[s->aflag](); \
|
gen_op_add_reg_im(s->aflag, R_ECX, -1); \
|
||||||
gen_op_set_cc_op(CC_OP_SUBB + ot); \
|
gen_op_set_cc_op(CC_OP_SUBB + ot); \
|
||||||
gen_op_string_jnz_sub[nz][ot](l2);\
|
gen_op_string_jnz_sub[nz][ot](l2);\
|
||||||
if (!s->jmp_opt) \
|
if (!s->jmp_opt) \
|
||||||
gen_op_jz_ecx[s->aflag](l2); \
|
gen_op_jz_ecx(s->aflag, l2); \
|
||||||
gen_jmp(s, cur_eip); \
|
gen_jmp(s, cur_eip); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,25 +1043,6 @@ static GenOpFunc1 *gen_jcc_sub[4][8] = {
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
static GenOpFunc1 *gen_op_loop[3][4] = {
|
|
||||||
[0] = {
|
|
||||||
gen_op_loopnzw,
|
|
||||||
gen_op_loopzw,
|
|
||||||
gen_op_jnz_ecxw,
|
|
||||||
},
|
|
||||||
[1] = {
|
|
||||||
gen_op_loopnzl,
|
|
||||||
gen_op_loopzl,
|
|
||||||
gen_op_jnz_ecxl,
|
|
||||||
},
|
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
[2] = {
|
|
||||||
gen_op_loopnzq,
|
|
||||||
gen_op_loopzq,
|
|
||||||
gen_op_jnz_ecxq,
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static GenOpFunc *gen_setcc_slow[8] = {
|
static GenOpFunc *gen_setcc_slow[8] = {
|
||||||
gen_op_seto_T0_cc,
|
gen_op_seto_T0_cc,
|
||||||
|
@ -1316,40 +1287,6 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c)
|
||||||
tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
|
tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_extu(int ot, TCGv reg)
|
|
||||||
{
|
|
||||||
switch(ot) {
|
|
||||||
case OT_BYTE:
|
|
||||||
tcg_gen_ext8u_tl(reg, reg);
|
|
||||||
break;
|
|
||||||
case OT_WORD:
|
|
||||||
tcg_gen_ext16u_tl(reg, reg);
|
|
||||||
break;
|
|
||||||
case OT_LONG:
|
|
||||||
tcg_gen_ext32u_tl(reg, reg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gen_exts(int ot, TCGv reg)
|
|
||||||
{
|
|
||||||
switch(ot) {
|
|
||||||
case OT_BYTE:
|
|
||||||
tcg_gen_ext8s_tl(reg, reg);
|
|
||||||
break;
|
|
||||||
case OT_WORD:
|
|
||||||
tcg_gen_ext16s_tl(reg, reg);
|
|
||||||
break;
|
|
||||||
case OT_LONG:
|
|
||||||
tcg_gen_ext32s_tl(reg, reg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: add faster immediate case */
|
/* XXX: add faster immediate case */
|
||||||
static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
|
static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
|
||||||
int is_right, int is_arith)
|
int is_right, int is_arith)
|
||||||
|
@ -2318,13 +2255,13 @@ static inline void gen_stack_update(DisasContext *s, int addend)
|
||||||
{
|
{
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
if (CODE64(s)) {
|
if (CODE64(s)) {
|
||||||
gen_op_addq_ESP_im(addend);
|
gen_op_add_reg_im(2, R_ESP, addend);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (s->ss32) {
|
if (s->ss32) {
|
||||||
gen_op_addl_ESP_im(addend);
|
gen_op_add_reg_im(1, R_ESP, addend);
|
||||||
} else {
|
} else {
|
||||||
gen_op_addw_ESP_im(addend);
|
gen_op_add_reg_im(0, R_ESP, addend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6066,13 +6003,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
|
||||||
break;
|
break;
|
||||||
case 0xe0: /* loopnz */
|
case 0xe0: /* loopnz */
|
||||||
case 0xe1: /* loopz */
|
case 0xe1: /* loopz */
|
||||||
if (s->cc_op != CC_OP_DYNAMIC)
|
|
||||||
gen_op_set_cc_op(s->cc_op);
|
|
||||||
/* FALL THRU */
|
|
||||||
case 0xe2: /* loop */
|
case 0xe2: /* loop */
|
||||||
case 0xe3: /* jecxz */
|
case 0xe3: /* jecxz */
|
||||||
{
|
{
|
||||||
int l1, l2;
|
int l1, l2, l3;
|
||||||
|
|
||||||
tval = (int8_t)insn_get(s, OT_BYTE);
|
tval = (int8_t)insn_get(s, OT_BYTE);
|
||||||
next_eip = s->pc - s->cs_base;
|
next_eip = s->pc - s->cs_base;
|
||||||
|
@ -6082,18 +6016,39 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
|
||||||
|
|
||||||
l1 = gen_new_label();
|
l1 = gen_new_label();
|
||||||
l2 = gen_new_label();
|
l2 = gen_new_label();
|
||||||
|
l3 = gen_new_label();
|
||||||
b &= 3;
|
b &= 3;
|
||||||
if (b == 3) {
|
switch(b) {
|
||||||
gen_op_jz_ecx[s->aflag](l1);
|
case 0: /* loopnz */
|
||||||
} else {
|
case 1: /* loopz */
|
||||||
gen_op_dec_ECX[s->aflag]();
|
if (s->cc_op != CC_OP_DYNAMIC)
|
||||||
if (b <= 1)
|
gen_op_set_cc_op(s->cc_op);
|
||||||
gen_op_mov_T0_cc();
|
gen_op_add_reg_im(s->aflag, R_ECX, -1);
|
||||||
gen_op_loop[s->aflag][b](l1);
|
gen_op_jz_ecx(s->aflag, l3);
|
||||||
|
gen_compute_eflags(cpu_tmp0);
|
||||||
|
tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_Z);
|
||||||
|
if (b == 0) {
|
||||||
|
tcg_gen_brcond_tl(TCG_COND_EQ,
|
||||||
|
cpu_tmp0, tcg_const_tl(0), l1);
|
||||||
|
} else {
|
||||||
|
tcg_gen_brcond_tl(TCG_COND_NE,
|
||||||
|
cpu_tmp0, tcg_const_tl(0), l1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: /* loop */
|
||||||
|
gen_op_add_reg_im(s->aflag, R_ECX, -1);
|
||||||
|
gen_op_jnz_ecx(s->aflag, l1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case 3: /* jcxz */
|
||||||
|
gen_op_jz_ecx(s->aflag, l1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gen_set_label(l3);
|
||||||
gen_jmp_im(next_eip);
|
gen_jmp_im(next_eip);
|
||||||
gen_op_jmp_label(l2);
|
gen_op_jmp_label(l2);
|
||||||
|
|
||||||
gen_set_label(l1);
|
gen_set_label(l1);
|
||||||
gen_jmp_im(tval);
|
gen_jmp_im(tval);
|
||||||
gen_set_label(l2);
|
gen_set_label(l2);
|
||||||
|
|
Loading…
Reference in New Issue