This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: __fixuns?fSI() lose if long is wider than SI
On Jan 31, 2001, Richard Henderson <rth@redhat.com> wrote:
> Ok. I certainly don't think that's the last such bug
> in that file, but this is at least two less.
Believe me, I had looked for other occurrences of 30, 31, 62 and 63,
but, stupidly, not 32 nor 64 :-(
Here's a patch that fixes all other 32-bit assumptions I could find.
I've already verified it compiles, but testing on
i686-pc-linux-gnu-x-sh-elf was just started. Ok to install (assuming
it passes)?
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* config/fp-bit.h (MAX_USI_INT, MAX_SI_INT): Don't assume
unsigned is wide enough.
(BITS_PER_SI): New.
* config/fp-bit.c (_fpmul_parts): Don't assume 32-bits SI.
(si_to_float): Likewise.
(float_to_si, float_to_usi): Use BITS_PER_SI.
Index: gcc/config/fp-bit.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/fp-bit.h,v
retrieving revision 1.3
diff -u -p -r1.3 fp-bit.h
--- gcc/config/fp-bit.h 2000/12/22 12:27:36 1.3
+++ gcc/config/fp-bit.h 2001/01/31 12:13:50
@@ -103,9 +103,9 @@ typedef unsigned int UHItype __attribute
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
-#define MAX_SI_INT ((SItype) ((unsigned) (~0)>>1))
-#define MAX_USI_INT ((USItype) ~0)
-
+#define MAX_USI_INT (~(USItype)0)
+#define MAX_SI_INT ((SItype) (MAX_USI_INT >> 1))
+#define BITS_PER_SI (4 * BITS_PER_UNIT)
#ifdef FLOAT_ONLY
#define NO_DI_MODE
Index: gcc/config/fp-bit.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/fp-bit.c,v
retrieving revision 1.23
diff -u -p -r1.23 fp-bit.c
--- gcc/config/fp-bit.c 2001/01/31 11:04:33 1.23
+++ gcc/config/fp-bit.c 2001/01/31 12:13:50
@@ -624,8 +624,8 @@ _fpmul_parts ( fp_number_type * a,
return b;
}
- /* Calculate the mantissa by multiplying both 64bit numbers to get a
- 128 bit number */
+ /* Calculate the mantissa by multiplying both numbers to get a
+ twice-as-wide number. */
{
#if defined(NO_DI_MODE)
{
@@ -654,22 +654,22 @@ _fpmul_parts ( fp_number_type * a,
}
}
#elif defined(FLOAT)
+ /* Multiplying two USIs to get a UDI, we're safe. */
{
- /* Multiplying two 32 bit numbers to get a 64 bit number on
- a machine with DI, so we're safe */
-
- DItype answer = (DItype)(a->fraction.ll) * (DItype)(b->fraction.ll);
+ UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
- high = answer >> 32;
+ high = answer >> BITS_PER_SI;
low = answer;
}
#else
- /* Doing a 64*64 to 128 */
- {
- USItype nl = a->fraction.ll & 0xffffffff;
- USItype nh = a->fraction.ll >> 32;
- USItype ml = b->fraction.ll & 0xffffffff;
- USItype mh = b->fraction.ll >>32;
+ /* fractype is DImode, but we need the result to be twice as wide.
+ Assuming a widening multiply from DImode to TImode, is not
+ available, build one by hand. */
+ {
+ USItype nl = a->fraction.ll;
+ USItype nh = a->fraction.ll >> BITS_PER_SI;
+ USItype ml = b->fraction.ll;
+ USItype mh = b->fraction.ll >> BITS_PER_SI;
UDItype pp_ll = (UDItype) ml * nl;
UDItype pp_hl = (UDItype) mh * nl;
UDItype pp_lh = (UDItype) ml * nh;
@@ -678,12 +678,12 @@ _fpmul_parts ( fp_number_type * a,
UDItype res0 = 0;
UDItype ps_hh__ = pp_hl + pp_lh;
if (ps_hh__ < pp_hl)
- res2 += 0x100000000LL;
- pp_hl = (ps_hh__ << 32) & 0xffffffff00000000LL;
+ res2 += (UDItype)1 << BITS_PER_SI;
+ pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
res0 = pp_ll + pp_hl;
if (res0 < pp_ll)
res2++;
- res2 += ((ps_hh__ >> 32) & 0xffffffffL) + pp_hh;
+ res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
high = res2;
low = res0;
}
@@ -1151,9 +1151,9 @@ si_to_float (SItype arg_a)
{
/* Special case for minint, since there is no +ve integer
representation for it */
- if (arg_a == (SItype) 0x80000000)
+ if (arg_a == (- MAX_SI_INT - 1))
{
- return -2147483648.0;
+ return (FLO_type)(- MAX_SI_INT - 1);
}
in.fraction.ll = (-arg_a);
}
@@ -1223,7 +1223,7 @@ float_to_si (FLO_type arg_a)
/* it is a number, but a small one */
if (a.normal_exp < 0)
return 0;
- if (a.normal_exp > 4 * BITS_PER_UNIT - 2)
+ if (a.normal_exp > BITS_PER_SI - 2)
return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
return a.sign ? (-tmp) : (tmp);
@@ -1260,7 +1260,7 @@ float_to_usi (FLO_type arg_a)
/* it is a number, but a small one */
if (a.normal_exp < 0)
return 0;
- if (a.normal_exp > 4 * BITS_PER_UNIT - 1)
+ if (a.normal_exp > BITS_PER_SI - 1)
return MAX_USI_INT;
else if (a.normal_exp > (FRACBITS + NGARDS))
return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me