X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fdfp.c;h=e2e90c4a4c320167c18a7f235c373b23a47c07e2;hb=5a0619d6d654250bddcb09385c402a07c60f5ace;hp=804f2031ca18f613014a91d398b89e5280e4fb07;hpb=eaf00f5717c138e8e75fc3265b79295208ab5b94;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/dfp.c b/gcc/dfp.c index 804f2031ca1..e2e90c4a4c3 100644 --- a/gcc/dfp.c +++ b/gcc/dfp.c @@ -1,11 +1,12 @@ /* Decimal floating point support. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2007, 2008, 2009 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 +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -14,9 +15,8 @@ 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. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -24,7 +24,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tm.h" #include "tree.h" #include "toplev.h" -#include "real.h" #include "tm_p.h" #include "dfp.h" @@ -32,28 +31,14 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA decNumber structure is large enough to hold decimal128 digits. */ #include "decimal128.h" +#include "decimal128Local.h" #include "decimal64.h" #include "decimal32.h" #include "decNumber.h" -static uint32_t -dfp_byte_swap (uint32_t in) -{ - uint32_t out = 0; - unsigned char *p = (unsigned char *) &out; - union { - uint32_t i; - unsigned char b[4]; - } u; - - u.i = in; - p[0] = u.b[3]; - p[1] = u.b[2]; - p[2] = u.b[1]; - p[3] = u.b[0]; - - return out; -} +#ifndef WORDS_BIGENDIAN +#define WORDS_BIGENDIAN 0 +#endif /* Initialize R (a real with the decimal flag set) from DN. Can utilize status passed in via CONTEXT, if a previous operation had @@ -65,8 +50,6 @@ decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context) memset (r, 0, sizeof (REAL_VALUE_TYPE)); r->cl = rvc_normal; - if (decNumberIsZero (dn)) - r->cl = rvc_zero; if (decNumberIsNaN (dn)) r->cl = rvc_nan; if (decNumberIsInfinite (dn)) @@ -96,7 +79,7 @@ decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s) decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; - decNumberFromString (&dn, (char *) s, &set); + decNumberFromString (&dn, s, &set); /* It would be more efficient to store directly in decNumber format, but that is impractical from current data structure size. @@ -119,17 +102,17 @@ decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn) decNumberZero (dn); break; case rvc_inf: - decNumberFromString (dn, (char *)"Infinity", &set); + decNumberFromString (dn, "Infinity", &set); break; case rvc_nan: if (r->signalling) - decNumberFromString (dn, (char *)"snan", &set); + decNumberFromString (dn, "snan", &set); else - decNumberFromString (dn, (char *)"nan", &set); + decNumberFromString (dn, "nan", &set); break; case rvc_normal: gcc_assert (r->decimal); - decimal128ToNumber ((decimal128 *) r->sig, dn); + decimal128ToNumber ((const decimal128 *) r->sig, dn); break; default: gcc_unreachable (); @@ -137,61 +120,61 @@ decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn) /* Fix up sign bit. */ if (r->sign != decNumberIsNegative (dn)) - decNumberNegate (dn); + dn->bits ^= DECNEG; } -/* Encode a real into an IEEE 754R decimal32 type. */ +/* Encode a real into an IEEE 754 decimal32 type. */ -void +void encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, const REAL_VALUE_TYPE *r) { decNumber dn; decimal32 d32; decContext set; + int32_t image; decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; - decimal_to_decnumber (r, &dn); + decimal_to_decnumber (r, &dn); decimal32FromNumber (&d32, &dn, &set); - if (FLOAT_WORDS_BIG_ENDIAN) - buf[0] = *(uint32_t *) d32.bytes; - else - buf[0] = dfp_byte_swap (*(uint32_t *) d32.bytes); + memcpy (&image, d32.bytes, sizeof (int32_t)); + buf[0] = image; } -/* Decode an IEEE 754R decimal32 type into a real. */ +/* Decode an IEEE 754 decimal32 type into a real. */ -void decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) +void +decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r, const long *buf) { decNumber dn; decimal32 d32; decContext set; + int32_t image; decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; - if (FLOAT_WORDS_BIG_ENDIAN) - *((uint32_t *) d32.bytes) = (uint32_t) buf[0]; - else - *((uint32_t *) d32.bytes) = dfp_byte_swap ((uint32_t) buf[0]); + image = buf[0]; + memcpy (&d32.bytes, &image, sizeof (int32_t)); decimal32ToNumber (&d32, &dn); - decimal_from_decnumber (r, &dn, &set); + decimal_from_decnumber (r, &dn, &set); } -/* Encode a real into an IEEE 754R decimal64 type. */ +/* Encode a real into an IEEE 754 decimal64 type. */ -void +void encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, const REAL_VALUE_TYPE *r) { decNumber dn; decimal64 d64; decContext set; + int32_t image; decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; @@ -199,55 +182,65 @@ encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, decimal_to_decnumber (r, &dn); decimal64FromNumber (&d64, &dn, &set); - if (FLOAT_WORDS_BIG_ENDIAN) + if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) { - buf[0] = *(uint32_t *) &d64.bytes[0]; - buf[1] = *(uint32_t *) &d64.bytes[4]; + memcpy (&image, &d64.bytes[0], sizeof (int32_t)); + buf[0] = image; + memcpy (&image, &d64.bytes[4], sizeof (int32_t)); + buf[1] = image; } else { - buf[1] = dfp_byte_swap (*(uint32_t *) &d64.bytes[0]); - buf[0] = dfp_byte_swap (*(uint32_t *) &d64.bytes[4]); + memcpy (&image, &d64.bytes[4], sizeof (int32_t)); + buf[0] = image; + memcpy (&image, &d64.bytes[0], sizeof (int32_t)); + buf[1] = image; } } -/* Decode an IEEE 754R decimal64 type into a real. */ +/* Decode an IEEE 754 decimal64 type into a real. */ -void +void decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, REAL_VALUE_TYPE *r, const long *buf) -{ +{ decNumber dn; decimal64 d64; decContext set; + int32_t image; decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; - if (FLOAT_WORDS_BIG_ENDIAN) + if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) { - *((uint32_t *) &d64.bytes[0]) = (uint32_t) buf[0]; - *((uint32_t *) &d64.bytes[4]) = (uint32_t) buf[1]; + image = buf[0]; + memcpy (&d64.bytes[0], &image, sizeof (int32_t)); + image = buf[1]; + memcpy (&d64.bytes[4], &image, sizeof (int32_t)); } else { - *((uint32_t *) &d64.bytes[0]) = dfp_byte_swap ((uint32_t) buf[1]); - *((uint32_t *) &d64.bytes[4]) = dfp_byte_swap ((uint32_t) buf[0]); + image = buf[1]; + memcpy (&d64.bytes[0], &image, sizeof (int32_t)); + image = buf[0]; + memcpy (&d64.bytes[4], &image, sizeof (int32_t)); } decimal64ToNumber (&d64, &dn); - decimal_from_decnumber (r, &dn, &set); + decimal_from_decnumber (r, &dn, &set); } -/* Encode a real into an IEEE 754R decimal128 type. */ +/* Encode a real into an IEEE 754 decimal128 type. */ -void +void encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, const REAL_VALUE_TYPE *r) { decNumber dn; decContext set; decimal128 d128; + int32_t image; decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; @@ -255,52 +248,69 @@ encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, decimal_to_decnumber (r, &dn); decimal128FromNumber (&d128, &dn, &set); - if (FLOAT_WORDS_BIG_ENDIAN) + if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) { - buf[0] = *(uint32_t *) &d128.bytes[0]; - buf[1] = *(uint32_t *) &d128.bytes[4]; - buf[2] = *(uint32_t *) &d128.bytes[8]; - buf[3] = *(uint32_t *) &d128.bytes[12]; + memcpy (&image, &d128.bytes[0], sizeof (int32_t)); + buf[0] = image; + memcpy (&image, &d128.bytes[4], sizeof (int32_t)); + buf[1] = image; + memcpy (&image, &d128.bytes[8], sizeof (int32_t)); + buf[2] = image; + memcpy (&image, &d128.bytes[12], sizeof (int32_t)); + buf[3] = image; } else { - buf[0] = dfp_byte_swap (*(uint32_t *) &d128.bytes[12]); - buf[1] = dfp_byte_swap (*(uint32_t *) &d128.bytes[8]); - buf[2] = dfp_byte_swap (*(uint32_t *) &d128.bytes[4]); - buf[3] = dfp_byte_swap (*(uint32_t *) &d128.bytes[0]); + memcpy (&image, &d128.bytes[12], sizeof (int32_t)); + buf[0] = image; + memcpy (&image, &d128.bytes[8], sizeof (int32_t)); + buf[1] = image; + memcpy (&image, &d128.bytes[4], sizeof (int32_t)); + buf[2] = image; + memcpy (&image, &d128.bytes[0], sizeof (int32_t)); + buf[3] = image; } } -/* Decode an IEEE 754R decimal128 type into a real. */ +/* Decode an IEEE 754 decimal128 type into a real. */ -void +void decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, REAL_VALUE_TYPE *r, const long *buf) { decNumber dn; decimal128 d128; decContext set; + int32_t image; decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; - if (FLOAT_WORDS_BIG_ENDIAN) + if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) { - *((uint32_t *) &d128.bytes[0]) = (uint32_t) buf[0]; - *((uint32_t *) &d128.bytes[4]) = (uint32_t) buf[1]; - *((uint32_t *) &d128.bytes[8]) = (uint32_t) buf[2]; - *((uint32_t *) &d128.bytes[12]) = (uint32_t) buf[3]; + image = buf[0]; + memcpy (&d128.bytes[0], &image, sizeof (int32_t)); + image = buf[1]; + memcpy (&d128.bytes[4], &image, sizeof (int32_t)); + image = buf[2]; + memcpy (&d128.bytes[8], &image, sizeof (int32_t)); + image = buf[3]; + memcpy (&d128.bytes[12], &image, sizeof (int32_t)); } else { - *((uint32_t *) &d128.bytes[0]) = dfp_byte_swap ((uint32_t) buf[3]); - *((uint32_t *) &d128.bytes[4]) = dfp_byte_swap ((uint32_t) buf[2]); - *((uint32_t *) &d128.bytes[8]) = dfp_byte_swap ((uint32_t) buf[1]); - *((uint32_t *) &d128.bytes[12]) = dfp_byte_swap ((uint32_t) buf[0]); + image = buf[3]; + memcpy (&d128.bytes[0], &image, sizeof (int32_t)); + image = buf[2]; + memcpy (&d128.bytes[4], &image, sizeof (int32_t)); + image = buf[1]; + memcpy (&d128.bytes[8], &image, sizeof (int32_t)); + image = buf[0]; + memcpy (&d128.bytes[12], &image, sizeof (int32_t)); } decimal128ToNumber (&d128, &dn); - decimal_from_decnumber (r, &dn, &set); + decimal_from_decnumber (r, &dn, &set); } /* Helper function to convert from a binary real internal @@ -311,8 +321,7 @@ decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from, enum machine_mode mode) { char string[256]; - decimal128 *d128; - d128 = (decimal128 *) from->sig; + const decimal128 *const d128 = (const decimal128 *) from->sig; decimal128ToString (d128, string); real_from_string3 (to, string, mode); @@ -355,12 +364,12 @@ decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, decimal_from_binary (&b1, b); b = &b1; } - + /* Convert into decNumber form for comparison operation. */ decContextDefault (&set, DEC_INIT_DECIMAL128); - set.traps = 0; - decimal128ToNumber ((decimal128 *) a->sig, &dn2); - decimal128ToNumber ((decimal128 *) b->sig, &dn3); + set.traps = 0; + decimal128ToNumber ((const decimal128 *) a->sig, &dn2); + decimal128ToNumber ((const decimal128 *) b->sig, &dn3); /* Finally, do the comparison. */ decNumberCompare (&dn, &dn2, &dn3, &set); @@ -372,7 +381,7 @@ decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, return 0; else if (decNumberIsNegative (&dn)) return -1; - else + else return 1; } @@ -425,7 +434,7 @@ decimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) binary and decimal types. */ void -decimal_real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode, +decimal_real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode, const REAL_VALUE_TYPE *a) { const struct real_format *fmt = REAL_MODE_FORMAT (mode); @@ -444,12 +453,13 @@ decimal_real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode, CROP_TRAILING_ZEROS, strip trailing zeros. Currently, not honoring DIGITS or CROP_TRAILING_ZEROS. */ -void decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, - size_t buf_size, - size_t digits ATTRIBUTE_UNUSED, - int crop_trailing_zeros ATTRIBUTE_UNUSED) +void +decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, + size_t buf_size, + size_t digits ATTRIBUTE_UNUSED, + int crop_trailing_zeros ATTRIBUTE_UNUSED) { - decimal128 *d128 = (decimal128*) r_orig->sig; + const decimal128 *const d128 = (const decimal128*) r_orig->sig; /* decimal128ToString requires space for at least 24 characters; Require two more for suffix. */ @@ -473,7 +483,7 @@ decimal_do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, if (subtract_p) decNumberSubtract (&dn, &dn2, &dn3, &set); - else + else decNumberAdd (&dn, &dn2, &dn3, &set); decimal_from_decnumber (r, &dn, &set); @@ -538,7 +548,7 @@ decimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; set.round = DEC_ROUND_DOWN; - decimal128ToNumber ((decimal128 *) a->sig, &dn2); + decimal128ToNumber ((const decimal128 *) a->sig, &dn2); decNumberToIntegralValue (&dn, &dn2, &set); decimal_from_decnumber (r, &dn, &set); @@ -557,7 +567,7 @@ decimal_real_to_integer (const REAL_VALUE_TYPE *r) decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; set.round = DEC_ROUND_DOWN; - decimal128ToNumber ((decimal128 *) r->sig, &dn); + decimal128ToNumber ((const decimal128 *) r->sig, &dn); decNumberToIntegralValue (&dn2, &dn, &set); decNumberZero (&dn3); @@ -584,62 +594,55 @@ decimal_real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, decContextDefault (&set, DEC_INIT_DECIMAL128); set.traps = 0; set.round = DEC_ROUND_DOWN; - decimal128ToNumber ((decimal128 *) r->sig, &dn); + decimal128ToNumber ((const decimal128 *) r->sig, &dn); decNumberToIntegralValue (&dn2, &dn, &set); decNumberZero (&dn3); decNumberRescale (&dn, &dn2, &dn3, &set); - /* Conver to REAL_VALUE_TYPE and call appropriate conversion + /* Convert to REAL_VALUE_TYPE and call appropriate conversion function. */ decNumberToString (&dn, string); real_from_string (&to, string); real_to_integer2 (plow, phigh, &to); } -/* Perform the decimal floating point operation described by COODE. - For a unary operation, leave OP1 NULL. This function returns true - if the result may be inexact due to loss of precision. */ +/* Perform the decimal floating point operation described by CODE. + For a unary operation, OP1 will be NULL. This function returns + true if the result may be inexact due to loss of precision. */ bool -decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode, +decimal_real_arithmetic (REAL_VALUE_TYPE *r, enum tree_code code, const REAL_VALUE_TYPE *op0, const REAL_VALUE_TYPE *op1) { - enum tree_code code = icode; - REAL_VALUE_TYPE a1; - REAL_VALUE_TYPE b1; + REAL_VALUE_TYPE a, b; - /* If either op is not a decimal, create a temporary decimal - versions. */ + /* If either operand is non-decimal, create temporaries. */ if (!op0->decimal) { - decimal_from_binary (&a1, op0); - op0 = &a1; + decimal_from_binary (&a, op0); + op0 = &a; } if (op1 && !op1->decimal) { - decimal_from_binary (&b1, op1); - op1 = &b1; + decimal_from_binary (&b, op1); + op1 = &b; } switch (code) { case PLUS_EXPR: - (void) decimal_do_add (r, op0, op1, 0); - break; + return decimal_do_add (r, op0, op1, 0); case MINUS_EXPR: - (void) decimal_do_add (r, op0, op1, 1); - break; + return decimal_do_add (r, op0, op1, 1); case MULT_EXPR: - (void) decimal_do_multiply (r, op0, op1); - break; + return decimal_do_multiply (r, op0, op1); case RDIV_EXPR: - (void) decimal_do_divide (r, op0, op1); - break; + return decimal_do_divide (r, op0, op1); case MIN_EXPR: if (op1->cl == rvc_nan) @@ -648,7 +651,7 @@ decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode, *r = *op0; else *r = *op1; - break; + return false; case MAX_EXPR: if (op1->cl == rvc_nan) @@ -657,43 +660,35 @@ decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode, *r = *op1; else *r = *op0; - break; + return false; case NEGATE_EXPR: { - decimal128 *d128; *r = *op0; - d128 = (decimal128 *) r->sig; - /* Flip high bit. */ - d128->bytes[0] ^= 1 << 7; + /* Flip sign bit. */ + decimal128FlipSign ((decimal128 *) r->sig); /* Keep sign field in sync. */ r->sign ^= 1; } - break; + return false; case ABS_EXPR: { - decimal128 *d128; *r = *op0; - d128 = (decimal128 *) r->sig; - /* Clear high bit. */ - d128->bytes[0] &= 0x7f; + /* Clear sign bit. */ + decimal128ClearSign ((decimal128 *) r->sig); /* Keep sign field in sync. */ r->sign = 0; } - break; + return false; case FIX_TRUNC_EXPR: decimal_do_fix_trunc (r, op0); - break; + return false; default: gcc_unreachable (); } - - /* FIXME: Indicate all operations as inexact for now due to unknown - working precision. */ - return true; } /* Fills R with the largest finite value representable in mode MODE. @@ -701,19 +696,19 @@ decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode, void decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) -{ - char *max; +{ + const char *max; switch (mode) { case SDmode: - max = (char *) "9.999999E96"; + max = "9.999999E96"; break; case DDmode: - max = (char *) "9.999999999999999E384"; + max = "9.999999999999999E384"; break; case TDmode: - max = (char *) "9.999999999999999999999999999999999E6144"; + max = "9.999999999999999999999999999999999E6144"; break; default: gcc_unreachable (); @@ -721,5 +716,5 @@ decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) decimal_real_from_string (r, max); if (sign) - r->sig[0] |= 0x80000000; + decimal128SetSign ((decimal128 *) r->sig, 1); }