Cygwin: Add new APIs tc[gs]etwinsize()
[newlib-cygwin.git] / newlib / libc / machine / powerpc / strtosfix64.c
blob9da3ffaee2103d4e8447723c0c3c3a2ac00b777c
1 #ifdef __SPE__
3 #include <_ansi.h>
4 #include <limits.h>
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <reent.h>
8 #include "fix64.h"
11 * Convert a string to a fixed-point (sign + 63-bits) value.
13 * Ignores `locale' stuff.
15 __int64_t
16 _strtosfix64_r (struct _reent *rptr,
17 const char *nptr,
18 char **endptr)
20 union long_double_union ldbl;
21 int exp, negexp, sign, ld_type;
22 __uint64_t tmp, tmp2;
23 __int64_t result = 0;
25 init(ldbl);
27 _simdstrtold ((char *)nptr, endptr, &ldbl);
29 /* treat NAN as domain error, +/- infinity as saturation */
30 ld_type = _simdldcheck (&ldbl);
31 if (ld_type != 0)
33 if (ld_type == 1)
35 _REENT_ERRNO(rptr) = EDOM;
36 return 0;
38 _REENT_ERRNO(rptr) = ERANGE;
39 if (word0(ldbl) & Sign_bit)
40 return LONG_LONG_MIN;
41 return LONG_LONG_MAX;
44 /* strip off sign and exponent */
45 sign = word0(ldbl) & Sign_bit;
46 exp = ((word0(ldbl) & Exp_mask) >> Exp_shift) - Bias;
47 negexp = -exp;
48 if (negexp > 63)
49 return 0;
50 word0(ldbl) &= ~(Exp_mask | Sign_bit);
51 /* add in implicit normalized bit */
52 word0(ldbl) |= Exp_msk1;
53 /* shift so result is contained in single word */
54 tmp = word0(ldbl) << Ebits;
55 tmp |= ((unsigned long)word1(ldbl) >> (32 - Ebits));
56 tmp <<= 32;
57 if (Ebits < 32)
58 tmp |= ((unsigned long)word1(ldbl) << Ebits);
59 tmp |= ((unsigned long)word2(ldbl) >> (32 - Ebits));
61 /* check for saturation */
62 if (sign)
64 if (exp > 0 || (exp == 0 && tmp != 0x8000000000000000LL))
66 _REENT_ERRNO(rptr) = ERANGE;
67 return LONG_LONG_MIN;
70 else
72 if (exp >= 0)
74 _REENT_ERRNO(rptr) = ERANGE;
75 return LONG_LONG_MAX;
79 /* otherwise we have normal number in range */
80 if (negexp != 0)
82 /* perform rounding */
83 tmp2 = tmp + (1 << (negexp - 1));
84 result = (long long)(tmp2 >> negexp);
85 /* check if rounding caused carry bit which must be added into result */
86 if (tmp2 < tmp)
87 result |= (1 << (64 - negexp));
88 /* check if positive saturation has occurred because of rounding */
89 if (!sign && result < 0)
91 _REENT_ERRNO(rptr) = ERANGE;
92 return LONG_LONG_MAX;
95 else
97 /* we have -1.0, no rounding necessary */
98 return LONG_LONG_MIN;
101 return sign ? -result : result;
104 #ifndef _REENT_ONLY
106 __int64_t
107 strtosfix64 (const char *s,
108 char **ptr)
110 return _strtosfix64_r (_REENT, s, ptr);
113 #endif
115 #endif /* __SPE__ */