mirror of https://github.com/xemu-project/xemu.git
target/i386: do not clobber A0 in POP translation
The new decoder likes to compute the address in A0 very early, so the gen_lea_v_seg in gen_pop_T0 would clobber the address of the memory operand. Instead use T0 since it is already available and will be overwritten immediately after. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
a71e0b246a
commit
24c0573bb0
|
@ -635,17 +635,17 @@ static TCGv eip_cur_tl(DisasContext *s)
|
|||
}
|
||||
}
|
||||
|
||||
/* Compute SEG:REG into A0. SEG is selected from the override segment
|
||||
/* Compute SEG:REG into DEST. SEG is selected from the override segment
|
||||
(OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
|
||||
indicate no override. */
|
||||
static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
|
||||
int def_seg, int ovr_seg)
|
||||
static void gen_lea_v_seg_dest(DisasContext *s, MemOp aflag, TCGv dest, TCGv a0,
|
||||
int def_seg, int ovr_seg)
|
||||
{
|
||||
switch (aflag) {
|
||||
#ifdef TARGET_X86_64
|
||||
case MO_64:
|
||||
if (ovr_seg < 0) {
|
||||
tcg_gen_mov_tl(s->A0, a0);
|
||||
tcg_gen_mov_tl(dest, a0);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -656,14 +656,14 @@ static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
|
|||
ovr_seg = def_seg;
|
||||
}
|
||||
if (ovr_seg < 0) {
|
||||
tcg_gen_ext32u_tl(s->A0, a0);
|
||||
tcg_gen_ext32u_tl(dest, a0);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MO_16:
|
||||
/* 16 bit address */
|
||||
tcg_gen_ext16u_tl(s->A0, a0);
|
||||
a0 = s->A0;
|
||||
tcg_gen_ext16u_tl(dest, a0);
|
||||
a0 = dest;
|
||||
if (ovr_seg < 0) {
|
||||
if (ADDSEG(s)) {
|
||||
ovr_seg = def_seg;
|
||||
|
@ -680,17 +680,23 @@ static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
|
|||
TCGv seg = cpu_seg_base[ovr_seg];
|
||||
|
||||
if (aflag == MO_64) {
|
||||
tcg_gen_add_tl(s->A0, a0, seg);
|
||||
tcg_gen_add_tl(dest, a0, seg);
|
||||
} else if (CODE64(s)) {
|
||||
tcg_gen_ext32u_tl(s->A0, a0);
|
||||
tcg_gen_add_tl(s->A0, s->A0, seg);
|
||||
tcg_gen_ext32u_tl(dest, a0);
|
||||
tcg_gen_add_tl(dest, dest, seg);
|
||||
} else {
|
||||
tcg_gen_add_tl(s->A0, a0, seg);
|
||||
tcg_gen_ext32u_tl(s->A0, s->A0);
|
||||
tcg_gen_add_tl(dest, a0, seg);
|
||||
tcg_gen_ext32u_tl(dest, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
|
||||
int def_seg, int ovr_seg)
|
||||
{
|
||||
gen_lea_v_seg_dest(s, aflag, s->A0, a0, def_seg, ovr_seg);
|
||||
}
|
||||
|
||||
static inline void gen_string_movl_A0_ESI(DisasContext *s)
|
||||
{
|
||||
gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
|
||||
|
@ -2576,8 +2582,8 @@ static MemOp gen_pop_T0(DisasContext *s)
|
|||
{
|
||||
MemOp d_ot = mo_pushpop(s, s->dflag);
|
||||
|
||||
gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
|
||||
gen_op_ld_v(s, d_ot, s->T0, s->A0);
|
||||
gen_lea_v_seg_dest(s, mo_stacksize(s), s->T0, cpu_regs[R_ESP], R_SS, -1);
|
||||
gen_op_ld_v(s, d_ot, s->T0, s->T0);
|
||||
|
||||
return d_ot;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue