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:
parent
0c6a8ad358
commit
3854679d58
@ -1102,7 +1102,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;
|
||||
}
|
||||
|
@ -2159,7 +2159,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;
|
||||
@ -2188,7 +2188,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);
|
||||
@ -2318,21 +2318,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);
|
||||
@ -4156,7 +4156,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);
|
||||
@ -4378,7 +4378,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;
|
||||
@ -5322,7 +5322,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);
|
||||
@ -6318,7 +6318,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
|
||||
@ -6362,7 +6362,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)) {
|
||||
@ -6423,7 +6423,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
|
||||
|
Loading…
Reference in New Issue
Block a user