decExcept.c: New.

libdecnumber/
	* decExcept.c: New.
	* decExcept.h: New.
libgcc/
	* Makefile.in (dec-filenames): Add decExcept.
gcc/
	* config/dfp-bit.c: Add parameterized support for fp exceptions.
	* config/dfp-bit.h: Ditto.
gcc/testsuite/
	* gcc.dg/dfp/dfp-except.h: New file.
	* gcc.dg/dfp/fe-check.h: New file.
	* gcc.dg/dfp/fe-binop.c: New test.
	* gcc.dg/dfp/fe-convert-1.c: New test.
	* gcc.dg/dfp/fe-convert-2.c: New test.
	* gcc.dg/dfp/fe-convert-3.c: New test.

From-SVN: r121317
This commit is contained in:
Janis Johnson 2007-01-29 23:01:35 +00:00 committed by Janis Johnson
parent 5b18f33782
commit d9a66f98c1
15 changed files with 523 additions and 1 deletions

View File

@ -1,3 +1,8 @@
2007-01-29 Janis Johnson <janis187@us.ibm.com>
* config/dfp-bit.c: Add parameterized support for fp exceptions.
* config/dfp-bit.h: Ditto.
007-01-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
* c-decl.c (pop_scope): Replace warnings with call to

View File

@ -88,6 +88,19 @@ dfp_unary_op (dfp_unary_func op, DFP_C_TYPE arg)
/* Perform the operation. */
op (&res, &arg1, &context);
if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
{
/* decNumber exception flags we care about here. */
int ieee_flags;
int dec_flags = DEC_IEEE_854_Division_by_zero | DEC_IEEE_854_Inexact
| DEC_IEEE_854_Invalid_operation | DEC_IEEE_854_Overflow
| DEC_IEEE_854_Underflow;
dec_flags &= context.status;
ieee_flags = DFP_IEEE_FLAGS (dec_flags);
if (ieee_flags != 0)
DFP_HANDLE_EXCEPTIONS (ieee_flags);
}
TO_ENCODED (&encoded_result, &res, &context);
IEEE_TO_HOST (encoded_result, &result);
return result;
@ -115,6 +128,19 @@ dfp_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
/* Perform the operation. */
op (&res, &arg1, &arg2, &context);
if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
{
/* decNumber exception flags we care about here. */
int ieee_flags;
int dec_flags = DEC_IEEE_854_Division_by_zero | DEC_IEEE_854_Inexact
| DEC_IEEE_854_Invalid_operation | DEC_IEEE_854_Overflow
| DEC_IEEE_854_Underflow;
dec_flags &= context.status;
ieee_flags = DFP_IEEE_FLAGS (dec_flags);
if (ieee_flags != 0)
DFP_HANDLE_EXCEPTIONS (ieee_flags);
}
TO_ENCODED (&encoded_result, &res, &context);
IEEE_TO_HOST (encoded_result, &result);
return result;
@ -379,6 +405,17 @@ DFP_TO_DFP (DFP_C_TYPE f_from)
TO_INTERNAL (&s_from, &d);
TO_ENCODED_TO (&s_to, &d, &context);
if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
{
/* decNumber exception flags we care about here. */
int ieee_flags;
int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation;
dec_flags &= context.status;
ieee_flags = DFP_IEEE_FLAGS (dec_flags);
if (ieee_flags != 0)
DFP_HANDLE_EXCEPTIONS (ieee_flags);
}
IEEE_TO_HOST_TO (s_to, &f_to);
return f_to;
}
@ -394,6 +431,9 @@ DFP_TO_INT (DFP_C_TYPE x)
/* decNumber's decimal* types have the same format as C's _Decimal*
types, but they have different calling conventions. */
/* TODO: Decimal float to integer conversions should raise FE_INVALID
if the result value does not fit into the result type. */
IEEE_TYPE s;
char buf[BUFMAX];
char *pos;
@ -444,6 +484,19 @@ INT_TO_DFP (INT_TYPE i)
/* Convert from the floating point string to a decimal* type. */
FROM_STRING (&s, buf, &context);
IEEE_TO_HOST (s, &f);
if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
{
/* decNumber exception flags we care about here. */
int ieee_flags;
int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
| DEC_IEEE_854_Overflow;
dec_flags &= context.status;
ieee_flags = DFP_IEEE_FLAGS (dec_flags);
if (ieee_flags != 0)
DFP_HANDLE_EXCEPTIONS (ieee_flags);
}
return f;
}
#endif
@ -492,6 +545,19 @@ BFP_TO_DFP (BFP_TYPE x)
/* Convert from the floating point string to a decimal* type. */
FROM_STRING (&s, buf, &context);
IEEE_TO_HOST (s, &f);
if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
{
/* decNumber exception flags we care about here. */
int ieee_flags;
int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
| DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow;
dec_flags &= context.status;
ieee_flags = DFP_IEEE_FLAGS (dec_flags);
if (ieee_flags != 0)
DFP_HANDLE_EXCEPTIONS (ieee_flags);
}
return f;
}
#endif

