X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fconfig%2Ffp-bit.c;fp=gcc%2Fconfig%2Ffp-bit.c;h=1cdac6ebecac1708e9cad742eb72719ebdace5ec;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=94e11e7e3d7070c4f172907ad4b749e18dc8f955;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/config/fp-bit.c b/gcc/config/fp-bit.c index 94e11e7e..1cdac6eb 100644 --- a/gcc/config/fp-bit.c +++ b/gcc/config/fp-bit.c @@ -1,37 +1,28 @@ /* This is a software floating point library which can be used for targets without hardware floating point. - Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001 - Free Software Foundation, Inc. - -This file 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 with other programs, and to distribute -those programs 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 another program.) - -This file 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 this program; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this library with other files, - some of which are compiled with GCC, to produce an executable, - this library does not by itself cause the resulting executable - to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. */ + Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, + 2004, 2005, 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 3, or (at your option) any later +version. + +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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ /* This implements IEEE 754 format arithmetic, but does not provide a mechanism for setting the rounding mode, or for generating or handling @@ -44,9 +35,11 @@ Boston, MA 02111-1307, USA. */ to one copy, then compile both copies and add them to libgcc.a. */ #include "tconfig.h" -#include "fp-bit.h" +#include "coretypes.h" +#include "tm.h" +#include "config/fp-bit.h" -/* The following macros can be defined to change the behaviour of this file: +/* The following macros can be defined to change the behavior of this file: FLOAT: Implement a `float', aka SFmode, fp library. If this is not defined, then this file implements a `double', aka DFmode, fp library. FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e. @@ -74,39 +67,47 @@ Boston, MA 02111-1307, USA. */ are referenced from within libc, since libgcc goes before and after the system library. */ +#ifdef DECLARE_LIBRARY_RENAMES + DECLARE_LIBRARY_RENAMES +#endif + #ifdef EXTENDED_FLOAT_STUBS -__truncxfsf2 (){ abort(); } -__extendsfxf2 (){ abort(); } -__addxf3 (){ abort(); } -__divxf3 (){ abort(); } -__eqxf2 (){ abort(); } -__extenddfxf2 (){ abort(); } -__gtxf2 (){ abort(); } -__lexf2 (){ abort(); } -__ltxf2 (){ abort(); } -__mulxf3 (){ abort(); } -__negxf2 (){ abort(); } -__nexf2 (){ abort(); } -__subxf3 (){ abort(); } -__truncxfdf2 (){ abort(); } - -__trunctfsf2 (){ abort(); } -__extendsftf2 (){ abort(); } -__addtf3 (){ abort(); } -__divtf3 (){ abort(); } -__eqtf2 (){ abort(); } -__extenddftf2 (){ abort(); } -__gttf2 (){ abort(); } -__letf2 (){ abort(); } -__lttf2 (){ abort(); } -__multf3 (){ abort(); } -__negtf2 (){ abort(); } -__netf2 (){ abort(); } -__subtf3 (){ abort(); } -__trunctfdf2 (){ abort(); } -__gexf2 (){ abort(); } -__fixxfsi (){ abort(); } -__floatsixf (){ abort(); } +extern void abort (void); +void __extendsfxf2 (void) { abort(); } +void __extenddfxf2 (void) { abort(); } +void __truncxfdf2 (void) { abort(); } +void __truncxfsf2 (void) { abort(); } +void __fixxfsi (void) { abort(); } +void __floatsixf (void) { abort(); } +void __addxf3 (void) { abort(); } +void __subxf3 (void) { abort(); } +void __mulxf3 (void) { abort(); } +void __divxf3 (void) { abort(); } +void __negxf2 (void) { abort(); } +void __eqxf2 (void) { abort(); } +void __nexf2 (void) { abort(); } +void __gtxf2 (void) { abort(); } +void __gexf2 (void) { abort(); } +void __lexf2 (void) { abort(); } +void __ltxf2 (void) { abort(); } + +void __extendsftf2 (void) { abort(); } +void __extenddftf2 (void) { abort(); } +void __trunctfdf2 (void) { abort(); } +void __trunctfsf2 (void) { abort(); } +void __fixtfsi (void) { abort(); } +void __floatsitf (void) { abort(); } +void __addtf3 (void) { abort(); } +void __subtf3 (void) { abort(); } +void __multf3 (void) { abort(); } +void __divtf3 (void) { abort(); } +void __negtf2 (void) { abort(); } +void __eqtf2 (void) { abort(); } +void __netf2 (void) { abort(); } +void __gttf2 (void) { abort(); } +void __getf2 (void) { abort(); } +void __letf2 (void) { abort(); } +void __lttf2 (void) { abort(); } #else /* !EXTENDED_FLOAT_STUBS, rest of file */ /* IEEE "special" number predicates */ @@ -122,6 +123,10 @@ __floatsixf (){ abort(); } const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; #elif defined L_thenan_df const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} }; +#elif defined L_thenan_tf +const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} }; +#elif defined TFLOAT +extern const fp_number_type __thenan_tf; #elif defined FLOAT extern const fp_number_type __thenan_sf; #else @@ -129,36 +134,38 @@ extern const fp_number_type __thenan_df; #endif INLINE -static fp_number_type * -nan (void) +static const fp_number_type * +makenan (void) { - /* Discard the const qualifier... */ -#ifdef FLOAT - return (fp_number_type *) (& __thenan_sf); +#ifdef TFLOAT + return & __thenan_tf; +#elif defined FLOAT + return & __thenan_sf; #else - return (fp_number_type *) (& __thenan_df); + return & __thenan_df; #endif } INLINE static int -isnan ( fp_number_type * x) +isnan (const fp_number_type *x) { - return x->class == CLASS_SNAN || x->class == CLASS_QNAN; + return __builtin_expect (x->class == CLASS_SNAN || x->class == CLASS_QNAN, + 0); } INLINE static int -isinf ( fp_number_type * x) +isinf (const fp_number_type * x) { - return x->class == CLASS_INFINITY; + return __builtin_expect (x->class == CLASS_INFINITY, 0); } #endif /* NO_NANS */ INLINE static int -iszero ( fp_number_type * x) +iszero (const fp_number_type * x) { return x->class == CLASS_ZERO; } @@ -170,23 +177,51 @@ flip_sign ( fp_number_type * x) x->sign = !x->sign; } -extern FLO_type pack_d ( fp_number_type * ); +/* Count leading zeroes in N. */ +INLINE +static int +clzusi (USItype n) +{ + extern int __clzsi2 (USItype); + if (sizeof (USItype) == sizeof (unsigned int)) + return __builtin_clz (n); + else if (sizeof (USItype) == sizeof (unsigned long)) + return __builtin_clzl (n); + else if (sizeof (USItype) == sizeof (unsigned long long)) + return __builtin_clzll (n); + else + return __clzsi2 (n); +} + +extern FLO_type pack_d (const fp_number_type * ); -#if defined(L_pack_df) || defined(L_pack_sf) +#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf) FLO_type -pack_d ( fp_number_type * src) +pack_d (const fp_number_type *src) { FLO_union_type dst; fractype fraction = src->fraction.ll; /* wasn't unsigned before? */ int sign = src->sign; int exp = 0; - if (isnan (src)) + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src))) + { + /* We can't represent these values accurately. By using the + largest possible magnitude, we guarantee that the conversion + of infinity is at least as big as any finite number. */ + exp = EXPMAX; + fraction = ((fractype) 1 << FRACBITS) - 1; + } + else if (isnan (src)) { exp = EXPMAX; if (src->class == CLASS_QNAN || 1) { +#ifdef QUIET_NAN_NEGATED + fraction |= QUIET_NAN - 1; +#else fraction |= QUIET_NAN; +#endif } } else if (isinf (src)) @@ -205,8 +240,15 @@ pack_d ( fp_number_type * src) } else { - if (src->normal_exp < NORMAL_EXPMIN) + if (__builtin_expect (src->normal_exp < NORMAL_EXPMIN, 0)) { +#ifdef NO_DENORMALS + /* Go straight to a zero representation if denormals are not + supported. The denormal handling would be harmless but + isn't unnecessary. */ + exp = 0; + fraction = 0; +#else /* NO_DENORMALS */ /* This number's exponent is too low to fit into the bits available in the number, so we'll store 0 in the exponent and shift the fraction to the right to make up for it. */ @@ -242,8 +284,10 @@ pack_d ( fp_number_type * src) exp += 1; } fraction >>= NGARDS; +#endif /* NO_DENORMALS */ } - else if (src->normal_exp > EXPBIAS) + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) + && __builtin_expect (src->normal_exp > EXPBIAS, 0)) { exp = EXPMAX; fraction = 0; @@ -251,25 +295,35 @@ pack_d ( fp_number_type * src) else { exp = src->normal_exp + EXPBIAS; - /* IF the gard bits are the all zero, but the first, then we're - half way between two numbers, choose the one which makes the - lsb of the answer 0. */ - if ((fraction & GARDMASK) == GARDMSB) - { - if (fraction & (1 << NGARDS)) - fraction += GARDROUND + 1; - } - else + if (!ROUND_TOWARDS_ZERO) { - /* Add a one to the guards to round up */ - fraction += GARDROUND; + /* IF the gard bits are the all zero, but the first, then we're + half way between two numbers, choose the one which makes the + lsb of the answer 0. */ + if ((fraction & GARDMASK) == GARDMSB) + { + if (fraction & (1 << NGARDS)) + fraction += GARDROUND + 1; + } + else + { + /* Add a one to the guards to round up */ + fraction += GARDROUND; + } + if (fraction >= IMPLICIT_2) + { + fraction >>= 1; + exp += 1; + } } - if (fraction >= IMPLICIT_2) + fraction >>= NGARDS; + + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX) { - fraction >>= 1; - exp += 1; + /* Saturate on overflow. */ + exp = EXPMAX; + fraction = ((fractype) 1 << FRACBITS) - 1; } - fraction >>= NGARDS; } } @@ -281,24 +335,110 @@ pack_d ( fp_number_type * src) dst.bits.exp = exp; dst.bits.sign = sign; #else +# if defined TFLOAT && defined HALFFRACBITS + { + halffractype high, low, unity; + int lowsign, lowexp; + + unity = (halffractype) 1 << HALFFRACBITS; + + /* Set HIGH to the high double's significand, masking out the implicit 1. + Set LOW to the low double's full significand. */ + high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1); + low = fraction & (unity * 2 - 1); + + /* Get the initial sign and exponent of the low double. */ + lowexp = exp - HALFFRACBITS - 1; + lowsign = sign; + + /* HIGH should be rounded like a normal double, making |LOW| <= + 0.5 ULP of HIGH. Assume round-to-nearest. */ + if (exp < EXPMAX) + if (low > unity || (low == unity && (high & 1) == 1)) + { + /* Round HIGH up and adjust LOW to match. */ + high++; + if (high == unity) + { + /* May make it infinite, but that's OK. */ + high = 0; + exp++; + } + low = unity * 2 - low; + lowsign ^= 1; + } + + high |= (halffractype) exp << HALFFRACBITS; + high |= (halffractype) sign << (HALFFRACBITS + EXPBITS); + + if (exp == EXPMAX || exp == 0 || low == 0) + low = 0; + else + { + while (lowexp > 0 && low < unity) + { + low <<= 1; + lowexp--; + } + + if (lowexp <= 0) + { + halffractype roundmsb, round; + int shift; + + shift = 1 - lowexp; + roundmsb = (1 << (shift - 1)); + round = low & ((roundmsb << 1) - 1); + + low >>= shift; + lowexp = 0; + + if (round > roundmsb || (round == roundmsb && (low & 1) == 1)) + { + low++; + if (low == unity) + /* LOW rounds up to the smallest normal number. */ + lowexp++; + } + } + + low &= unity - 1; + low |= (halffractype) lowexp << HALFFRACBITS; + low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS); + } + dst.value_raw = ((fractype) high << HALFSHIFT) | low; + } +# else dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1); dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS; dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS); +# endif #endif #if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) +#ifdef TFLOAT + { + qrtrfractype tmp1 = dst.words[0]; + qrtrfractype tmp2 = dst.words[1]; + dst.words[0] = dst.words[3]; + dst.words[1] = dst.words[2]; + dst.words[2] = tmp2; + dst.words[3] = tmp1; + } +#else { halffractype tmp = dst.words[0]; dst.words[0] = dst.words[1]; dst.words[1] = tmp; } +#endif #endif return dst.value; } #endif -#if defined(L_unpack_df) || defined(L_unpack_sf) +#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf) void unpack_d (FLO_union_type * src, fp_number_type * dst) { @@ -312,8 +452,15 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) #if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT) FLO_union_type swapped; +#ifdef TFLOAT + swapped.words[0] = src->words[3]; + swapped.words[1] = src->words[2]; + swapped.words[2] = src->words[1]; + swapped.words[3] = src->words[0]; +#else swapped.words[0] = src->words[1]; swapped.words[1] = src->words[0]; +#endif src = &swapped; #endif @@ -322,9 +469,54 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) exp = src->bits.exp; sign = src->bits.sign; #else - fraction = src->value_raw & ((((fractype)1) << FRACBITS) - (fractype)1); +# if defined TFLOAT && defined HALFFRACBITS + { + halffractype high, low; + + high = src->value_raw >> HALFSHIFT; + low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1); + + fraction = high & ((((fractype)1) << HALFFRACBITS) - 1); + fraction <<= FRACBITS - HALFFRACBITS; + exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); + sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1; + + if (exp != EXPMAX && exp != 0 && low != 0) + { + int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1); + int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1; + int shift; + fractype xlow; + + xlow = low & ((((fractype)1) << HALFFRACBITS) - 1); + if (lowexp) + xlow |= (((halffractype)1) << HALFFRACBITS); + else + lowexp = 1; + shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp); + if (shift > 0) + xlow <<= shift; + else if (shift < 0) + xlow >>= -shift; + if (sign == lowsign) + fraction += xlow; + else if (fraction >= xlow) + fraction -= xlow; + else + { + /* The high part is a power of two but the full number is lower. + This code will leave the implicit 1 in FRACTION, but we'd + have added that below anyway. */ + fraction = (((fractype) 1 << FRACBITS) - xlow) << 1; + exp--; + } + } + } +# else + fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1); exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1); sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1; +# endif #endif dst->sign = sign; @@ -342,7 +534,7 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) } else { - /* Zero exponent with non zero fraction - it's denormalized, + /* Zero exponent with nonzero fraction - it's denormalized, so there isn't a leading implicit one - we'll shift it so it gets one. */ dst->normal_exp = exp - EXPBIAS + 1; @@ -359,7 +551,8 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) dst->fraction.ll = fraction; } } - else if (exp == EXPMAX) + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) + && __builtin_expect (exp == EXPMAX, 0)) { /* Huge exponent*/ if (fraction == 0) @@ -369,8 +562,12 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) } else { - /* Non zero fraction, means nan */ + /* Nonzero fraction, means nan */ +#ifdef QUIET_NAN_NEGATED + if ((fraction & QUIET_NAN) == 0) +#else if (fraction & QUIET_NAN) +#endif { dst->class = CLASS_QNAN; } @@ -392,8 +589,8 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) } #endif /* L_unpack_df || L_unpack_sf */ -#if defined(L_addsub_sf) || defined(L_addsub_df) -static fp_number_type * +#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf) +static const fp_number_type * _fpadd_parts (fp_number_type * a, fp_number_type * b, fp_number_type * tmp) @@ -418,7 +615,7 @@ _fpadd_parts (fp_number_type * a, { /* Adding infinities with opposite signs yields a NaN. */ if (isinf (b) && a->sign != b->sign) - return nan (); + return makenan (); return a; } if (isinf (b)) @@ -444,6 +641,7 @@ _fpadd_parts (fp_number_type * a, they're the same */ { int diff; + int sdiff; a_normal_exp = a->normal_exp; b_normal_exp = b->normal_exp; @@ -451,21 +649,21 @@ _fpadd_parts (fp_number_type * a, b_fraction = b->fraction.ll; diff = a_normal_exp - b_normal_exp; + sdiff = diff; if (diff < 0) diff = -diff; if (diff < FRAC_NBITS) { - /* ??? This does shifts one bit at a time. Optimize. */ - while (a_normal_exp > b_normal_exp) + if (sdiff > 0) { - b_normal_exp++; - LSHIFT (b_fraction); + b_normal_exp += diff; + LSHIFT (b_fraction, diff); } - while (b_normal_exp > a_normal_exp) + else if (sdiff < 0) { - a_normal_exp++; - LSHIFT (a_fraction); + a_normal_exp += diff; + LSHIFT (a_fraction, diff); } } else @@ -526,11 +724,10 @@ _fpadd_parts (fp_number_type * a, if (tmp->fraction.ll >= IMPLICIT_2) { - LSHIFT (tmp->fraction.ll); + LSHIFT (tmp->fraction.ll, 1); tmp->normal_exp++; } return tmp; - } FLO_type @@ -539,7 +736,7 @@ add (FLO_type arg_a, FLO_type arg_b) fp_number_type a; fp_number_type b; fp_number_type tmp; - fp_number_type *res; + const fp_number_type *res; FLO_union_type au, bu; au.value = arg_a; @@ -559,7 +756,7 @@ sub (FLO_type arg_a, FLO_type arg_b) fp_number_type a; fp_number_type b; fp_number_type tmp; - fp_number_type *res; + const fp_number_type *res; FLO_union_type au, bu; au.value = arg_a; @@ -576,8 +773,8 @@ sub (FLO_type arg_a, FLO_type arg_b) } #endif /* L_addsub_sf || L_addsub_df */ -#if defined(L_mul_sf) || defined(L_mul_df) -static INLINE fp_number_type * +#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf) +static inline __attribute__ ((__always_inline__)) const fp_number_type * _fpmul_parts ( fp_number_type * a, fp_number_type * b, fp_number_type * tmp) @@ -598,7 +795,7 @@ _fpmul_parts ( fp_number_type * a, if (isinf (a)) { if (iszero (b)) - return nan (); + return makenan (); a->sign = a->sign != b->sign; return a; } @@ -606,7 +803,7 @@ _fpmul_parts ( fp_number_type * a, { if (iszero (a)) { - return nan (); + return makenan (); } b->sign = a->sign != b->sign; return b; @@ -625,7 +822,7 @@ _fpmul_parts ( fp_number_type * a, /* Calculate the mantissa by multiplying both numbers to get a twice-as-wide number. */ { -#if defined(NO_DI_MODE) +#if defined(NO_DI_MODE) || defined(TFLOAT) { fractype x = a->fraction.ll; fractype ylow = b->fraction.ll; @@ -688,13 +885,9 @@ _fpmul_parts ( fp_number_type * a, #endif } - tmp->normal_exp = a->normal_exp + b->normal_exp; + tmp->normal_exp = a->normal_exp + b->normal_exp + + FRAC_NBITS - (FRACBITS + NGARDS); tmp->sign = a->sign != b->sign; -#ifdef FLOAT - tmp->normal_exp += 2; /* ??????????????? */ -#else - tmp->normal_exp += 4; /* ??????????????? */ -#endif while (high >= IMPLICIT_2) { tmp->normal_exp++; @@ -714,32 +907,28 @@ _fpmul_parts ( fp_number_type * a, high |= 1; low <<= 1; } - /* rounding is tricky. if we only round if it won't make us round later. */ -#if 0 - if (low & FRACHIGH2) - { - if (((high & GARDMASK) != GARDMSB) - && (((high + 1) & GARDMASK) == GARDMSB)) - { - /* don't round, it gets done again later. */ - } - else - { - high++; - } - } -#endif - if ((high & GARDMASK) == GARDMSB) + + if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB) { if (high & (1 << NGARDS)) { - /* half way, so round to even */ - high += GARDROUND + 1; + /* Because we're half way, we would round to even by adding + GARDROUND + 1, except that's also done in the packing + function, and rounding twice will lose precision and cause + the result to be too far off. Example: 32-bit floats with + bit patterns 0xfff * 0x3f800400 ~= 0xfff (less than 0.5ulp + off), not 0x1000 (more than 0.5ulp off). */ } else if (low) { - /* but we really weren't half way */ + /* We're a further than half way by a small amount corresponding + to the bits set in "low". Knowing that, we round here and + not in pack_d, because there we don't have "low" available + anymore. */ high += GARDROUND + 1; + + /* Avoid further rounding in pack_d. */ + high &= ~(fractype) GARDMASK; } } tmp->fraction.ll = high; @@ -753,7 +942,7 @@ multiply (FLO_type arg_a, FLO_type arg_b) fp_number_type a; fp_number_type b; fp_number_type tmp; - fp_number_type *res; + const fp_number_type *res; FLO_union_type au, bu; au.value = arg_a; @@ -766,10 +955,10 @@ multiply (FLO_type arg_a, FLO_type arg_b) return pack_d (res); } -#endif /* L_mul_sf || L_mul_df */ +#endif /* L_mul_sf || L_mul_df || L_mul_tf */ -#if defined(L_div_sf) || defined(L_div_df) -static INLINE fp_number_type * +#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf) +static inline __attribute__ ((__always_inline__)) const fp_number_type * _fpdiv_parts (fp_number_type * a, fp_number_type * b) { @@ -792,7 +981,7 @@ _fpdiv_parts (fp_number_type * a, if (isinf (a) || iszero (a)) { if (a->class == b->class) - return nan (); + return makenan (); return a; } @@ -839,17 +1028,25 @@ _fpdiv_parts (fp_number_type * a, numerator *= 2; } - if ((quotient & GARDMASK) == GARDMSB) + if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB) { if (quotient & (1 << NGARDS)) { - /* half way, so round to even */ - quotient += GARDROUND + 1; + /* Because we're half way, we would round to even by adding + GARDROUND + 1, except that's also done in the packing + function, and rounding twice will lose precision and cause + the result to be too far off. */ } else if (numerator) { - /* but we really weren't half way, more bits exist */ + /* We're a further than half way by the small amount + corresponding to the bits set in "numerator". Knowing + that, we round here and not in pack_d, because there we + don't have "numerator" available anymore. */ quotient += GARDROUND + 1; + + /* Avoid further rounding in pack_d. */ + quotient &= ~(fractype) GARDMASK; } } @@ -863,7 +1060,7 @@ divide (FLO_type arg_a, FLO_type arg_b) { fp_number_type a; fp_number_type b; - fp_number_type *res; + const fp_number_type *res; FLO_union_type au, bu; au.value = arg_a; @@ -878,7 +1075,8 @@ divide (FLO_type arg_a, FLO_type arg_b) } #endif /* L_div_sf || L_div_df */ -#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) +#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \ + || defined(L_fpcmp_parts_tf) /* according to the demo, fpcmp returns a comparison with 0... thus a -1 a==b -> 0 @@ -889,7 +1087,7 @@ int __fpcmp_parts (fp_number_type * a, fp_number_type * b) { #if 0 - /* either nan -> unordered. Must be checked outside of this routine. */ + /* either nan -> unordered. Must be checked outside of this routine. */ if (isnan (a) && isnan (b)) { return 1; /* still unordered! */ @@ -909,11 +1107,11 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b) -------+--------+-------- -inf(1)| a>b(1) | a==b(0) -------+--------+-------- - So since unordered must be non zero, just line up the columns... + So since unordered must be nonzero, just line up the columns... */ return b->sign - a->sign; } - /* but not both... */ + /* but not both... */ if (isinf (a)) { return a->sign ? -1 : 1; @@ -934,7 +1132,7 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b) { return a->sign ? -1 : 1; } - /* now both are "normal". */ + /* now both are "normal". */ if (a->sign != b->sign) { /* opposite signs */ @@ -949,7 +1147,7 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b) { return a->sign ? 1 : -1; } - /* same exponents; check size. */ + /* same exponents; check size. */ if (a->fraction.ll > b->fraction.ll) { return a->sign ? -1 : 1; @@ -958,12 +1156,12 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b) { return a->sign ? 1 : -1; } - /* after all that, they're equal. */ + /* after all that, they're equal. */ return 0; } #endif -#if defined(L_compare_sf) || defined(L_compare_df) +#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf) CMPtype compare (FLO_type arg_a, FLO_type arg_b) { @@ -985,7 +1183,7 @@ compare (FLO_type arg_a, FLO_type arg_b) /* These should be optimized for their specific tasks someday. */ -#if defined(L_eq_sf) || defined(L_eq_df) +#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf) CMPtype _eq_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1006,7 +1204,7 @@ _eq_f2 (FLO_type arg_a, FLO_type arg_b) } #endif /* L_eq_sf || L_eq_df */ -#if defined(L_ne_sf) || defined(L_ne_df) +#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf) CMPtype _ne_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1027,7 +1225,7 @@ _ne_f2 (FLO_type arg_a, FLO_type arg_b) } #endif /* L_ne_sf || L_ne_df */ -#if defined(L_gt_sf) || defined(L_gt_df) +#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf) CMPtype _gt_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1048,7 +1246,7 @@ _gt_f2 (FLO_type arg_a, FLO_type arg_b) } #endif /* L_gt_sf || L_gt_df */ -#if defined(L_ge_sf) || defined(L_ge_df) +#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf) CMPtype _ge_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1068,7 +1266,7 @@ _ge_f2 (FLO_type arg_a, FLO_type arg_b) } #endif /* L_ge_sf || L_ge_df */ -#if defined(L_lt_sf) || defined(L_lt_df) +#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf) CMPtype _lt_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1089,7 +1287,7 @@ _lt_f2 (FLO_type arg_a, FLO_type arg_b) } #endif /* L_lt_sf || L_lt_df */ -#if defined(L_le_sf) || defined(L_le_df) +#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf) CMPtype _le_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1110,7 +1308,9 @@ _le_f2 (FLO_type arg_a, FLO_type arg_b) } #endif /* L_le_sf || L_le_df */ -#if defined(L_unord_sf) || defined(L_unord_df) +#endif /* ! US_SOFTWARE_GOFAST */ + +#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf) CMPtype _unord_f2 (FLO_type arg_a, FLO_type arg_b) { @@ -1128,9 +1328,7 @@ _unord_f2 (FLO_type arg_a, FLO_type arg_b) } #endif /* L_unord_sf || L_unord_df */ -#endif /* ! US_SOFTWARE_GOFAST */ - -#if defined(L_si_to_sf) || defined(L_si_to_df) +#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf) FLO_type si_to_float (SItype arg_a) { @@ -1144,6 +1342,8 @@ si_to_float (SItype arg_a) } else { + USItype uarg; + int shift; in.normal_exp = FRACBITS + NGARDS; if (in.sign) { @@ -1153,22 +1353,24 @@ si_to_float (SItype arg_a) { return (FLO_type)(- MAX_SI_INT - 1); } - in.fraction.ll = (-arg_a); + uarg = (-arg_a); } else - in.fraction.ll = arg_a; + uarg = arg_a; - while (in.fraction.ll < (1LL << (FRACBITS + NGARDS))) + in.fraction.ll = uarg; + shift = clzusi (uarg) - (BITS_PER_SI - 1 - FRACBITS - NGARDS); + if (shift > 0) { - in.fraction.ll <<= 1; - in.normal_exp -= 1; + in.fraction.ll <<= shift; + in.normal_exp -= shift; } } return pack_d (&in); } #endif /* L_si_to_sf || L_si_to_df */ -#if defined(L_usi_to_sf) || defined(L_usi_to_df) +#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf) FLO_type usi_to_float (USItype arg_a) { @@ -1181,26 +1383,30 @@ usi_to_float (USItype arg_a) } else { + int shift; in.class = CLASS_NUMBER; in.normal_exp = FRACBITS + NGARDS; in.fraction.ll = arg_a; - while (in.fraction.ll > (1LL << (FRACBITS + NGARDS))) - { - in.fraction.ll >>= 1; - in.normal_exp += 1; - } - while (in.fraction.ll < (1LL << (FRACBITS + NGARDS))) + shift = clzusi (arg_a) - (BITS_PER_SI - 1 - FRACBITS - NGARDS); + if (shift < 0) + { + fractype guard = in.fraction.ll & (((fractype)1 << -shift) - 1); + in.fraction.ll >>= -shift; + in.fraction.ll |= (guard != 0); + in.normal_exp -= shift; + } + else if (shift > 0) { - in.fraction.ll <<= 1; - in.normal_exp -= 1; + in.fraction.ll <<= shift; + in.normal_exp -= shift; } } return pack_d (&in); } #endif -#if defined(L_sf_to_si) || defined(L_df_to_si) +#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si) SItype float_to_si (FLO_type arg_a) { @@ -1215,7 +1421,7 @@ float_to_si (FLO_type arg_a) return 0; if (isnan (&a)) return 0; - /* get reasonable MAX_SI_INT... */ + /* get reasonable MAX_SI_INT... */ if (isinf (&a)) return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; /* it is a number, but a small one */ @@ -1228,8 +1434,8 @@ float_to_si (FLO_type arg_a) } #endif /* L_sf_to_si || L_df_to_si */ -#if defined(L_sf_to_usi) || defined(L_df_to_usi) -#ifdef US_SOFTWARE_GOFAST +#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi) +#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi) /* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines, we also define them for GOFAST because the ones in libgcc2.c have the wrong names and I'd rather define these here and keep GOFAST CYG-LOC's @@ -1252,7 +1458,7 @@ float_to_usi (FLO_type arg_a) /* it is a negative number */ if (a.sign) return 0; - /* get reasonable MAX_USI_INT... */ + /* get reasonable MAX_USI_INT... */ if (isinf (&a)) return MAX_USI_INT; /* it is a number, but a small one */ @@ -1268,7 +1474,7 @@ float_to_usi (FLO_type arg_a) #endif /* US_SOFTWARE_GOFAST */ #endif /* L_sf_to_usi || L_df_to_usi */ -#if defined(L_negate_sf) || defined(L_negate_df) +#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf) FLO_type negate (FLO_type arg_a) { @@ -1324,6 +1530,21 @@ sf_to_df (SFtype arg_a) } #endif /* L_sf_to_df */ +#if defined(L_sf_to_tf) && defined(TMODES) +TFtype +sf_to_tf (SFtype arg_a) +{ + fp_number_type in; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + return __make_tp (in.class, in.sign, in.normal_exp, + ((UTItype) in.fraction.ll) << F_T_BITOFF); +} +#endif /* L_sf_to_df */ + #endif /* ! FLOAT_ONLY */ #endif /* FLOAT */ @@ -1367,5 +1588,84 @@ df_to_sf (DFtype arg_a) } #endif /* L_df_to_sf */ +#if defined(L_df_to_tf) && defined(TMODES) \ + && !defined(FLOAT) && !defined(TFLOAT) +TFtype +df_to_tf (DFtype arg_a) +{ + fp_number_type in; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + return __make_tp (in.class, in.sign, in.normal_exp, + ((UTItype) in.fraction.ll) << D_T_BITOFF); +} +#endif /* L_sf_to_df */ + +#ifdef TFLOAT +#if defined(L_make_tf) +TFtype +__make_tp(fp_class_type class, + unsigned int sign, + int exp, + UTItype frac) +{ + fp_number_type in; + + in.class = class; + in.sign = sign; + in.normal_exp = exp; + in.fraction.ll = frac; + return pack_d (&in); +} +#endif /* L_make_tf */ + +#if defined(L_tf_to_df) +DFtype +tf_to_df (TFtype arg_a) +{ + fp_number_type in; + UDItype sffrac; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + sffrac = in.fraction.ll >> D_T_BITOFF; + + /* We set the lowest guard bit in SFFRAC if we discarded any non + zero bits. */ + if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0) + sffrac |= 1; + + return __make_dp (in.class, in.sign, in.normal_exp, sffrac); +} +#endif /* L_tf_to_df */ + +#if defined(L_tf_to_sf) +SFtype +tf_to_sf (TFtype arg_a) +{ + fp_number_type in; + USItype sffrac; + FLO_union_type au; + + au.value = arg_a; + unpack_d (&au, &in); + + sffrac = in.fraction.ll >> F_T_BITOFF; + + /* We set the lowest guard bit in SFFRAC if we discarded any non + zero bits. */ + if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0) + sffrac |= 1; + + return __make_fp (in.class, in.sign, in.normal_exp, sffrac); +} +#endif /* L_tf_to_sf */ +#endif /* TFLOAT */ + #endif /* ! FLOAT */ #endif /* !EXTENDED_FLOAT_STUBS */