From 2c538c86c15d597cc875dc926e4e39285c5625df Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Mon, 10 May 2010 16:48:20 -0700 Subject: Upstream: Use CONFIG_BSD instead of _BSD and HOST_BSD Also fix OS X build, which failed with a link error. Change-Id: Idd63f25dc1f46ea66da5727c7577def34f048c3c --- fpu/softfloat-native.c | 15 +++-- fpu/softfloat-native.h | 13 +++-- fpu/softfloat-specialize.h | 4 +- fpu/softfloat.c | 138 +++++++++++++++++++++++++++++++++++++++++++++ fpu/softfloat.h | 11 +++- 5 files changed, 166 insertions(+), 15 deletions(-) (limited to 'fpu') diff --git a/fpu/softfloat-native.c b/fpu/softfloat-native.c index 2af07a3..8d64f4e 100644 --- a/fpu/softfloat-native.c +++ b/fpu/softfloat-native.c @@ -2,15 +2,15 @@ context is supported */ #include "softfloat.h" #include -#if defined(HOST_SOLARIS) +#if defined(CONFIG_SOLARIS) #include #endif void set_float_rounding_mode(int val STATUS_PARAM) { STATUS(float_rounding_mode) = val; -#if defined(HOST_BSD) && !defined(__APPLE__) || \ - (defined(HOST_SOLARIS) && HOST_SOLARIS < 10) +#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) || \ + (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) fpsetround(val); #elif defined(__arm__) /* nothing to do */ @@ -26,7 +26,8 @@ void set_floatx80_rounding_precision(int val STATUS_PARAM) } #endif -#if defined(HOST_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10) +#if defined(CONFIG_BSD) || \ + (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) #define lrint(d) ((int32_t)rint(d)) #define llrint(d) ((int64_t)rint(d)) #define lrintf(f) ((int32_t)rint(f)) @@ -34,7 +35,8 @@ void set_floatx80_rounding_precision(int val STATUS_PARAM) #define sqrtf(f) ((float)sqrt(f)) #define remainderf(fa, fb) ((float)remainder(fa, fb)) #define rintf(f) ((float)rint(f)) -#if !defined(__sparc__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10 +#if !defined(__sparc__) && \ + (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) extern long double rintl(long double); extern long double scalbnl(long double, int); @@ -349,7 +351,8 @@ uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM) /*---------------------------------------------------------------------------- | Software IEC/IEEE double-precision operations. *----------------------------------------------------------------------------*/ -#if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10 +#if defined(__sun__) && \ + (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) static inline float64 trunc(float64 x) { return x < 0 ? -floor(-x) : floor(x); diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h index a28c769..fe737b3 100644 --- a/fpu/softfloat-native.h +++ b/fpu/softfloat-native.h @@ -1,7 +1,8 @@ /* Native implementation of soft float functions */ #include -#if (defined(HOST_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS) +#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \ + || defined(CONFIG_SOLARIS) #include #define fabsf(f) ((float)fabs(f)) #else @@ -19,8 +20,9 @@ * Solaris 10 with GCC4 does not need these macros as they * are defined in with a compiler directive */ -#if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ((HOST_SOLARIS >= 10) \ - && (__GNUC__ < 4))) \ +#if defined(CONFIG_SOLARIS) && \ + ((CONFIG_SOLARIS_VERSION <= 9 ) || \ + ((CONFIG_SOLARIS_VERSION == 10) && (__GNUC__ < 4))) \ || (defined(__OpenBSD__) && (OpenBSD < 200811)) /* * C99 7.12.3 classification macros @@ -61,7 +63,7 @@ #define isunordered(x,y) unordered(x, y) #endif -#if defined(__sun__) && !defined(NEED_LIBSUNMATH) +#if defined(__sun__) && !defined(CONFIG_NEEDS_LIBSUNMATH) #ifndef isnan # define isnan(x) \ @@ -111,7 +113,8 @@ typedef union { /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point rounding mode. *----------------------------------------------------------------------------*/ -#if (defined(HOST_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS) +#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \ + || defined(CONFIG_SOLARIS) #if defined(__OpenBSD__) #define FE_RM FP_RM #define FE_RP FP_RP diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index f607e19..8e6aceb 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -61,7 +61,7 @@ typedef struct { *----------------------------------------------------------------------------*/ #if defined(TARGET_SPARC) #define float32_default_nan make_float32(0x7FFFFFFF) -#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) +#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) #define float32_default_nan make_float32(0x7FC00000) #elif defined(TARGET_HPPA) #define float32_default_nan make_float32(0x7FA00000) @@ -189,7 +189,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) *----------------------------------------------------------------------------*/ #if defined(TARGET_SPARC) #define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF )) -#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) +#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) #define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 )) #elif defined(TARGET_HPPA) #define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 )) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 4d58744..395f9b1 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -2457,6 +2457,144 @@ float32 float64_to_float32( float64 a STATUS_PARAM ) } + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| half-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ +static bits16 packFloat16(flag zSign, int16 zExp, bits16 zSig) +{ + return (((bits32)zSign) << 15) + (((bits32)zExp) << 10) + zSig; +} + +/* Half precision floats come in two formats: standard IEEE and "ARM" format. + The latter gains extra exponent range by omitting the NaN/Inf encodings. */ + +float32 float16_to_float32( bits16 a, flag ieee STATUS_PARAM ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSign = a >> 15; + aExp = (a >> 10) & 0x1f; + aSig = a & 0x3ff; + + if (aExp == 0x1f && ieee) { + if (aSig) { + /* Make sure correct exceptions are raised. */ + float32ToCommonNaN(a STATUS_VAR); + aSig |= 0x200; + } + return packFloat32(aSign, 0xff, aSig << 13); + } + if (aExp == 0) { + int8 shiftCount; + + if (aSig == 0) { + return packFloat32(aSign, 0, 0); + } + + shiftCount = countLeadingZeros32( aSig ) - 21; + aSig = aSig << shiftCount; + aExp = -shiftCount; + } + return packFloat32( aSign, aExp + 0x70, aSig << 13); +} + +bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM) +{ + flag aSign; + int16 aExp; + bits32 aSig; + bits32 mask; + bits32 increment; + int8 roundingMode; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if (aSig) { + /* Make sure correct exceptions are raised. */ + float32ToCommonNaN(a STATUS_VAR); + aSig |= 0x00400000; + } + return packFloat16(aSign, 0x1f, aSig >> 13); + } + if (aExp == 0 && aSign == 0) { + return packFloat16(aSign, 0, 0); + } + /* Decimal point between bits 22 and 23. */ + aSig |= 0x00800000; + aExp -= 0x7f; + if (aExp < -14) { + mask = 0x007fffff; + if (aExp < -24) { + aExp = -25; + } else { + mask >>= 24 + aExp; + } + } else { + mask = 0x00001fff; + } + if (aSig & mask) { + float_raise( float_flag_underflow STATUS_VAR ); + roundingMode = STATUS(float_rounding_mode); + switch (roundingMode) { + case float_round_nearest_even: + increment = (mask + 1) >> 1; + if ((aSig & mask) == increment) { + increment = aSig & (increment << 1); + } + break; + case float_round_up: + increment = aSign ? 0 : mask; + break; + case float_round_down: + increment = aSign ? mask : 0; + break; + default: /* round_to_zero */ + increment = 0; + break; + } + aSig += increment; + if (aSig >= 0x01000000) { + aSig >>= 1; + aExp++; + } + } else if (aExp < -14 + && STATUS(float_detect_tininess) == float_tininess_before_rounding) { + float_raise( float_flag_underflow STATUS_VAR); + } + + if (ieee) { + if (aExp > 15) { + float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR); + return packFloat16(aSign, 0x1f, 0); + } + } else { + if (aExp > 16) { + float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR); + return packFloat16(aSign, 0x1f, 0x3ff); + } + } + if (aExp < -24) { + return packFloat16(aSign, 0, 0); + } + if (aExp < -14) { + aSig >>= -14 - aExp; + aExp = -14; + } + return packFloat16(aSign, aExp + 14, aSig >> 13); +} + #ifdef FLOATX80 /*---------------------------------------------------------------------------- diff --git a/fpu/softfloat.h b/fpu/softfloat.h index 850a01f..c31e62f 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -32,7 +32,7 @@ these four paragraphs for those parts of this code that are retained. #ifndef SOFTFLOAT_H #define SOFTFLOAT_H -#if defined(HOST_SOLARIS) && defined(NEEDS_LIBSUNMATH) +#if defined(CONFIG_SOLARIS) && defined(CONFIG_NEEDS_LIBSUNMATH) #include #endif @@ -90,7 +90,7 @@ typedef int64_t sbits64; #define FLOAT128 #else /* native float support */ -#if (defined(__i386__) || defined(__x86_64__)) && !defined(HOST_BSD) +#if (defined(__i386__) || defined(__x86_64__)) && !defined(CONFIG_BSD) #define FLOATX80 #endif #endif /* !CONFIG_SOFTFLOAT */ @@ -187,6 +187,7 @@ typedef struct float_status { signed char float_detect_tininess; signed char float_rounding_mode; signed char float_exception_flags; + signed char float_exception_mask; #ifdef FLOATX80 signed char floatx80_rounding_precision; #endif @@ -243,6 +244,12 @@ float128 int64_to_float128( int64_t STATUS_PARAM ); #endif /*---------------------------------------------------------------------------- +| Software half-precision conversion routines. +*----------------------------------------------------------------------------*/ +bits16 float32_to_float16( float32, flag STATUS_PARAM ); +float32 float16_to_float32( bits16, flag STATUS_PARAM ); + +/*---------------------------------------------------------------------------- | Software IEC/IEEE single-precision conversion routines. *----------------------------------------------------------------------------*/ int float32_to_int32( float32 STATUS_PARAM ); -- cgit v1.1