Message ID | 1293315947-8961-1-git-send-email-aurelien@aurel32.net |
---|---|
State | New |
Headers | show |
Thanks, applied. On Sat, Dec 25, 2010 at 10:25 PM, Aurelien Jarno <aurelien@aurel32.net> wrote: > Since commit 5a4bb580cdb10b066f9fd67658b31cac4a4ea5e5, Xorg crashes on > a Debian Etch image. The commit itself is fine, but it triggers a bug > due to wrong computation of flags for udiv(cc) and sdiv(cc). > > This patch only compute cc_src2 for the cc version of udiv/sdiv. It > also moves the update of cc_dst and cc_op to the helper, as it is > faster doing it here when there is already an helper. > > Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> > --- > target-sparc/helper.h | 2 + > target-sparc/op_helper.c | 54 +++++++++++++++++++++++++++++++++++---------- > target-sparc/translate.c | 12 +++++----- > 3 files changed, 50 insertions(+), 18 deletions(-) > > diff --git a/target-sparc/helper.h b/target-sparc/helper.h > index 6f103e7..e6d82f9 100644 > --- a/target-sparc/helper.h > +++ b/target-sparc/helper.h > @@ -37,7 +37,9 @@ DEF_HELPER_0(save, void) > DEF_HELPER_0(restore, void) > DEF_HELPER_1(flush, void, tl) > DEF_HELPER_2(udiv, tl, tl, tl) > +DEF_HELPER_2(udiv_cc, tl, tl, tl) > DEF_HELPER_2(sdiv, tl, tl, tl) > +DEF_HELPER_2(sdiv_cc, tl, tl, tl) > DEF_HELPER_2(stdf, void, tl, int) > DEF_HELPER_2(lddf, void, tl, int) > DEF_HELPER_2(ldqf, void, tl, int) > diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c > index 4f753ba..58f9f82 100644 > --- a/target-sparc/op_helper.c > +++ b/target-sparc/op_helper.c > @@ -3300,8 +3300,9 @@ void helper_rett(void) > } > #endif > > -target_ulong helper_udiv(target_ulong a, target_ulong b) > +static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc) > { > + int overflow = 0; > uint64_t x0; > uint32_t x1; > > @@ -3314,16 +3315,31 @@ target_ulong helper_udiv(target_ulong a, target_ulong b) > > x0 = x0 / x1; > if (x0 > 0xffffffff) { > - env->cc_src2 = 1; > - return 0xffffffff; > - } else { > - env->cc_src2 = 0; > - return x0; > + x0 = 0xffffffff; > + overflow = 1; > + } > + > + if (cc) { > + env->cc_dst = x0; > + env->cc_src2 = overflow; > + env->cc_op = CC_OP_DIV; > } > + return x0; > } > > -target_ulong helper_sdiv(target_ulong a, target_ulong b) > +target_ulong helper_udiv(target_ulong a, target_ulong b) > +{ > + return helper_udiv_common(a, b, 0); > +} > + > +target_ulong helper_udiv_cc(target_ulong a, target_ulong b) > +{ > + return helper_udiv_common(a, b, 1); > +} > + > +static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc) > { > + int overflow = 0; > int64_t x0; > int32_t x1; > > @@ -3336,12 +3352,26 @@ target_ulong helper_sdiv(target_ulong a, target_ulong b) > > x0 = x0 / x1; > if ((int32_t) x0 != x0) { > - env->cc_src2 = 1; > - return x0 < 0? 0x80000000: 0x7fffffff; > - } else { > - env->cc_src2 = 0; > - return x0; > + x0 = x0 < 0 ? 0x80000000: 0x7fffffff; > + overflow = 1; > + } > + > + if (cc) { > + env->cc_dst = x0; > + env->cc_src2 = overflow; > + env->cc_op = CC_OP_DIV; > } > + return x0; > +} > + > +target_ulong helper_sdiv(target_ulong a, target_ulong b) > +{ > + return helper_sdiv_common(a, b, 0); > +} > + > +target_ulong helper_sdiv_cc(target_ulong a, target_ulong b) > +{ > + return helper_sdiv_common(a, b, 1); > } > > void helper_stdf(target_ulong addr, int mem_idx) > diff --git a/target-sparc/translate.c b/target-sparc/translate.c > index 23f9519..21c5675 100644 > --- a/target-sparc/translate.c > +++ b/target-sparc/translate.c > @@ -3162,20 +3162,20 @@ static void disas_sparc_insn(DisasContext * dc) > #endif > case 0xe: /* udiv */ > CHECK_IU_FEATURE(dc, DIV); > - gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2); > if (xop & 0x10) { > - tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); > - tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV); > + gen_helper_udiv_cc(cpu_dst, cpu_src1, cpu_src2); > dc->cc_op = CC_OP_DIV; > + } else { > + gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2); > } > break; > case 0xf: /* sdiv */ > CHECK_IU_FEATURE(dc, DIV); > - gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2); > if (xop & 0x10) { > - tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); > - tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV); > + gen_helper_sdiv_cc(cpu_dst, cpu_src1, cpu_src2); > dc->cc_op = CC_OP_DIV; > + } else { > + gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2); > } > break; > default: > -- > 1.7.2.3 > >
diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 6f103e7..e6d82f9 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -37,7 +37,9 @@ DEF_HELPER_0(save, void) DEF_HELPER_0(restore, void) DEF_HELPER_1(flush, void, tl) DEF_HELPER_2(udiv, tl, tl, tl) +DEF_HELPER_2(udiv_cc, tl, tl, tl) DEF_HELPER_2(sdiv, tl, tl, tl) +DEF_HELPER_2(sdiv_cc, tl, tl, tl) DEF_HELPER_2(stdf, void, tl, int) DEF_HELPER_2(lddf, void, tl, int) DEF_HELPER_2(ldqf, void, tl, int) diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 4f753ba..58f9f82 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -3300,8 +3300,9 @@ void helper_rett(void) } #endif -target_ulong helper_udiv(target_ulong a, target_ulong b) +static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc) { + int overflow = 0; uint64_t x0; uint32_t x1; @@ -3314,16 +3315,31 @@ target_ulong helper_udiv(target_ulong a, target_ulong b) x0 = x0 / x1; if (x0 > 0xffffffff) { - env->cc_src2 = 1; - return 0xffffffff; - } else { - env->cc_src2 = 0; - return x0; + x0 = 0xffffffff; + overflow = 1; + } + + if (cc) { + env->cc_dst = x0; + env->cc_src2 = overflow; + env->cc_op = CC_OP_DIV; } + return x0; } -target_ulong helper_sdiv(target_ulong a, target_ulong b) +target_ulong helper_udiv(target_ulong a, target_ulong b) +{ + return helper_udiv_common(a, b, 0); +} + +target_ulong helper_udiv_cc(target_ulong a, target_ulong b) +{ + return helper_udiv_common(a, b, 1); +} + +static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc) { + int overflow = 0; int64_t x0; int32_t x1; @@ -3336,12 +3352,26 @@ target_ulong helper_sdiv(target_ulong a, target_ulong b) x0 = x0 / x1; if ((int32_t) x0 != x0) { - env->cc_src2 = 1; - return x0 < 0? 0x80000000: 0x7fffffff; - } else { - env->cc_src2 = 0; - return x0; + x0 = x0 < 0 ? 0x80000000: 0x7fffffff; + overflow = 1; + } + + if (cc) { + env->cc_dst = x0; + env->cc_src2 = overflow; + env->cc_op = CC_OP_DIV; } + return x0; +} + +target_ulong helper_sdiv(target_ulong a, target_ulong b) +{ + return helper_sdiv_common(a, b, 0); +} + +target_ulong helper_sdiv_cc(target_ulong a, target_ulong b) +{ + return helper_sdiv_common(a, b, 1); } void helper_stdf(target_ulong addr, int mem_idx) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 23f9519..21c5675 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3162,20 +3162,20 @@ static void disas_sparc_insn(DisasContext * dc) #endif case 0xe: /* udiv */ CHECK_IU_FEATURE(dc, DIV); - gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { - tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); - tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV); + gen_helper_udiv_cc(cpu_dst, cpu_src1, cpu_src2); dc->cc_op = CC_OP_DIV; + } else { + gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2); } break; case 0xf: /* sdiv */ CHECK_IU_FEATURE(dc, DIV); - gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { - tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); - tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV); + gen_helper_sdiv_cc(cpu_dst, cpu_src1, cpu_src2); dc->cc_op = CC_OP_DIV; + } else { + gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2); } break; default:
Since commit 5a4bb580cdb10b066f9fd67658b31cac4a4ea5e5, Xorg crashes on a Debian Etch image. The commit itself is fine, but it triggers a bug due to wrong computation of flags for udiv(cc) and sdiv(cc). This patch only compute cc_src2 for the cc version of udiv/sdiv. It also moves the update of cc_dst and cc_op to the helper, as it is faster doing it here when there is already an helper. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> --- target-sparc/helper.h | 2 + target-sparc/op_helper.c | 54 +++++++++++++++++++++++++++++++++++---------- target-sparc/translate.c | 12 +++++----- 3 files changed, 50 insertions(+), 18 deletions(-)