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:
parent
202005f1f8
commit
8760ded661
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue