From e6eb1ce760420ad1ed88e50103be3cc26089c6c4 Mon Sep 17 00:00:00 2001 From: janis Date: Tue, 11 Sep 2007 00:25:18 +0000 Subject: [PATCH] * config/dfp-bit.c (dfp_unary_func): Delete. (dfp_unary_op): Delete. (dfp_binary_op): Use decFloat functions instead of decNumber functions for binary operations. (d32_binary_op): Convert 32-bit operands to 64 bits for evaluation. (dnn_binary_op): Call dfp_binary_op with decFloat rather than DFP_C_TYPE. (dfp_compare_op): Use decFloat functions insteadof decNumber functions for comparisons. (d32_compare_op): Convert 32-bit operands to 64 bits for evaluation. (dnn_binary_op): Call dfp_compare_op with decFloat rather than DFP_C_TYPE. (DFP_ADD, DFP_SUB, DFP_MULTIPLE, DFP_DIVIDE): Use macros for call to dxx_binary_op and decFloat function. (DFP_EQ, DFP_NE, DFP_LT, DFP_GT, DFP_LE, DFP_GE): Use macros for calls to dxx_binary_op and decFloat function. * config/dfp-bit.h: Include decFloat header files. (decFloat, DFP_BINARY_OP, DFP_COMPARE_OP, DEC_FLOAT_ADD, DEC_FLOAT_SUBTRACT, DEC_FLOAT_MULTIPLY, DEC_FLOAT_DIVIDE, DEC_FLOAT_COMPARE, DEC_FLOAT_IS_ZERO, DEC_FLOAT_IS_NAN, DEC_FLOAT_IS_SIGNED: Define for each of 3 operand widths. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128358 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 24 ++++++++ gcc/config/dfp-bit.c | 157 +++++++++++++++++++++++++++++---------------------- gcc/config/dfp-bit.h | 43 ++++++++++++++ 3 files changed, 157 insertions(+), 67 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab75d14b912..275023a773b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2007-09-10 Janis Johnson + + * config/dfp-bit.c (dfp_unary_func): Delete. + (dfp_unary_op): Delete. + (dfp_binary_op): Use decFloat functions instead of decNumber + functions for binary operations. + (d32_binary_op): Convert 32-bit operands to 64 bits for evaluation. + (dnn_binary_op): Call dfp_binary_op with decFloat rather than + DFP_C_TYPE. + (dfp_compare_op): Use decFloat functions insteadof decNumber + functions for comparisons. + (d32_compare_op): Convert 32-bit operands to 64 bits for evaluation. + (dnn_binary_op): Call dfp_compare_op with decFloat rather than + DFP_C_TYPE. + (DFP_ADD, DFP_SUB, DFP_MULTIPLE, DFP_DIVIDE): Use macros for + call to dxx_binary_op and decFloat function. + (DFP_EQ, DFP_NE, DFP_LT, DFP_GT, DFP_LE, DFP_GE): Use macros for + calls to dxx_binary_op and decFloat function. + * config/dfp-bit.h: Include decFloat header files. + (decFloat, DFP_BINARY_OP, DFP_COMPARE_OP, DEC_FLOAT_ADD, + DEC_FLOAT_SUBTRACT, DEC_FLOAT_MULTIPLY, DEC_FLOAT_DIVIDE, + DEC_FLOAT_COMPARE, DEC_FLOAT_IS_ZERO, DEC_FLOAT_IS_NAN, + DEC_FLOAT_IS_SIGNED: Define for each of 3 operand widths. + 2007-09-10 Harsha Jagasia Jan Sjodin diff --git a/gcc/config/dfp-bit.c b/gcc/config/dfp-bit.c index 252abe0224c..6a1bc30a21a 100644 --- a/gcc/config/dfp-bit.c +++ b/gcc/config/dfp-bit.c @@ -63,33 +63,25 @@ void __host_to_ieee_128 (_Decimal128 in, decimal128 *out); void __ieee_to_host_128 (decimal128 in, _Decimal128 *out); #endif -/* A pointer to a unary decNumber operation. */ -typedef decNumber* (*dfp_unary_func) - (decNumber *, decNumber *, decContext *); - -/* A pointer to a binary decNumber operation. */ -typedef decNumber* (*dfp_binary_func) - (decNumber *, const decNumber *, const decNumber *, decContext *); +/* A pointer to a binary decFloat operation. */ +typedef decFloat* (*dfp_binary_func) + (decFloat *, const decFloat *, const decFloat *, decContext *); -/* Unary operations. */ +/* Binary operations. */ -static inline DFP_C_TYPE -dfp_unary_op (dfp_unary_func op, DFP_C_TYPE arg) +/* Use a decFloat (decDouble or decQuad) function to perform a DFP + binary operation. */ +static inline decFloat +dfp_binary_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b) { - DFP_C_TYPE result; + decFloat result; decContext context; - decNumber arg1, res; - IEEE_TYPE a, encoded_result; - - HOST_TO_IEEE (arg, &a); decContextDefault (&context, CONTEXT_INIT); DFP_INIT_ROUNDMODE (context.round); - TO_INTERNAL (&a, &arg1); - /* Perform the operation. */ - op (&res, &arg1, &context); + op (&result, &arg_a, &arg_b, &context); if (DFP_EXCEPTIONS_ENABLED && context.status != 0) { @@ -104,39 +96,35 @@ dfp_unary_op (dfp_unary_func op, DFP_C_TYPE arg) DFP_HANDLE_EXCEPTIONS (ieee_flags); } - TO_ENCODED (&encoded_result, &res, &context); - IEEE_TO_HOST (encoded_result, &result); return result; } -/* Binary operations. */ - -static inline DFP_C_TYPE -dfp_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) +#if WIDTH == 32 +/* The decNumber package doesn't provide arithmetic for decSingle (32 bits); + convert to decDouble, use the operation for that, and convert back. */ +static inline _Decimal32 +d32_binary_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b) { - DFP_C_TYPE result; + union { _Decimal32 c; decSingle f; } a32, b32, res32; + decDouble a, b, res; decContext context; - decNumber arg1, arg2, res; - IEEE_TYPE a, b, encoded_result; - HOST_TO_IEEE (arg_a, &a); - HOST_TO_IEEE (arg_b, &b); + /* Widen the operands and perform the operation. */ + a32.c = arg_a; + b32.c = arg_b; + decSingleToWider (&a32.f, &a); + decSingleToWider (&b32.f, &b); + res = dfp_binary_op (op, a, b); + /* Narrow the result, which might result in an underflow or overflow. */ decContextDefault (&context, CONTEXT_INIT); DFP_INIT_ROUNDMODE (context.round); - - TO_INTERNAL (&a, &arg1); - TO_INTERNAL (&b, &arg2); - - /* Perform the operation. */ - op (&res, &arg1, &arg2, &context); - + decSingleFromWider (&res32.f, &res, &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 + int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow; dec_flags &= context.status; ieee_flags = DFP_IEEE_FLAGS (dec_flags); @@ -144,45 +132,80 @@ dfp_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) DFP_HANDLE_EXCEPTIONS (ieee_flags); } - TO_ENCODED (&encoded_result, &res, &context); - IEEE_TO_HOST (encoded_result, &result); - return result; + return res32.c; +} +#else +/* decFloat operations are supported for decDouble (64 bits) and + decQuad (128 bits). The bit patterns for the types are the same. */ +static inline DFP_C_TYPE +dnn_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) +{ + union { DFP_C_TYPE c; decFloat f; } a, b, result; + + a.c = arg_a; + b.c = arg_b; + result.f = dfp_binary_op (op, a.f, b.f); + return result.c; } +#endif /* Comparison operations. */ -static inline int -dfp_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) +/* Use a decFloat (decDouble or decQuad) function to perform a DFP + comparison. */ +static inline CMPtype +dfp_compare_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b) { - IEEE_TYPE a, b; decContext context; - decNumber arg1, arg2, res; + decFloat res; int result; - HOST_TO_IEEE (arg_a, &a); - HOST_TO_IEEE (arg_b, &b); - decContextDefault (&context, CONTEXT_INIT); DFP_INIT_ROUNDMODE (context.round); - TO_INTERNAL (&a, &arg1); - TO_INTERNAL (&b, &arg2); - /* Perform the comparison. */ - op (&res, &arg1, &arg2, &context); + op (&res, &arg_a, &arg_b, &context); - if (decNumberIsNegative (&res)) + if (DEC_FLOAT_IS_SIGNED (&res)) result = -1; - else if (decNumberIsZero (&res)) + else if (DEC_FLOAT_IS_ZERO (&res)) result = 0; - else if (decNumberIsNaN (&res)) + else if (DEC_FLOAT_IS_NAN (&res)) result = -2; else result = 1; - return result; + return (CMPtype) result; +} + +#if WIDTH == 32 +/* The decNumber package doesn't provide comparisons for decSingle (32 bits); + convert to decDouble, use the operation for that, and convert back. */ +static inline CMPtype +d32_compare_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b) +{ + union { _Decimal32 c; decSingle f; } a32, b32; + decDouble a, b; + + a32.c = arg_a; + b32.c = arg_b; + decSingleToWider (&a32.f, &a); + decSingleToWider (&b32.f, &b); + return dfp_compare_op (op, a, b); } +#else +/* decFloat comparisons are supported for decDouble (64 bits) and + decQuad (128 bits). The bit patterns for the types are the same. */ +static inline CMPtype +dnn_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) +{ + union { DFP_C_TYPE c; decFloat f; } a, b; + a.c = arg_a; + b.c = arg_b; + return dfp_compare_op (op, a.f, b.f); +} +#endif #if defined(L_conv_sd) void @@ -230,13 +253,13 @@ __ieee_to_host_128 (decimal128 in, _Decimal128 *out) DFP_C_TYPE DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { - return dfp_binary_op (decNumberAdd, arg_a, arg_b); + return DFP_BINARY_OP (DEC_FLOAT_ADD, arg_a, arg_b); } DFP_C_TYPE DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { - return dfp_binary_op (decNumberSubtract, arg_a, arg_b); + return DFP_BINARY_OP (DEC_FLOAT_SUBTRACT, arg_a, arg_b); } #endif /* L_addsub */ @@ -244,7 +267,7 @@ DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) DFP_C_TYPE DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { - return dfp_binary_op (decNumberMultiply, arg_a, arg_b); + return DFP_BINARY_OP (DEC_FLOAT_MULTIPLY, arg_a, arg_b); } #endif /* L_mul */ @@ -252,7 +275,7 @@ DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) DFP_C_TYPE DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { - return dfp_binary_op (decNumberDivide, arg_a, arg_b); + return DFP_BINARY_OP (DEC_FLOAT_DIVIDE, arg_a, arg_b); } #endif /* L_div */ @@ -260,8 +283,8 @@ DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) CMPtype DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { - int stat; - stat = dfp_compare_op (decNumberCompare, arg_a, arg_b); + CMPtype stat; + stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b); /* For EQ return zero for true, nonzero for false. */ return stat != 0; } @@ -272,7 +295,7 @@ CMPtype DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { int stat; - stat = dfp_compare_op (decNumberCompare, arg_a, arg_b); + stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b); /* For NE return zero for true, nonzero for false. */ if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */ return 1; @@ -285,7 +308,7 @@ CMPtype DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { int stat; - stat = dfp_compare_op (decNumberCompare, arg_a, arg_b); + stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b); /* For LT return -1 (<0) for true, 1 for false. */ return (stat == -1) ? -1 : 1; } @@ -296,7 +319,7 @@ CMPtype DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { int stat; - stat = dfp_compare_op (decNumberCompare, arg_a, arg_b); + stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b); /* For GT return 1 (>0) for true, -1 for false. */ return (stat == 1) ? 1 : -1; } @@ -307,7 +330,7 @@ CMPtype DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { int stat; - stat = dfp_compare_op (decNumberCompare, arg_a, arg_b); + stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b); /* For LE return 0 (<= 0) for true, 1 for false. */ if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */ return 1; @@ -320,7 +343,7 @@ CMPtype DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b) { int stat; - stat = dfp_compare_op (decNumberCompare, arg_a, arg_b); + stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b); /* For GE return 1 (>=0) for true, -1 for false. */ if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */ return -1; diff --git a/gcc/config/dfp-bit.h b/gcc/config/dfp-bit.h index dfbf4f48338..7c4738760ed 100644 --- a/gcc/config/dfp-bit.h +++ b/gcc/config/dfp-bit.h @@ -277,12 +277,15 @@ extern float strtof (const char *, char **); #if WIDTH == 128 || WIDTH_TO == 128 #include "decimal128.h" +#include "decQuad.h" #endif #if WIDTH == 64 || WIDTH_TO == 64 #include "decimal64.h" +#include "decDouble.h" #endif #if WIDTH == 32 || WIDTH_TO == 32 #include "decimal32.h" +#include "decSingle.h" #endif #include "decNumber.h" @@ -332,6 +335,46 @@ extern float strtof (const char *, char **); #define DFP_UNORD DPD_BID_NAME(__dpd_unordtd2,__bid_unordtd2) #endif +/* Names of decNumber functions for DPD arithmetic. */ + +#if WIDTH == 32 +#define decFloat decDouble +#define DFP_BINARY_OP d32_binary_op +#define DFP_COMPARE_OP d32_compare_op +#define DEC_FLOAT_ADD decDoubleAdd +#define DEC_FLOAT_SUBTRACT decDoubleSubtract +#define DEC_FLOAT_MULTIPLY decDoubleMultiply +#define DEC_FLOAT_DIVIDE decDoubleDivide +#define DEC_FLOAT_COMPARE decDoubleCompare +#define DEC_FLOAT_IS_ZERO decDoubleIsZero +#define DEC_FLOAT_IS_NAN decDoubleIsNaN +#define DEC_FLOAT_IS_SIGNED decDoubleIsSigned +#elif WIDTH == 64 +#define DFP_BINARY_OP dnn_binary_op +#define DFP_COMPARE_OP dnn_compare_op +#define decFloat decDouble +#define DEC_FLOAT_ADD decDoubleAdd +#define DEC_FLOAT_SUBTRACT decDoubleSubtract +#define DEC_FLOAT_MULTIPLY decDoubleMultiply +#define DEC_FLOAT_DIVIDE decDoubleDivide +#define DEC_FLOAT_COMPARE decDoubleCompare +#define DEC_FLOAT_IS_ZERO decDoubleIsZero +#define DEC_FLOAT_IS_NAN decDoubleIsNaN +#define DEC_FLOAT_IS_SIGNED decDoubleIsSigned +#elif WIDTH == 128 +#define DFP_BINARY_OP dnn_binary_op +#define DFP_COMPARE_OP dnn_compare_op +#define decFloat decQuad +#define DEC_FLOAT_ADD decQuadAdd +#define DEC_FLOAT_SUBTRACT decQuadSubtract +#define DEC_FLOAT_MULTIPLY decQuadMultiply +#define DEC_FLOAT_DIVIDE decQuadDivide +#define DEC_FLOAT_COMPARE decQuadCompare +#define DEC_FLOAT_IS_ZERO decQuadIsZero +#define DEC_FLOAT_IS_NAN decQuadIsNaN +#define DEC_FLOAT_IS_SIGNED decQuadIsSigned +#endif + /* Names of functions to convert between different decimal float types. */ #if WIDTH == 32 -- 2.11.0