aboutsummaryrefslogtreecommitdiffstats
path: root/fpu
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2010-05-10 16:48:20 -0700
committerDavid 'Digit' Turner <digit@android.com>2010-05-10 16:49:50 -0700
commit2c538c86c15d597cc875dc926e4e39285c5625df (patch)
treefd02b6da79b5e1375ab2ec5264ab339044e4a7da /fpu
parent5e097bf40ed22b422dce1fb2c58098d6c97cf0c6 (diff)
downloadexternal_qemu-2c538c86c15d597cc875dc926e4e39285c5625df.zip
external_qemu-2c538c86c15d597cc875dc926e4e39285c5625df.tar.gz
external_qemu-2c538c86c15d597cc875dc926e4e39285c5625df.tar.bz2
Upstream: Use CONFIG_BSD instead of _BSD and HOST_BSD
Also fix OS X build, which failed with a link error. Change-Id: Idd63f25dc1f46ea66da5727c7577def34f048c3c
Diffstat (limited to 'fpu')
-rw-r--r--fpu/softfloat-native.c15
-rw-r--r--fpu/softfloat-native.h13
-rw-r--r--fpu/softfloat-specialize.h4
-rw-r--r--fpu/softfloat.c138
-rw-r--r--fpu/softfloat.h11
5 files changed, 166 insertions, 15 deletions
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 <math.h>
-#if defined(HOST_SOLARIS)
+#if defined(CONFIG_SOLARIS)
#include <fenv.h>
#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 <math.h>
-#if (defined(HOST_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
+#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \
+ || defined(CONFIG_SOLARIS)
#include <ieeefp.h>
#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 <iso/math_c99.h> 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 <sunmath.h>
#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 );