mirror of https://github.com/xemu-project/xemu.git
target/i386: Fix VSIB decode
With normal SIB, index == 4 indicates no index. With VSIB, there is no exception for VR4/VR12. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2474 Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Link: https://lore.kernel.org/r/20240805003130.1421051-3-richard.henderson@linaro.org Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
d4392415c3
commit
ac63755b20
target/i386/tcg
|
@ -1811,7 +1811,8 @@ static int decode_modrm(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
|
||||||
} else {
|
} else {
|
||||||
op->has_ea = true;
|
op->has_ea = true;
|
||||||
op->n = -1;
|
op->n = -1;
|
||||||
decode->mem = gen_lea_modrm_0(env, s, get_modrm(s, env));
|
decode->mem = gen_lea_modrm_0(env, s, modrm,
|
||||||
|
decode->e.vex_class == 12);
|
||||||
}
|
}
|
||||||
return modrm;
|
return modrm;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1523,7 +1523,7 @@ typedef struct AddressParts {
|
||||||
} AddressParts;
|
} AddressParts;
|
||||||
|
|
||||||
static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
|
static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
|
||||||
int modrm)
|
int modrm, bool is_vsib)
|
||||||
{
|
{
|
||||||
int def_seg, base, index, scale, mod, rm;
|
int def_seg, base, index, scale, mod, rm;
|
||||||
target_long disp;
|
target_long disp;
|
||||||
|
@ -1552,7 +1552,7 @@ static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
|
||||||
int code = x86_ldub_code(env, s);
|
int code = x86_ldub_code(env, s);
|
||||||
scale = (code >> 6) & 3;
|
scale = (code >> 6) & 3;
|
||||||
index = ((code >> 3) & 7) | REX_X(s);
|
index = ((code >> 3) & 7) | REX_X(s);
|
||||||
if (index == 4) {
|
if (index == 4 && !is_vsib) {
|
||||||
index = -1; /* no index */
|
index = -1; /* no index */
|
||||||
}
|
}
|
||||||
base = (code & 7) | REX_B(s);
|
base = (code & 7) | REX_B(s);
|
||||||
|
@ -1682,21 +1682,21 @@ static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a, bool is_vsib)
|
||||||
|
|
||||||
static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
|
static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
|
||||||
{
|
{
|
||||||
AddressParts a = gen_lea_modrm_0(env, s, modrm);
|
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
|
||||||
TCGv ea = gen_lea_modrm_1(s, a, false);
|
TCGv ea = gen_lea_modrm_1(s, a, false);
|
||||||
gen_lea_v_seg(s, ea, a.def_seg, s->override);
|
gen_lea_v_seg(s, ea, a.def_seg, s->override);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
|
static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
|
||||||
{
|
{
|
||||||
(void)gen_lea_modrm_0(env, s, modrm);
|
(void)gen_lea_modrm_0(env, s, modrm, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used for BNDCL, BNDCU, BNDCN. */
|
/* Used for BNDCL, BNDCU, BNDCN. */
|
||||||
static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
|
static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
|
||||||
TCGCond cond, TCGv_i64 bndv)
|
TCGCond cond, TCGv_i64 bndv)
|
||||||
{
|
{
|
||||||
AddressParts a = gen_lea_modrm_0(env, s, modrm);
|
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
|
||||||
TCGv ea = gen_lea_modrm_1(s, a, false);
|
TCGv ea = gen_lea_modrm_1(s, a, false);
|
||||||
|
|
||||||
tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
|
tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
|
||||||
|
@ -2417,7 +2417,7 @@ static bool disas_insn_x87(DisasContext *s, CPUState *cpu, int b)
|
||||||
op = ((b & 7) << 3) | ((modrm >> 3) & 7);
|
op = ((b & 7) << 3) | ((modrm >> 3) & 7);
|
||||||
if (mod != 3) {
|
if (mod != 3) {
|
||||||
/* memory op */
|
/* memory op */
|
||||||
AddressParts a = gen_lea_modrm_0(env, s, modrm);
|
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
|
||||||
TCGv ea = gen_lea_modrm_1(s, a, false);
|
TCGv ea = gen_lea_modrm_1(s, a, false);
|
||||||
TCGv last_addr = tcg_temp_new();
|
TCGv last_addr = tcg_temp_new();
|
||||||
bool update_fdp = true;
|
bool update_fdp = true;
|
||||||
|
@ -3078,7 +3078,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
||||||
rm = (modrm & 7) | REX_B(s);
|
rm = (modrm & 7) | REX_B(s);
|
||||||
gen_op_mov_v_reg(s, MO_32, s->T1, reg);
|
gen_op_mov_v_reg(s, MO_32, s->T1, reg);
|
||||||
if (mod != 3) {
|
if (mod != 3) {
|
||||||
AddressParts a = gen_lea_modrm_0(env, s, modrm);
|
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
|
||||||
/* specific case: we need to add a displacement */
|
/* specific case: we need to add a displacement */
|
||||||
gen_exts(ot, s->T1);
|
gen_exts(ot, s->T1);
|
||||||
tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
|
tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
|
||||||
|
@ -3635,7 +3635,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
||||||
}
|
}
|
||||||
} else if (mod != 3) {
|
} else if (mod != 3) {
|
||||||
/* bndldx */
|
/* bndldx */
|
||||||
AddressParts a = gen_lea_modrm_0(env, s, modrm);
|
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
|
||||||
if (reg >= 4
|
if (reg >= 4
|
||||||
|| (prefixes & PREFIX_LOCK)
|
|| (prefixes & PREFIX_LOCK)
|
||||||
|| s->aflag == MO_16
|
|| s->aflag == MO_16
|
||||||
|
@ -3679,7 +3679,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
||||||
|| s->aflag == MO_16) {
|
|| s->aflag == MO_16) {
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
AddressParts a = gen_lea_modrm_0(env, s, modrm);
|
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
|
||||||
if (a.base >= 0) {
|
if (a.base >= 0) {
|
||||||
tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
|
tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
|
||||||
if (!CODE64(s)) {
|
if (!CODE64(s)) {
|
||||||
|
@ -3740,7 +3740,7 @@ static void disas_insn_old(DisasContext *s, CPUState *cpu, int b)
|
||||||
}
|
}
|
||||||
} else if (mod != 3) {
|
} else if (mod != 3) {
|
||||||
/* bndstx */
|
/* bndstx */
|
||||||
AddressParts a = gen_lea_modrm_0(env, s, modrm);
|
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
|
||||||
if (reg >= 4
|
if (reg >= 4
|
||||||
|| (prefixes & PREFIX_LOCK)
|
|| (prefixes & PREFIX_LOCK)
|
||||||
|| s->aflag == MO_16
|
|| s->aflag == MO_16
|
||||||
|
|
Loading…
Reference in New Issue