diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2002-08-17 09:57:20 +0400 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2002-08-17 09:57:20 +0400 |
commit | 936b520f8eac458e26623632280b0f34cb8abc17 (patch) | |
tree | f4d9c0b7b2bafdca16e643eb2060d48abb5e5315 /newlib/libc/machine/powerpc/strtosfix64.c | |
parent | ad5527663ef5d01f531b4d4b23390c7566c93ee2 (diff) |
2002-08-17 Jeff Johnston <jjohnstn@redhat.com>
* configure.host: Add powerpc*-*-eabispe* configuration.
* libc/machine/powerpc/atosfix16.c: New fixed-point conversion file.
* libc/machine/powerpc/atosfix32.c: Ditto.
* libc/machine/powerpc/atosfix64.c: Ditto.
* libc/machine/powerpc/atoufix16.c: Ditto.
* libc/machine/powerpc/atoufix32.c: Ditto.
* libc/machine/powerpc/atoufix64.c: Ditto.
* libc/machine/powerpc/fix64.h: Ditto.
* libc/machine/powerpc/simdldtoa.c: Ditto.
* libc/machine/powerpc/strtosfix16.c: Ditto.
* libc/machine/powerpc/strtosfix32.c: Ditto.
* libc/machine/powerpc/strtosfix64.c: Ditto.
* libc/machine/powerpc/strtoufix16.c: Ditto.
* libc/machine/powerpc/strtoufix32.c: Ditto.
* libc/machine/powerpc/strtoufix64.c: Ditto.
* libc/machine/powerpc/ufix64toa.c: Ditto.
* libc/machine/powerpc/configure.in: Add check for
powerpc*-eabispe and add fixed-point conversion functions.
* libc/machine/powerpc/configure: Regenerated.
* libc/machine/powerpc/vfprintf.c[__SPE__]: Add support for
%r and %R format specifiers which handle fixed-point data.
* libc/machine/powerpc/vfscanf.c[__SPE__]: Ditto.
* libc/machine/powerpc/machine/stdlib.h[__SPE__]: Add fixed-point
function prototypes.
Diffstat (limited to 'newlib/libc/machine/powerpc/strtosfix64.c')
-rw-r--r-- | newlib/libc/machine/powerpc/strtosfix64.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/newlib/libc/machine/powerpc/strtosfix64.c b/newlib/libc/machine/powerpc/strtosfix64.c new file mode 100644 index 000000000..d0fa769d9 --- /dev/null +++ b/newlib/libc/machine/powerpc/strtosfix64.c @@ -0,0 +1,113 @@ +#include <_ansi.h> +#include <limits.h> +#include <errno.h> +#include <stdlib.h> +#include <reent.h> +#include "fix64.h" + +/* + * Convert a string to a fixed-point (sign + 63-bits) value. + * + * Ignores `locale' stuff. + */ +__int64_t +_DEFUN (_strtosfix64_r, (rptr, nptr, endptr), + struct _reent *rptr _AND + _CONST char *nptr _AND + char **endptr) +{ + union long_double_union ldbl; + int exp, negexp, sign, ld_type; + __uint64_t tmp, tmp2; + __int64_t result = 0; + + init(ldbl); + + _simdstrtold ((char *)nptr, endptr, &ldbl); + + /* treat NAN as domain error, +/- infinity as saturation */ + ld_type = _simdldcheck (&ldbl.ld); + if (ld_type != 0) + { + if (ld_type == 1) + { + rptr->_errno = EDOM; + return 0; + } + rptr->_errno = ERANGE; + if (word0(ldbl) & Sign_bit) + return LONG_LONG_MIN; + return LONG_LONG_MAX; + } + + /* strip off sign and exponent */ + sign = word0(ldbl) & Sign_bit; + exp = ((word0(ldbl) & Exp_mask) >> Exp_shift) - Bias; + negexp = -exp; + if (negexp > 63) + return 0; + word0(ldbl) &= ~(Exp_mask | Sign_bit); + /* add in implicit normalized bit */ + word0(ldbl) |= Exp_msk1; + /* shift so result is contained in single word */ + tmp = word0(ldbl) << Ebits; + tmp |= ((unsigned long)word1(ldbl) >> (32 - Ebits)); + tmp <<= 32; + if (Ebits < 32) + tmp |= ((unsigned long)word1(ldbl) << Ebits); + tmp |= ((unsigned long)word2(ldbl) >> (32 - Ebits)); + + /* check for saturation */ + if (sign) + { + if (exp > 0 || (exp == 0 && tmp != 0x8000000000000000LL)) + { + rptr->_errno = ERANGE; + return LONG_LONG_MIN; + } + } + else + { + if (exp >= 0) + { + rptr->_errno = ERANGE; + return LONG_LONG_MAX; + } + } + + /* otherwise we have normal number in range */ + if (negexp != 0) + { + /* perform rounding */ + tmp2 = tmp + (1 << (negexp - 1)); + result = (long long)(tmp2 >> negexp); + /* check if rounding caused carry bit which must be added into result */ + if (tmp2 < tmp) + result |= (1 << (64 - negexp)); + /* check if positive saturation has occurred because of rounding */ + if (!sign && result < 0) + { + rptr->_errno = ERANGE; + return LONG_LONG_MAX; + } + } + else + { + /* we have -1.0, no rounding necessary */ + return LONG_LONG_MIN; + } + + return sign ? -result : result; +} + +#ifndef _REENT_ONLY + +__int64_t +_DEFUN (strtosfix64, (s, ptr, base), + _CONST char *s _AND + char **ptr) +{ + return _strtosfix64_r (_REENT, s, ptr); +} + +#endif |