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
|
(OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
|
||||||
indicate no override. */
|
indicate no override. */
|
||||||
static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
|
static void gen_lea_v_seg_dest(DisasContext *s, MemOp aflag, TCGv dest, TCGv a0,
|
||||||
int def_seg, int ovr_seg)
|
int def_seg, int ovr_seg)
|
||||||
{
|
{
|
||||||
switch (aflag) {
|
switch (aflag) {
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
case MO_64:
|
case MO_64:
|
||||||
if (ovr_seg < 0) {
|
if (ovr_seg < 0) {
|
||||||
tcg_gen_mov_tl(s->A0, a0);
|
tcg_gen_mov_tl(dest, a0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -656,14 +656,14 @@ static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
|
|||||||
ovr_seg = def_seg;
|
ovr_seg = def_seg;
|
||||||
}
|
}
|
||||||
if (ovr_seg < 0) {
|
if (ovr_seg < 0) {
|
||||||
tcg_gen_ext32u_tl(s->A0, a0);
|
tcg_gen_ext32u_tl(dest, a0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MO_16:
|
case MO_16:
|
||||||
/* 16 bit address */
|
/* 16 bit address */
|
||||||
tcg_gen_ext16u_tl(s->A0, a0);
|
tcg_gen_ext16u_tl(dest, a0);
|
||||||
a0 = s->A0;
|
a0 = dest;
|
||||||
if (ovr_seg < 0) {
|
if (ovr_seg < 0) {
|
||||||
if (ADDSEG(s)) {
|
if (ADDSEG(s)) {
|
||||||
ovr_seg = def_seg;
|
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];
|
TCGv seg = cpu_seg_base[ovr_seg];
|
||||||
|
|
||||||
if (aflag == MO_64) {
|
if (aflag == MO_64) {
|
||||||
tcg_gen_add_tl(s->A0, a0, seg);
|
tcg_gen_add_tl(dest, a0, seg);
|
||||||
} else if (CODE64(s)) {
|
} else if (CODE64(s)) {
|
||||||
tcg_gen_ext32u_tl(s->A0, a0);
|
tcg_gen_ext32u_tl(dest, a0);
|
||||||
tcg_gen_add_tl(s->A0, s->A0, seg);
|
tcg_gen_add_tl(dest, dest, seg);
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_add_tl(s->A0, a0, seg);
|
tcg_gen_add_tl(dest, a0, seg);
|
||||||
tcg_gen_ext32u_tl(s->A0, s->A0);
|
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)
|
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);
|
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);
|
MemOp d_ot = mo_pushpop(s, s->dflag);
|
||||||
|
|
||||||
gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
|
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->A0);
|
gen_op_ld_v(s, d_ot, s->T0, s->T0);
|
||||||
|
|
||||||
return d_ot;
|
return d_ot;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user