From a67651406d4154cd5093884dea6ca0ca395d56db Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Dec 2015 21:05:44 +0000 Subject: [PATCH] lib/libm: Allow math funcs to be used by non-Thumb archs. Requires addition of software implementation of sqrtf function. --- lib/libm/ef_sqrt.c | 102 +++++++++++++++++++++++++++++++++++++++++++++ lib/libm/math.c | 9 ++++ 2 files changed, 111 insertions(+) create mode 100644 lib/libm/ef_sqrt.c diff --git a/lib/libm/ef_sqrt.c b/lib/libm/ef_sqrt.c new file mode 100644 index 000000000..87484d0bf --- /dev/null +++ b/lib/libm/ef_sqrt.c @@ -0,0 +1,102 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * These math functions are taken from newlib-nano-2, the newlib/libm/math + * directory, available from https://github.com/32bitmicro/newlib-nano-2. + * + * Appropriate copyright headers are reproduced below. + */ + +/* ef_sqrtf.c -- float version of e_sqrt.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float one = 1.0, tiny=1.0e-30; +#else +static float one = 1.0, tiny=1.0e-30; +#endif + +// sqrtf is exactly __ieee754_sqrtf when _IEEE_LIBM defined +float sqrtf(float x) +/* +#ifdef __STDC__ + float __ieee754_sqrtf(float x) +#else + float __ieee754_sqrtf(x) + float x; +#endif +*/ +{ + 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 */ + if(!FLT_UWORD_IS_FINITE(hx)) + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + /* take care of zero and -ves */ + if(FLT_UWORD_IS_ZERO(hx)) return x;/* sqrt(+-0) = +-0 */ + if(ix<0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ + + /* normalize x */ + m = (ix>>23); + if(FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */ + for(i=0;(ix&0x00800000L)==0;i++) ix<<=1; + m -= i-1; + } + m -= 127; /* unbias exponent */ + ix = (ix&0x007fffffL)|0x00800000L; + if(m&1) /* odd m, double x to make it even */ + ix += ix; + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix += ix; + q = s = 0; /* q = sqrt(x) */ + r = 0x01000000L; /* r = moving bit from right to left */ + + while(r!=0) { + t = s+r; + if(t<=ix) { + s = t+r; + ix -= t; + q += r; + } + ix += ix; + r>>=1; + } + + /* use floating add to find out rounding direction */ + if(ix!=0) { + z = one-tiny; /* trigger inexact flag */ + 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; +} diff --git a/lib/libm/math.c b/lib/libm/math.c index 5d4779b62..7cbec5fb3 100644 --- a/lib/libm/math.c +++ b/lib/libm/math.c @@ -45,6 +45,8 @@ typedef union { }; } double_s_t; +#if defined(__thumb__) + double __attribute__((pcs("aapcs"))) __aeabi_i2d(int32_t x) { return (float)x; } @@ -82,6 +84,11 @@ double __aeabi_dmul(double x , double y) { } +#endif // defined(__thumb__) + +// TODO this needs a better way of testing for Thumb2 FP hardware +#if defined(__thumb2__) + float sqrtf(float x) { asm volatile ( "vsqrt.f32 %[r], %[x]\n" @@ -90,6 +97,8 @@ float sqrtf(float x) { return x; } +#endif + #ifndef NDEBUG float copysignf(float x, float y) { float_s_t fx={.f = x};