target/i386: Create gen_jmp_rel

Create a common helper for pc-relative branches.  The jmp jb insn
was missing a mask for CODE32.  In all cases the CODE64 check was
incorrectly placed, allowing PREFIX_DATA to truncate %rip to 16 bits.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221001140935.465607-18-richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Richard Henderson 2022-10-01 07:09:26 -07:00 committed by Paolo Bonzini
parent 202005f1f8
commit 8760ded661
1 changed files with 29 additions and 29 deletions

View File

@ -226,6 +226,7 @@ static void gen_eob(DisasContext *s);
static void gen_jr(DisasContext *s);
static void gen_jmp(DisasContext *s, target_ulong eip);
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num);
static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
static void gen_exception_gpf(DisasContext *s);
@ -2792,6 +2793,21 @@ static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
}
}
static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num)
{
target_ulong dest = s->pc - s->cs_base + diff;
/* In 64-bit mode, operand size is fixed at 64 bits. */
if (!CODE64(s)) {
if (ot == MO_16) {
dest &= 0xffff;
} else {
dest &= 0xffffffff;
}
}
gen_jmp_tb(s, dest, tb_num);
}
static void gen_jmp(DisasContext *s, target_ulong eip)
{
gen_jmp_tb(s, eip, 0);
@ -6862,20 +6878,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
case 0xe8: /* call im */
{
if (dflag != MO_16) {
tval = (int32_t)insn_get(env, s, MO_32);
} else {
tval = (int16_t)insn_get(env, s, MO_16);
}
tval += s->pc - s->cs_base;
if (dflag == MO_16) {
tval &= 0xffff;
} else if (!CODE64(s)) {
tval &= 0xffffffff;
}
int diff = (dflag != MO_16
? (int32_t)insn_get(env, s, MO_32)
: (int16_t)insn_get(env, s, MO_16));
gen_push_v(s, eip_next_tl(s));
gen_bnd_jmp(s);
gen_jmp(s, tval);
gen_jmp_rel(s, dflag, diff, 0);
}
break;
case 0x9a: /* lcall im */
@ -6893,19 +6901,13 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
goto do_lcall;
case 0xe9: /* jmp im */
if (dflag != MO_16) {
tval = (int32_t)insn_get(env, s, MO_32);
} else {
tval = (int16_t)insn_get(env, s, MO_16);
{
int diff = (dflag != MO_16
? (int32_t)insn_get(env, s, MO_32)
: (int16_t)insn_get(env, s, MO_16));
gen_bnd_jmp(s);
gen_jmp_rel(s, dflag, diff, 0);
}
tval += s->pc - s->cs_base;
if (dflag == MO_16) {
tval &= 0xffff;
} else if (!CODE64(s)) {
tval &= 0xffffffff;
}
gen_bnd_jmp(s);
gen_jmp(s, tval);
break;
case 0xea: /* ljmp im */
{
@ -6922,12 +6924,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
goto do_ljmp;
case 0xeb: /* jmp Jb */
tval = (int8_t)insn_get(env, s, MO_8);
tval += s->pc - s->cs_base;
if (dflag == MO_16) {
tval &= 0xffff;
{
int diff = (int8_t)insn_get(env, s, MO_8);
gen_jmp_rel(s, dflag, diff, 0);
}
gen_jmp(s, tval);
break;
case 0x70 ... 0x7f: /* jcc Jb */
tval = (int8_t)insn_get(env, s, MO_8);