diff options
Diffstat (limited to 'core/nds32/math.c')
-rw-r--r-- | core/nds32/math.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/core/nds32/math.c b/core/nds32/math.c new file mode 100644 index 0000000000..496fcc0e5d --- /dev/null +++ b/core/nds32/math.c @@ -0,0 +1,116 @@ +/* Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "common.h" + +#ifdef CONFIG_FPU +union ieee_float_shape_type { + float value; + uint32_t word; +}; + +/* Get a 32 bit int from a float. */ +#define GET_FLOAT_WORD(i, d) \ + do { \ + union ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ + } while (0) + +/* Set a float from a 32 bit int. */ +#define SET_FLOAT_WORD(d, i) \ + do { \ + union ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ + } while (0) + +float fabsf(float x) +{ + uint32_t ix; + + GET_FLOAT_WORD(ix, x); + SET_FLOAT_WORD(x, (ix & 0x7fffffff)); + + return x; +} + +#define FLT_UWORD_IS_ZERO(x) ((x) == 0) +#define FLT_UWORD_IS_SUBNORMAL(x) ((x) < 0x00800000L) +#define FLT_UWORD_IS_FINITE(x) ((x) < 0x7f800000L) + +static const float one = 1.0f, tiny = 1.0e-30f; +static float __ieee754_sqrtf(float x) +{ + float z; + uint32_t r, hx; + int32_t ix, s, q, m, t, i; + + GET_FLOAT_WORD(ix, x); + hx = ix & 0x7fffffff; + + /* + * take care of Inf and NaN + * sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN + */ + if (!FLT_UWORD_IS_FINITE(hx)) + return x * x + x; + /* take care of zero and -ves */ + if (FLT_UWORD_IS_ZERO(hx)) + return x; + if (ix < 0) + return (x - x) / (x - x); + + m = (ix >> 23); + if (FLT_UWORD_IS_SUBNORMAL(hx)) { + for (i = 0; (ix & 0x00800000L) == 0; i++) + ix <<= 1; + m -= i - 1; + } + + m -= 127; + ix = (ix & 0x007fffffL) | 0x00800000L; + if (m & 1) + ix += ix; + + m >>= 1; + ix += ix; + q = s = 0; + r = 0x01000000L; + + while (r != 0) { + t = s + r; + if (t <= ix) { + s = t + r; + ix -= t; + q += r; + } + ix += ix; + r >>= 1; + } + + if (ix != 0) { + z = one - tiny; + if (z >= one) { + z = one + tiny; + if (z > one) + q += 2; + else + q += (q & 1); + } + } + + ix = (q >> 1) + 0x3f000000L; + ix += (m << 23); + SET_FLOAT_WORD(z, ix); + + return z; +} + +float sqrtf(float x) +{ + return __ieee754_sqrtf(x); +} +#endif |