View File

@ -32,6 +32,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include <fenv.h>
#include <decRound.h>
#include <decExcept.h>
#include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
@ -120,6 +121,27 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#define DFP_INIT_ROUNDMODE(A) A = DEC_ROUND_HALF_EVEN
#endif
#ifdef DFP_EXCEPTIONS_ENABLED
/* Return IEEE exception flags based on decNumber status flags. */
#define DFP_IEEE_FLAGS(DEC_FLAGS) __extension__ \
({int _fe_flags = 0; \
if ((dec_flags & DEC_IEEE_854_Division_by_zero) != 0) \
_fe_flags |= FE_DIVBYZERO; \
if ((dec_flags & DEC_IEEE_854_Inexact) != 0) \
_fe_flags |= FE_INEXACT; \
if ((dec_flags & DEC_IEEE_854_Invalid_operation) != 0) \
_fe_flags |= FE_INVALID; \
if ((dec_flags & DEC_IEEE_854_Overflow) != 0) \
_fe_flags |= FE_OVERFLOW; \
if ((dec_flags & DEC_IEEE_854_Underflow) != 0) \
_fe_flags |= FE_UNDERFLOW; \
_fe_flags; })
#else
#define DFP_EXCEPTIONS_ENABLED 0
#define DFP_IEEE_FLAGS(A) 0
#define DFP_HANDLE_EXCEPTIONS(A) do {} while (0)
#endif
/* Conversions between different decimal float types use WIDTH_TO to
determine additional macros to define. */

View File

@ -1,5 +1,12 @@
2007-01-29 Janis Johnson <janis187@us.ibm.com>
* gcc.dg/dfp/dfp-except.h: New file.
* gcc.dg/dfp/fe-check.h: New file.
* gcc.dg/dfp/fe-binop.c: New test.
* gcc.dg/dfp/fe-convert-1.c: New test.
* gcc.dg/dfp/fe-convert-2.c: New test.
* gcc.dg/dfp/fe-convert-3.c: New test.
* gcc.dg/dfp/dec-eval-method.c: Replace decfloat.h with float.h.
* gcc.dg/dfp/decfloat-constants.c: Ditto.
* gcc.dg/dfp/convert-dfp.c: Ditto.

View File

@ -0,0 +1,13 @@
/* Use undocumented functions in libgcc to clear and test dummy floating
point exception flags. That functionality is in libgcc just for
testing purposes.
If fesetexcept and feclearexcept are available, use those instead. */
/* Get names of exception flags. */
#include <fenv.h>
extern void __dfp_clear_except (int);
#define DFP_CLEAR_EXCEPT(M) __dfp_clear_except(M)
extern int __dfp_test_except (int);
#define DFP_TEST_EXCEPT(M) __dfp_test_except(M)

View File

