diff options
Diffstat (limited to 'newlib/libc/machine/powerpc/strtosfix32.c')
-rw-r--r-- | newlib/libc/machine/powerpc/strtosfix32.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/newlib/libc/machine/powerpc/strtosfix32.c b/newlib/libc/machine/powerpc/strtosfix32.c new file mode 100644 index 000000000..0f2ded6f7 --- /dev/null +++ b/newlib/libc/machine/powerpc/strtosfix32.c @@ -0,0 +1,100 @@ +#include <_ansi.h> +#include <limits.h> +#include <errno.h> +#include <stdlib.h> +#include <reent.h> +#include "vfieeefp.h" + +/* + * Convert a string to a fixed-point (sign + 31-bits) value. + * + * Ignores `locale' stuff. + */ +__int32_t +_DEFUN (_strtosfix32_r, (rptr, nptr, endptr), + struct _reent *rptr _AND + _CONST char *nptr _AND + char **endptr) +{ + union double_union dbl; + int exp, negexp, sign; + unsigned long tmp, tmp2; + long result = 0; + + dbl.d = _strtod_r (rptr, nptr, endptr); + + /* treat NAN as domain error, +/- infinity as saturation */ + if (!finite(dbl.d)) + { + if (isnan (dbl.d)) + { + rptr->_errno = EDOM; + return 0; + } + rptr->_errno = ERANGE; + if (word0(dbl) & Sign_bit) + return LONG_MIN; + return LONG_MAX; + } + + /* check for normal saturation */ + if (dbl.d >= 1.0) + { + rptr->_errno = ERANGE; + return LONG_MAX; + } + else if (dbl.d < -1.0) + { + rptr->_errno = ERANGE; + return LONG_MIN; + } + + /* otherwise we have normal number in range */ + + /* strip off sign and exponent */ + sign = word0(dbl) & Sign_bit; + exp = ((word0(dbl) & Exp_mask) >> Exp_shift) - Bias; + negexp = -exp; + if (negexp > 31) + return 0; + word0(dbl) &= ~(Exp_mask | Sign_bit); + /* add in implicit normalized bit */ + word0(dbl) |= Exp_msk1; + /* shift so result is contained in single word */ + tmp = word0(dbl) << Ebits; + tmp |= ((unsigned long)word1(dbl) >> (32 - Ebits)); + if (negexp != 0) + { + /* perform rounding */ + tmp2 = tmp + (1 << (negexp - 1)); + result = (long)(tmp2 >> negexp); + /* check if rounding caused carry bit which must be added into result */ + if (tmp2 < tmp) + result |= (1 << (32 - negexp)); + /* check if positive saturation has occurred because of rounding */ + if (!sign && result < 0) + { + rptr->_errno = ERANGE; + return LONG_MAX; + } + } + else + { + /* we have -1.0, no rounding necessary */ + return LONG_MIN; + } + + return sign ? -result : result; +} + +#ifndef _REENT_ONLY + +__int32_t +_DEFUN (strtosfix32, (s, ptr, base), + _CONST char *s _AND + char **ptr) +{ + return _strtosfix32_r (_REENT, s, ptr); +} + +#endif |