re PR other/18665 (-ftrapv borks up simple integer arithmetic)

PR other/18665
	* 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.

From-SVN: r92187
This commit is contained in:
Eric Botcazou 2004-12-15 13:30:46 +01:00 committed by Eric Botcazou
parent c331bf0802
commit 0aec601466
5 changed files with 242 additions and 22 deletions

View 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
}

View 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
#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)
#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
#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
#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
#ifdef L_negvdi2
DWtype
__negvdi2 (DWtype a)
__negvDI2 (DWtype a)
{
const DWtype w = -a;
@ -165,10 +215,28 @@ __negvdi2 (DWtype a)
#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);
@ -181,17 +249,18 @@ __absvsi2 (Wtype a)
return w;
}
#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
#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. */

View 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);

View 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

View File

@ -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;
}