@ -0,0 +1,107 @@
/* { dg-options "-std=gnu99" } */
/* Touch tests that check for raising appropriate exceptions for binary
arithmetic operations on decimal float values. */
#include "fe-check.h"
volatile _Decimal32 a32, b32, c32;
volatile _Decimal64 a64, b64, c64;
volatile _Decimal128 a128, b128, c128;
_Decimal32 inf32;
_Decimal64 inf64;
_Decimal128 inf128;
BINOP (100, /, a32, 2.0df, b32, 0.df, c32, FE_DIVBYZERO)
BINOP (101, /, a64, 2.0dd, b64, 0.dd, c64, FE_DIVBYZERO)
BINOP (102, /, a128, 2.0dl, b128, 0.dl, c128, FE_DIVBYZERO)
BINOP (200, /, a32, 0.df, b32, 0.df, c32, FE_INVALID)
BINOP (201, /, a64, 0.dd, b64, 0.dd, c64, FE_INVALID)
BINOP (202, /, a128, 0.dl, b128, 0.dl, c128, FE_INVALID)
BINOP (203, /, a32, inf32, b32, inf32, c32, FE_INVALID)
BINOP (204, /, a64, inf64, b64, inf64, c64, FE_INVALID)
BINOP (205, /, a128, inf128, b128, inf128, c128, FE_INVALID)
BINOP (206, *, a32, 0.df, b32, __builtin_infd32(), c32, FE_INVALID)
BINOP (207, *, a32, __builtin_infd32(), b32, 0.df, c32, FE_INVALID)
BINOP (208, *, a64, 0.df, b64, __builtin_infd64(), c64, FE_INVALID)
BINOP (209, *, a64, __builtin_infd64(), b64, 0.df, c64, FE_INVALID)
BINOP (210, *, a128, 0.df, b128, __builtin_infd128(), c128, FE_INVALID)
BINOP (211, *, a128, __builtin_infd128(), b128, 0.df, c128, FE_INVALID)
BINOP (212, +, a32, inf32, b32, -inf32, c32, FE_INVALID)
BINOP (213, +, a64, inf64, b64, -inf64, c64, FE_INVALID)
BINOP (214, +, a128, inf128, b128, -inf128, c128, FE_INVALID)
BINOP (215, -, a32, inf32, b32, inf32, c32, FE_INVALID)
BINOP (216, -, a64, inf64, b64, inf64, c64, FE_INVALID)
BINOP (217, -, a128, inf128, b128, inf128, c128, FE_INVALID)
BINOP (300, /, a32, 9.9e94df, b32, 1.e-3df, c32, FE_OVERFLOW|FE_INEXACT)
BINOP (301, /, a64, 9.9e382dd, b64, 1.e-3dd, c64, FE_OVERFLOW|FE_INEXACT)
BINOP (302, /, a128, 9.9e6142dl, b128, 1.e-3dl, c128, FE_OVERFLOW|FE_INEXACT)
BINOP (303, +, a32, 9.9e96df, b32, 1.e96df, c32, FE_OVERFLOW|FE_INEXACT)
BINOP (304, +, a64, 9.9e384dd, b64, 1.e384dd, c64, FE_OVERFLOW|FE_INEXACT)
BINOP (305, +, a128, 9.9e6144dl, b128, 1.e6144dl, c128, FE_OVERFLOW|FE_INEXACT)
BINOP (400, /, a32, 1.e-3df, b32, 9.9e94df, c32, FE_UNDERFLOW|FE_INEXACT)
BINOP (401, /, a64, 1.e-3dd, b64, 9.9e382dd, c64, FE_UNDERFLOW|FE_INEXACT)
BINOP (402, /, a128, 1.e-3dl, b128, 9.9e6142dl, c128, FE_UNDERFLOW|FE_INEXACT)
BINOP (403, *, a32, 1.e-95df, b32, 1.e-7df, c32, FE_UNDERFLOW|FE_INEXACT)
BINOP (404, *, a64, 1.e-383dd, b64, 1.e-16dd, c64, FE_UNDERFLOW|FE_INEXACT)
BINOP (405, *, a128, 1.e-6143dl, b128, 1.e-34dl, c128, FE_UNDERFLOW|FE_INEXACT)
BINOP (500, /, a32, 1.df, b32, 3.df, c32, FE_INEXACT)
BINOP (501, /, a64, 1.dd, b64, 3.dd, c64, FE_INEXACT)
BINOP (502, /, a128, 1.dl, b128, 3.dl, c128, FE_INEXACT)
int
main ()
{
inf32 = __builtin_infd32();
inf64 = __builtin_infd64();
inf128 = __builtin_infd128();
binop_100 ();
binop_101 ();
binop_102 ();
binop_200 ();
binop_201 ();
binop_202 ();
binop_203 ();
binop_204 ();
binop_205 ();
binop_206 ();
binop_207 ();
binop_208 ();
binop_209 ();
binop_210 ();
binop_211 ();
binop_212 ();
binop_213 ();
binop_214 ();
binop_215 ();
binop_216 ();
binop_217 ();
binop_300 ();
binop_301 ();
binop_302 ();
binop_303 ();
binop_304 ();
binop_305 ();
binop_400 ();
binop_401 ();
binop_402 ();
binop_403 ();
binop_404 ();
binop_405 ();
binop_500 ();
binop_501 ();
binop_502 ();
if (failcnt != 0)
abort ();
return 0;
}

