#ifdef L_addvsi3
Wtype
-__addvsi3 (Wtype a, Wtype b)
+__addvSI3 (Wtype a, Wtype b)
{
const Wtype w = a + b;
return w;
}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__addvsi3 (SItype a, SItype b)
+{
+ const SItype w = a + b;
+
+ if (b >= 0 ? w < a : w > a)
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_addvdi3
DWtype
-__addvdi3 (DWtype a, DWtype b)
+__addvDI3 (DWtype a, DWtype b)
{
const DWtype w = a + b;
\f
#ifdef L_subvsi3
Wtype
-__subvsi3 (Wtype a, Wtype b)
+__subvSI3 (Wtype a, Wtype b)
{
- const DWtype w = a - b;
+ const Wtype w = a - b;
if (b >= 0 ? w > a : w < a)
abort ();
return w;
}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__subvsi3 (SItype a, SItype b)
+{
+ const SItype w = a - b;
+
+ if (b >= 0 ? w > a : w < a)
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_subvdi3
DWtype
-__subvdi3 (DWtype a, DWtype b)
+__subvDI3 (DWtype a, DWtype b)
{
const DWtype w = a - b;
#ifdef L_mulvsi3
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
Wtype
-__mulvsi3 (Wtype a, Wtype b)
+__mulvSI3 (Wtype a, Wtype b)
{
const DWtype w = (DWtype) a * (DWtype) b;
return w;
}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+#undef WORD_SIZE
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+SItype
+__mulvsi3 (SItype a, SItype b)
+{
+ const DItype w = (DItype) a * (DItype) b;
+
+ if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1))
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_negvsi2
Wtype
-__negvsi2 (Wtype a)
+__negvSI2 (Wtype a)
{
const Wtype w = -a;
return w;
}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__negvsi2 (SItype a)
+{
+ const SItype w = -a;
+
+ if (a >= 0 ? w > 0 : w < 0)
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_negvdi2
DWtype
-__negvdi2 (DWtype a)
+__negvDI2 (DWtype a)
{
const DWtype w = -a;
\f
#ifdef L_absvsi2
Wtype
-__absvsi2 (Wtype a)
+__absvSI2 (Wtype a)
{
Wtype w = a;
+ if (a < 0)
+#ifdef L_negvsi2
+ w = __negvSI2 (a);
+#else
+ w = -a;
+
+ if (w < 0)
+ abort ();
+#endif
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__absvsi2 (SItype a)
+{
+ SItype w = a;
+
if (a < 0)
#ifdef L_negvsi2
w = __negvsi2 (a);
return w;
}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_absvdi2
DWtype
-__absvdi2 (DWtype a)
+__absvDI2 (DWtype a)
{
DWtype w = a;
if (a < 0)
#ifdef L_negvdi2
- w = __negvdi2 (a);
+ w = __negvDI2 (a);
#else
w = -a;
#ifdef L_mulvdi3
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
DWtype
-__mulvdi3 (DWtype u, DWtype v)
+__mulvDI3 (DWtype u, DWtype v)
{
/* The unchecked multiplication needs 3 Wtype x Wtype multiplications,
but the checked multiplication needs only two. */
#define float bogus_type
#define double bogus_type
+/* Versions prior to 3.4.4 were not taking into account the word size for
+ the 5 trapping arithmetic functions absv, addv, subv, mulv and negv. As
+ a consequence, the si and di variants were always and the only ones emitted.
+ To maintain backward compatibility, COMPAT_SIMODE_TRAPPING_ARITHMETIC is
+ defined on platforms where it makes sense to still have the si variants
+ emitted. As a bonus, their implementation is now correct. Note that the
+ same mechanism should have been implemented for the di variants, but it
+ turns out that no platform would define COMPAT_DIMODE_TRAPPING_ARITHMETIC
+ if it existed. */
+
#if MIN_UNITS_PER_WORD > 4
#define W_TYPE_SIZE (8 * BITS_PER_UNIT)
#define Wtype DItype
#define UDWtype UTItype
#define __NW(a,b) __ ## a ## di ## b
#define __NDW(a,b) __ ## a ## ti ## b
+#define COMPAT_SIMODE_TRAPPING_ARITHMETIC
#elif MIN_UNITS_PER_WORD > 2 \
|| (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32)
#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
#define __fixunsdfSI __NW(fixunsdf,)
#define __fixunssfSI __NW(fixunssf,)
+#define __absvSI2 __NW(absv,2)
+#define __addvSI3 __NW(addv,3)
+#define __subvSI3 __NW(subv,3)
+#define __mulvSI3 __NW(mulv,3)
+#define __negvSI2 __NW(negv,2)
+#define __absvDI2 __NDW(absv,2)
+#define __addvDI3 __NDW(addv,3)
+#define __subvDI3 __NDW(subv,3)
+#define __mulvDI3 __NDW(mulv,3)
+#define __negvDI2 __NDW(negv,2)
+
#define __ffsSI2 __NW(ffs,2)
#define __clzSI2 __NW(clz,2)
#define __ctzSI2 __NW(ctz,2)
extern word_type __cmpdi2 (DWtype, DWtype);
extern word_type __ucmpdi2 (DWtype, DWtype);
-extern Wtype __absvsi2 (Wtype);
-extern DWtype __absvdi2 (DWtype);
-extern Wtype __addvsi3 (Wtype, Wtype);
-extern DWtype __addvdi3 (DWtype, DWtype);
-extern Wtype __subvsi3 (Wtype, Wtype);
-extern DWtype __subvdi3 (DWtype, DWtype);
-extern Wtype __mulvsi3 (Wtype, Wtype);
-extern DWtype __mulvdi3 (DWtype, DWtype);
-extern Wtype __negvsi2 (Wtype);
-extern DWtype __negvdi2 (DWtype);
+extern Wtype __absvSI2 (Wtype);
+extern Wtype __addvSI3 (Wtype, Wtype);
+extern Wtype __subvSI3 (Wtype, Wtype);
+extern Wtype __mulvSI3 (Wtype, Wtype);
+extern Wtype __negvSI2 (Wtype);
+extern DWtype __absvDI2 (DWtype);
+extern DWtype __addvDI3 (DWtype, DWtype);
+extern DWtype __subvDI3 (DWtype, DWtype);
+extern DWtype __mulvDI3 (DWtype, DWtype);
+extern DWtype __negvDI2 (DWtype);
+
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+extern SItype __absvsi2 (SItype);
+extern SItype __addvsi3 (SItype, SItype);
+extern SItype __subvsi3 (SItype, SItype);
+extern SItype __mulvsi3 (SItype, SItype);
+extern SItype __negvsi2 (SItype);
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#if BITS_PER_UNIT == 8
extern DWtype __fixdfdi (DFtype);
--- /dev/null
+/* Copyright (C) 2004 Free Software Foundation.
+
+ PR other/18665
+ Verify that -ftrapv doesn't produce bogus results
+ on 64-bit platforms.
+
+ Written by Eric Botcazou */
+
+/* { dg-do run } */
+/* { dg-options "-ftrapv" } */
+
+extern void abort(void);
+
+int __attribute__((noinline))
+iabsv(int a)
+{
+ return abs(a);
+}
+
+int __attribute__((noinline))
+iaddv(int a, int b)
+{
+ return a + b;
+}
+
+int __attribute__((noinline))
+isubv(int a, int b)
+{
+ return a - b;
+}
+
+int __attribute__((noinline))
+imulv(int a, int b)
+{
+ return a * b;
+}
+
+int __attribute__((noinline))
+inegv(int a)
+{
+ return -a;
+}
+
+long __attribute__((noinline))
+labsv(long a)
+{
+ return abs(a);
+}
+
+long __attribute__((noinline))
+laddv(long a, long b)
+{
+ return a + b;
+}
+
+long __attribute__((noinline))
+lsubv(long a, long b)
+{
+ return a - b;
+}
+
+long __attribute__((noinline))
+lmulv(long a, long b)
+{
+ return a * b;
+}
+
+long __attribute__((noinline))
+lnegv(long a)
+{
+ return -a;
+}
+
+int main(void)
+{
+ if (iabsv (-1) != 1)
+ abort ();
+
+ if (iaddv (2,-3) != -1)
+ abort ();
+
+ if (isubv (2,3) != -1)
+ abort ();
+
+ if (imulv (-2,3) != -6)
+ abort ();
+
+ if (inegv (-1) != 1)
+ abort ();
+
+ if (labsv (-1L) != 1L)
+ abort ();
+
+ if (laddv (2L,-3L) != -1L)
+ abort ();
+
+ if (lsubv (2L,3L) != -1L)
+ abort ();
+
+ if (lmulv (-2L,3L) != -6L)
+ abort ();
+
+ if (lnegv (-1L) != 1L)
+ abort ();
+
+ return 0;
+}