target/i386: split gen_ldst_modrm for load and store
The is_store argument of gen_ldst_modrm has only ever been passed a constant. Just split the function in two. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
b3c49e654a
commit
420d60caad
@ -1828,27 +1828,33 @@ static void gen_add_A0_ds_seg(DisasContext *s)
|
|||||||
gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
|
gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate modrm memory load or store of 'reg'. */
|
/* generate modrm load of memory or register. */
|
||||||
static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
|
static void gen_ld_modrm(CPUX86State *env, DisasContext *s, int modrm, MemOp ot)
|
||||||
MemOp ot, int is_store)
|
|
||||||
{
|
{
|
||||||
int mod, rm;
|
int mod, rm;
|
||||||
|
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
rm = (modrm & 7) | REX_B(s);
|
rm = (modrm & 7) | REX_B(s);
|
||||||
if (mod == 3) {
|
if (mod == 3) {
|
||||||
if (is_store) {
|
|
||||||
gen_op_mov_reg_v(s, ot, rm, s->T0);
|
|
||||||
} else {
|
|
||||||
gen_op_mov_v_reg(s, ot, s->T0, rm);
|
gen_op_mov_v_reg(s, ot, s->T0, rm);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
gen_lea_modrm(env, s, modrm);
|
gen_lea_modrm(env, s, modrm);
|
||||||
if (is_store) {
|
|
||||||
gen_op_st_v(s, ot, s->T0, s->A0);
|
|
||||||
} else {
|
|
||||||
gen_op_ld_v(s, ot, s->T0, s->A0);
|
gen_op_ld_v(s, ot, s->T0, s->A0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate modrm store of memory or register. */
|
||||||
|
static void gen_st_modrm(CPUX86State *env, DisasContext *s, int modrm, MemOp ot)
|
||||||
|
{
|
||||||
|
int mod, rm;
|
||||||
|
|
||||||
|
mod = (modrm >> 6) & 3;
|
||||||
|
rm = (modrm & 7) | REX_B(s);
|
||||||
|
if (mod == 3) {
|
||||||
|
gen_op_mov_reg_v(s, ot, rm, s->T0);
|
||||||
|
} else {
|
||||||
|
gen_lea_modrm(env, s, modrm);
|
||||||
|
gen_op_st_v(s, ot, s->T0, s->A0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3438,7 +3444,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
ot = dflag;
|
ot = dflag;
|
||||||
modrm = x86_ldub_code(env, s);
|
modrm = x86_ldub_code(env, s);
|
||||||
reg = ((modrm >> 3) & 7) | REX_R(s);
|
reg = ((modrm >> 3) & 7) | REX_R(s);
|
||||||
gen_ldst_modrm(env, s, modrm, ot, 0);
|
gen_ld_modrm(env, s, modrm, ot);
|
||||||
gen_extu(ot, s->T0);
|
gen_extu(ot, s->T0);
|
||||||
|
|
||||||
/* Note that lzcnt and tzcnt are in different extensions. */
|
/* Note that lzcnt and tzcnt are in different extensions. */
|
||||||
@ -3589,14 +3595,14 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
tcg_gen_ld32u_tl(s->T0, tcg_env,
|
tcg_gen_ld32u_tl(s->T0, tcg_env,
|
||||||
offsetof(CPUX86State, ldt.selector));
|
offsetof(CPUX86State, ldt.selector));
|
||||||
ot = mod == 3 ? dflag : MO_16;
|
ot = mod == 3 ? dflag : MO_16;
|
||||||
gen_ldst_modrm(env, s, modrm, ot, 1);
|
gen_st_modrm(env, s, modrm, ot);
|
||||||
break;
|
break;
|
||||||
case 2: /* lldt */
|
case 2: /* lldt */
|
||||||
if (!PE(s) || VM86(s))
|
if (!PE(s) || VM86(s))
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
if (check_cpl0(s)) {
|
if (check_cpl0(s)) {
|
||||||
gen_svm_check_intercept(s, SVM_EXIT_LDTR_WRITE);
|
gen_svm_check_intercept(s, SVM_EXIT_LDTR_WRITE);
|
||||||
gen_ldst_modrm(env, s, modrm, MO_16, 0);
|
gen_ld_modrm(env, s, modrm, MO_16);
|
||||||
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
|
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
|
||||||
gen_helper_lldt(tcg_env, s->tmp2_i32);
|
gen_helper_lldt(tcg_env, s->tmp2_i32);
|
||||||
}
|
}
|
||||||
@ -3611,14 +3617,14 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
tcg_gen_ld32u_tl(s->T0, tcg_env,
|
tcg_gen_ld32u_tl(s->T0, tcg_env,
|
||||||
offsetof(CPUX86State, tr.selector));
|
offsetof(CPUX86State, tr.selector));
|
||||||
ot = mod == 3 ? dflag : MO_16;
|
ot = mod == 3 ? dflag : MO_16;
|
||||||
gen_ldst_modrm(env, s, modrm, ot, 1);
|
gen_st_modrm(env, s, modrm, ot);
|
||||||
break;
|
break;
|
||||||
case 3: /* ltr */
|
case 3: /* ltr */
|
||||||
if (!PE(s) || VM86(s))
|
if (!PE(s) || VM86(s))
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
if (check_cpl0(s)) {
|
if (check_cpl0(s)) {
|
||||||
gen_svm_check_intercept(s, SVM_EXIT_TR_WRITE);
|
gen_svm_check_intercept(s, SVM_EXIT_TR_WRITE);
|
||||||
gen_ldst_modrm(env, s, modrm, MO_16, 0);
|
gen_ld_modrm(env, s, modrm, MO_16);
|
||||||
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
|
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
|
||||||
gen_helper_ltr(tcg_env, s->tmp2_i32);
|
gen_helper_ltr(tcg_env, s->tmp2_i32);
|
||||||
}
|
}
|
||||||
@ -3627,7 +3633,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
case 5: /* verw */
|
case 5: /* verw */
|
||||||
if (!PE(s) || VM86(s))
|
if (!PE(s) || VM86(s))
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
gen_ldst_modrm(env, s, modrm, MO_16, 0);
|
gen_ld_modrm(env, s, modrm, MO_16);
|
||||||
gen_update_cc_op(s);
|
gen_update_cc_op(s);
|
||||||
if (op == 4) {
|
if (op == 4) {
|
||||||
gen_helper_verr(tcg_env, s->T0);
|
gen_helper_verr(tcg_env, s->T0);
|
||||||
@ -3891,7 +3897,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
*/
|
*/
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
ot = (mod != 3 ? MO_16 : s->dflag);
|
ot = (mod != 3 ? MO_16 : s->dflag);
|
||||||
gen_ldst_modrm(env, s, modrm, ot, 1);
|
gen_st_modrm(env, s, modrm, ot);
|
||||||
break;
|
break;
|
||||||
case 0xee: /* rdpkru */
|
case 0xee: /* rdpkru */
|
||||||
if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
|
if (s->prefix & (PREFIX_LOCK | PREFIX_DATA
|
||||||
@ -3918,7 +3924,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
|
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
|
||||||
gen_ldst_modrm(env, s, modrm, MO_16, 0);
|
gen_ld_modrm(env, s, modrm, MO_16);
|
||||||
/*
|
/*
|
||||||
* Only the 4 lower bits of CR0 are modified.
|
* Only the 4 lower bits of CR0 are modified.
|
||||||
* PE cannot be set to zero if already set to one.
|
* PE cannot be set to zero if already set to one.
|
||||||
@ -3990,7 +3996,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
ot = dflag != MO_16 ? MO_32 : MO_16;
|
ot = dflag != MO_16 ? MO_32 : MO_16;
|
||||||
modrm = x86_ldub_code(env, s);
|
modrm = x86_ldub_code(env, s);
|
||||||
reg = ((modrm >> 3) & 7) | REX_R(s);
|
reg = ((modrm >> 3) & 7) | REX_R(s);
|
||||||
gen_ldst_modrm(env, s, modrm, MO_16, 0);
|
gen_ld_modrm(env, s, modrm, MO_16);
|
||||||
t0 = tcg_temp_new();
|
t0 = tcg_temp_new();
|
||||||
gen_update_cc_op(s);
|
gen_update_cc_op(s);
|
||||||
if (b == 0x102) {
|
if (b == 0x102) {
|
||||||
@ -4494,7 +4500,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
|||||||
reg = ((modrm >> 3) & 7) | REX_R(s);
|
reg = ((modrm >> 3) & 7) | REX_R(s);
|
||||||
|
|
||||||
ot = dflag;
|
ot = dflag;
|
||||||
gen_ldst_modrm(env, s, modrm, ot, 0);
|
gen_ld_modrm(env, s, modrm, ot);
|
||||||
gen_extu(ot, s->T0);
|
gen_extu(ot, s->T0);
|
||||||
tcg_gen_mov_tl(cpu_cc_src, s->T0);
|
tcg_gen_mov_tl(cpu_cc_src, s->T0);
|
||||||
tcg_gen_ctpop_tl(s->T0, s->T0);
|
tcg_gen_ctpop_tl(s->T0, s->T0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user