View File

@ -0,0 +1,70 @@
/* Common support for checking that appropriate floating point exceptions
are raised for decimal float operations. These tests are here to test
the software decimal float support in libgcc. */
#include "dfp-except.h"
extern void abort (void);
static int failcnt = 0;
/* Support compiling the test to report individual failures; default is
to abort as soon as a check fails. */
#if defined(DBG) || defined(DBG2)
#include <stdio.h>
#define FAILURE(NUM,KIND,EXCEPT) \
{ printf ("failed for test %d: %s %s\n", NUM, KIND, EXCEPT); failcnt++; }
#else
#define FAILURE(N,K,E) abort ();
#endif
/* This is useful when modifying the test to make sure that tests are
actually run. */
#if defined(DBG2)
#define SUCCESS(NUM,EXCEPT) \
{ printf ("passed for test %d: %s\n", NUM, EXCEPT); }
#else
#define SUCCESS(N,E) ;
#endif
#define CHECKFLAG(NUM,EXCEPT,GOT,WANT) \
if ((WANT & EXCEPT) != (GOT & EXCEPT)) \
{ \
if ((WANT & EXCEPT) != 0) \
FAILURE (NUM, "missing", #EXCEPT) \
else \
FAILURE (NUM, "unexpected", #EXCEPT) \
} \
else \
SUCCESS (NUM, #EXCEPT)
void
checkflags (int num, int want)
{
int got = DFP_TEST_EXCEPT (FE_ALL_EXCEPT);
CHECKFLAG (num, FE_INVALID, got, want)
CHECKFLAG (num, FE_OVERFLOW, got, want)
CHECKFLAG (num, FE_UNDERFLOW, got, want)
CHECKFLAG (num, FE_DIVBYZERO, got, want)
CHECKFLAG (num, FE_INEXACT, got, want)
}
#define BINOP(NUM,OP,VAR1,VAL1,VAR2,VAL2,VAR3,EXCEPT) \
void \
binop_##NUM (void) \
{ \
VAR1 = VAL1; \
VAR2 = VAL2; \
DFP_CLEAR_EXCEPT (FE_ALL_EXCEPT); \
VAR3 = VAR1 OP VAR2; \
checkflags (NUM, EXCEPT); \
}
#define CONVERT(NUM,FROM,TO,VALUE,EXCEPT) \
void \
convert_##NUM (void) \
{ \
FROM = VALUE; \
DFP_CLEAR_EXCEPT (FE_ALL_EXCEPT); \
TO = FROM; \
checkflags (NUM, EXCEPT); \
}

View File

@ -0,0 +1,42 @@
/* { dg-options "-std=gnu99" } */
/* Check that appropriate exceptions are raised for conversions involving
decimal float values. */
#include "fe-check.h"
volatile _Decimal32 d32;
volatile _Decimal64 d64;
volatile _Decimal128 d128;
/* Conversions between decimal float types should raise an invalid
exception if the values doesn't fit, either because the value
is too large or the result can't hold the full precision. */
CONVERT (100, d64, d32, 9.999999e96DD, 0)
CONVERT (101, d64, d32, 10.000000e96DD, FE_INEXACT)
CONVERT (102, d64, d32, 1.1111111DD, FE_INEXACT)
CONVERT (110, d128, d32, 9.999999e96DL, 0)
CONVERT (111, d128, d32, 10.000000e96DL, FE_INEXACT)
CONVERT (112, d128, d32, 1.1111111DL, FE_INEXACT)
CONVERT (120, d128, d64, 9.999999999999999E384DL, 0)
CONVERT (121, d128, d64, 10.00000000000000E384DL, FE_INEXACT)
CONVERT (122, d128, d64, 1.1111111111111111DL, FE_INEXACT)
int
main ()
{
convert_100 ();
convert_101 ();
convert_102 ();
convert_110 ();
convert_111 ();
convert_112 ();
convert_120 ();
convert_121 ();
convert_122 ();
if (failcnt != 0)
abort ();
return 0;
}

View File

@ -0,0 +1,34 @@
/* { dg-options "-std=gnu99" } */
/* Check that appropriate exceptions are raised for BFP to DFP conversions.
The test only uses double and _Decimal32; tests for conversions to
_Decimal64 would need 128-bit long double. */
#include "fe-check.h"
volatile _Decimal32 d32;
volatile double d;
CONVERT (100, d, d32, 1.0e96, 0)
CONVERT (101, d, d32, 1.0e97, FE_OVERFLOW|FE_INEXACT)
CONVERT (102, d, d32, -1.0e96, 0)
CONVERT (103, d, d32, -1.0e97, FE_OVERFLOW|FE_INEXACT)
#if 0
/* These should result in fp exceptions but don't. */
CONVERT (xxx, d, d32, 1.0e-96, FE_UNDERFLOW|FE_INEXACT)
CONVERT (xxx, d, d32, 0.00048828125, FE_INEXACT) /* exact power of 2 */
#endif
int
main ()
{
convert_100 ();
convert_101 ();
convert_102 ();
convert_103 ();
if (failcnt != 0)
abort ();
return 0;
}

View File

@ -0,0 +1,49 @@
/* { dg-options "-std=gnu99" } */
/* Check that appropriate exceptions are raised for int to DFP conversions. */
#include "fe-check.h"
volatile _Decimal32 d32;
volatile _Decimal64 d64;
volatile signed int si;
volatile unsigned int ui;
volatile signed long long sll;
volatile unsigned long long ull;
CONVERT (100, si, d32, 9999999, 0)
CONVERT (101, si, d32, 11111111, FE_INEXACT)
CONVERT (102, si, d32, -9999999, 0)
CONVERT (103, si, d32, -10000001, FE_INEXACT)
CONVERT (110, ui, d32, 9999999, 0)
CONVERT (111, ui, d32, 10000001, FE_INEXACT)
CONVERT (200, sll, d64, 9999999999999999, 0)
CONVERT (201, sll, d64, 10000000000000001, FE_INEXACT)
CONVERT (202, sll, d64, -9999999999999999, 0)
CONVERT (203, sll, d64, -10000000000000001, FE_INEXACT)
CONVERT (210, ull, d64, 9999999999999999, 0)
CONVERT (211, ull, d64, 10000000000000001, FE_INEXACT)
int
main ()
{
if (sizeof (long long) != 16)
return 0;
convert_100 ();
convert_101 ();
convert_102 ();
convert_103 ();
convert_110 ();
convert_111 ();
convert_200 ();
convert_201 ();
convert_202 ();
convert_203 ();
convert_210 ();
convert_211 ();
if (failcnt != 0)
abort ();
return 0;
}

View File

@ -1,3 +1,8 @@
2007-01-29 Janis Johnson <janis187@us.ibm.com>
* decExcept.c: New.
* decExcept.h: New.
2006-11-29 Janis Johnson <janis187@us.ibm.com>
* decRound.c: Move declarations to new file, update comments.

59
libdecnumber/decExcept.c Normal file
View File

@ -0,0 +1,59 @@
/* Temporary library support for decimal floating point.
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
#include <fenv.h>
#include "config.h"
#include "decContext.h"
#include "decExcept.h"
/* Internal, non-documented functions for testing libgcc functions.
This support is not sufficient for real use. */
static int __dfp_except_flags = 0;
/* Clear the dummy exception flags. */
void
__dfp_clear_except (void)
{
__dfp_except_flags = 0;
}
/* Return the dummy exception flags corresponding to the mask. */
int
__dfp_test_except (int mask)
{
return __dfp_except_flags & mask;
}
/* Set dummy exception flags. */
void
__dfp_raise_except (int flags)
{
__dfp_except_flags |= flags;
}

39
libdecnumber/decExcept.h Normal file
View File

@ -0,0 +1,39 @@
/* Temporary library support for decimal floating point.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
#include <fenv.h>
#include "config.h"
#include "decContext.h"
#define DFP_EXCEPTIONS_ENABLED 1
#define DFP_HANDLE_EXCEPTIONS(A) __dfp_raise_except(A)
void __dfp_clear_except (void);
int __dfp_test_except (int);
void __dfp_raise_except (int);

View File

@ -1,3 +1,7 @@
2007-01-29 Janis Johnson <janis187@us.ibm.com>
* Makefile.in (dec-filenames): Add decExcept.
2007-01-28 Daniel Jacobowitz <dan@codesourcery.com>
PR bootstrap/30469

View File

@ -464,7 +464,7 @@ endif
dec-filenames =
ifneq ($(D32PBIT)$(D64PBIT)$(D128PBIT),)
dec-filenames += decContext decNumber decRound decLibrary decUtility
dec-filenames += decContext decNumber decExcept decRound decLibrary decUtility
endif
ifneq ($(D32PBIT),)