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:
Richard Henderson 2024-08-05 10:31:24 +10:00 committed by Paolo Bonzini
parent d4392415c3
commit ac63755b20
2 changed files with 12 additions and 11 deletions

View File

@ -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;
} }

View File

@ -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