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>
(cherry picked from commit ac63755b20)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(Mjt: modify the change to pre-new-decoder introduced past qemu 9.0)
This commit is contained in:
Richard Henderson 2024-08-05 10:31:24 +10:00 committed by Michael Tokarev
parent ce15d843f1
commit 73b491b792
2 changed files with 13 additions and 12 deletions

View File

@ -1135,7 +1135,8 @@ static int decode_modrm(DisasContext *s, CPUX86State *env, X86DecodedInsn *decod
} else {
op->has_ea = true;
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;
}

View File

@ -2187,7 +2187,7 @@ typedef struct AddressParts {
} AddressParts;
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;
target_long disp;
@ -2216,7 +2216,7 @@ static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
int code = x86_ldub_code(env, s);
scale = (code >> 6) & 3;
index = ((code >> 3) & 7) | REX_X(s);
if (index == 4) {
if (index == 4 && !is_vsib) {
index = -1; /* no index */
}
base = (code & 7) | REX_B(s);
@ -2346,21 +2346,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)
{
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);
gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
}
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. */
static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
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);
tcg_gen_extu_tl_i64(s->tmp1_i64, ea);
@ -4179,7 +4179,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
reg = ((modrm >> 3) & 7) | REX_R(s);
{
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);
gen_lea_v_seg(s, s->aflag, ea, -1, -1);
gen_op_mov_reg_v(s, dflag, reg, s->A0);
@ -4400,7 +4400,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
op = ((b & 7) << 3) | ((modrm >> 3) & 7);
if (mod != 3) {
/* 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 last_addr = tcg_temp_new();
bool update_fdp = true;
@ -5348,7 +5348,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
rm = (modrm & 7) | REX_B(s);
gen_op_mov_v_reg(s, MO_32, s->T1, reg);
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 */
gen_exts(ot, s->T1);
tcg_gen_sari_tl(s->tmp0, s->T1, 3 + ot);
@ -6343,7 +6343,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
} else if (mod != 3) {
/* bndldx */
AddressParts a = gen_lea_modrm_0(env, s, modrm);
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
if (reg >= 4
|| (prefixes & PREFIX_LOCK)
|| s->aflag == MO_16
@ -6387,7 +6387,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|| s->aflag == MO_16) {
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) {
tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
if (!CODE64(s)) {
@ -6448,7 +6448,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
} else if (mod != 3) {
/* bndstx */
AddressParts a = gen_lea_modrm_0(env, s, modrm);
AddressParts a = gen_lea_modrm_0(env, s, modrm, false);
if (reg >= 4
|| (prefixes & PREFIX_LOCK)
|| s->aflag == MO_16