PR other/18665
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Dec 2004 12:30:46 +0000 (12:30 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Dec 2004 12:30:46 +0000 (12:30 +0000)
* libgcc-std.ver (GCC_3.4.4): Inherit from GCC_3.4.2.
Export __absvti2, __addvti3, __mulvti3, __negvti2 and __subvti3.
* libgcc2.c (__addvsi3): Rename to __addvSI3.
New version if COMPAT_SIMODE_TRAPPING_ARITHMETIC.
(__addvdi3): Rename to __addvDI3.
(__subvsi3): Rename to __subvSI3.  Use word type for the result.
New version if COMPAT_SIMODE_TRAPPING_ARITHMETIC.
(__subvdi3): Rename to __subvDI3.
(_mulvsi3): Rename to _mulvSI3.
New version if COMPAT_SIMODE_TRAPPING_ARITHMETIC.
(_mulvdi3): Rename to _mulvDI3.
(__negvsi2): Rename to __negvSI2.
New version if COMPAT_SIMODE_TRAPPING_ARITHMETIC.
(__negvdi2): Rename to __negvDI2.
(__absvsi2): Rename to __absvSI2.
New version if COMPAT_SIMODE_TRAPPING_ARITHMETIC.
(__absvdi2): Rename to __absvDI2.
* libgcc2.h (64-bit targets): Define COMPAT_SIMODE_TRAPPING_ARITHMETIC.
(__absvSI2, __addvSI3, __subvSI3, __mulvSI3, __negvSI2, __absvDI2,
__addvDI3, __subvDI3, __mulvDI3, __negvDI2): Define to the appropriate
symbol and declare.
(__absvsi2, __addvsi3, __subvsi3, __mulvsi3, __negvsi2): Declare if
COMPAT_SIMODE_TRAPPING_ARITHMETIC.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@92187 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/libgcc-std.ver
gcc/libgcc2.c
gcc/libgcc2.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ftrapv-2.c [new file with mode: 0644]

index f95c305..db68ea6 100644 (file)
@@ -223,3 +223,13 @@ GCC_3.4.2 {
   __enable_execute_stack
   __trampoline_setup
 }
+
+%inherit GCC_3.4.4 GCC_3.4.2
+GCC_3.4.4 {
+  # libgcc2 TImode arithmetic (for 64-bit targets).
+  __absvti2
+  __addvti3
+  __mulvti3
+  __negvti2
+  __subvti3
+}
index 1f9fe25..1b1455d 100644 (file)
@@ -73,7 +73,7 @@ __negdi2 (DWtype u)
 
 #ifdef L_addvsi3
 Wtype
-__addvsi3 (Wtype a, Wtype b)
+__addvSI3 (Wtype a, Wtype b)
 {
   const Wtype w = a + b;
 
@@ -82,11 +82,23 @@ __addvsi3 (Wtype a, Wtype 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;
 
@@ -99,20 +111,32 @@ __addvdi3 (DWtype a, DWtype 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;
 
@@ -126,7 +150,7 @@ __subvdi3 (DWtype a, DWtype 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;
 
@@ -135,11 +159,25 @@ __mulvsi3 (Wtype a, Wtype 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;
 
@@ -148,11 +186,23 @@ __negvsi2 (Wtype 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;
 
@@ -165,12 +215,30 @@ __negvdi2 (DWtype 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);
 #else
     w = -a;
@@ -181,17 +249,18 @@ __absvsi2 (Wtype 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;
 
@@ -206,7 +275,7 @@ __absvdi2 (DWtype 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.  */
index 87de901..f6b8fa4 100644 (file)
@@ -139,6 +139,16 @@ typedef int word_type __attribute__ ((mode (__word__)));
 #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
@@ -149,6 +159,7 @@ typedef int word_type __attribute__ ((mode (__word__)));
 #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)
@@ -214,6 +225,17 @@ typedef int word_type __attribute__ ((mode (__word__)));
 #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)
@@ -255,16 +277,24 @@ extern UWtype __udiv_w_sdiv (UWtype *, UWtype, UWtype, UWtype);
 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);
index 98a3af8..37a59e2 100644 (file)
@@ -1,3 +1,7 @@
+2004-12-15  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * gcc.dg/ftrapv-2.c: New test.
+
 2004-12-15  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR 18981
diff --git a/gcc/testsuite/gcc.dg/ftrapv-2.c b/gcc/testsuite/gcc.dg/ftrapv-2.c
new file mode 100644 (file)
index 0000000..de66129
--- /dev/null
@@ -0,0 +1,107 @@
+/* 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;
+}