Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / machine / powerpc / strtoufix64.c
blob205706856806bb81aa18c5bacd1da87509a265b0
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 64-bit unsigned value.
13 * Ignores `locale' stuff.
15 __uint64_t
16 _strtoufix64_r (struct _reent *rptr,
17 const char *nptr,
18 char **endptr)
20 union long_double_union ldbl;
21 int exp, sign, negexp, ld_type;
22 __uint64_t tmp, tmp2, result = 0;
24 init(ldbl);
26 _simdstrtold ((char *)nptr, endptr, &ldbl);
28 /* treat NAN as domain error, +/- infinity as saturation */
29 ld_type = _simdldcheck (&ldbl);
30 if (ld_type != 0)
32 if (ld_type == 1)
34 _REENT_ERRNO(rptr) = EDOM;
35 return 0;
37 _REENT_ERRNO(rptr) = ERANGE;
38 if (word0(ldbl) & Sign_bit)
39 return 0;
40 return ULONG_LONG_MAX;
43 /* strip off sign and exponent */
44 sign = word0(ldbl) & Sign_bit;
45 exp = ((word0(ldbl) & Exp_mask) >> Exp_shift) - Bias;
46 negexp = -exp;
47 if (negexp > 63)
48 return 0;
49 word0(ldbl) &= ~(Exp_mask | Sign_bit);
50 /* add in implicit normalized bit */
51 word0(ldbl) |= Exp_msk1;
52 /* shift so result is contained in single word */
53 tmp = word0(ldbl) << Ebits;
54 tmp |= ((unsigned long)word1(ldbl) >> (32 - Ebits));
55 tmp <<= 32;
56 if (Ebits < 32)
57 tmp |= ((unsigned long)word1(ldbl) << Ebits);
58 tmp |= ((unsigned long)word2(ldbl) >> (32 - Ebits));
60 /* check for saturation */
61 if (sign)
63 _REENT_ERRNO(rptr) = ERANGE;
64 return 0;
66 else
68 if (exp > 0 || (exp == 0 && tmp >= 0x8000000000000000LL))
70 _REENT_ERRNO(rptr) = ERANGE;
71 return ULONG_LONG_MAX;
75 /* otherwise we have normal number in range */
76 if (negexp > 1)
78 tmp2 = tmp + (1 << (negexp - 2));
79 result = (tmp2 >> (negexp - 1));
80 /* if rounding causes carry, add carry bit in */
81 if (tmp2 < tmp)
82 result += 1 << (64 - negexp);
84 else
86 if (Ebits < 32)
88 result = tmp + ((word2(ldbl) & (1 << (32 - Ebits - 1))) != 0);
89 /* if rounding causes carry, then saturation has occurred */
90 if (result < tmp)
92 _REENT_ERRNO(rptr) = ERANGE;
93 return ULONG_LONG_MAX;
96 else
97 result = tmp;
100 return result;
103 #ifndef _REENT_ONLY
105 __uint64_t
106 strtoufix64 (const char *s,
107 char **ptr)
109 return _strtoufix64_r (_REENT, s, ptr);
112 #endif
114 #endif /* __SPE__ */