softfloat-native.c revision 4af48bf7c72ef1e201c64bd475377b5af9d8e8a1
/* Native implementation of soft float functions. Only a single status
context is supported */
#include "softfloat.h"
#include <math.h>
{
#if defined(_BSD) && !defined(__APPLE__) || (defined(HOST_SOLARIS) && (HOST_SOLARIS < 10 || HOST_SOLARIS == 11)) /* VBOX adds sol 11 */
/* nothing to do */
#else
#endif
}
#ifdef FLOATX80
{
}
#endif
/* Some defines which only apply to *BSD */
# endif /* VBOX && _BSD */
extern long double rintl(long double);
extern long double scalbnl(long double, int);
long long
llrintl(long double x) {
return ((long long) rintl(x));
}
long
lrintl(long double x) {
return ((long) rintl(x));
}
long double
ldexpl(long double x, int n) {
return (scalbnl(x, n));
}
#endif
#endif
#if defined(_ARCH_PPC)
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
static double qemu_rint(double x)
{
double y = 4503599627370496.0;
if (fabs(x) >= y)
return x;
if (x < 0)
y = -y;
y = (x + y) - y;
if (y == 0.0)
y = copysign(y, x);
return y;
}
#endif
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
{
return (float32)v;
}
{
return (float32)v;
}
{
return (float64)v;
}
{
return (float64)v;
}
#ifdef FLOATX80
{
return (floatx80)v;
}
#endif
{
return (float32)v;
}
{
return (float32)v;
}
{
return (float64)v;
}
{
return (float64)v;
}
#ifdef FLOATX80
{
return (floatx80)v;
}
#endif
/* XXX: this code implements the x86 behaviour, not the IEEE one. */
#if HOST_LONG_BITS == 32
static inline int long_to_int32(long a)
{
return a;
}
#else
static inline int long_to_int32(long a)
{
if (a != (int32_t)a)
a = 0x80000000;
return a;
}
#endif
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
{
return long_to_int32(lrintf(a));
}
{
return (int)a;
}
{
return llrintf(a);
}
{
return (int64_t)a;
}
{
return a;
}
#ifdef FLOATX80
{
return a;
}
#endif
{
int64_t v;
unsigned int res;
v = llrintf(a);
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
{
int64_t v;
unsigned int res;
v = (int64_t)a;
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
{
return rintf(a);
}
{
return remainderf(a, b);
}
{
return sqrtf(a);
}
{
if (a < b) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (a > b) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
{
if (isless(a, b)) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (isgreater(a, b)) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
{
float32u u;
uint32_t a;
u.f = a1;
a = u.i;
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
}
{
float32u u;
uint64_t a;
u.f = a1;
a = u.i;
return ( 0xFF800000 < ( a<<1 ) );
}
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
{
return long_to_int32(lrint(a));
}
{
return (int)a;
}
{
return llrint(a);
}
{
return (int64_t)a;
}
{
return a;
}
#ifdef FLOATX80
{
return a;
}
#endif
#ifdef FLOAT128
{
return a;
}
#endif
{
int64_t v;
unsigned int res;
v = llrint(a);
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
{
int64_t v;
unsigned int res;
v = (int64_t)a;
if (v < 0) {
res = 0;
} else if (v > 0xffffffff) {
res = 0xffffffff;
} else {
res = v;
}
return res;
}
{
int64_t v;
return v - INT64_MIN;
}
{
int64_t v;
return v - INT64_MIN;
}
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
{
}
#endif
{
return trunc(a);
}
{
#if defined(__arm__)
switch(STATUS(float_rounding_mode)) {
default:
case float_round_nearest_even:
asm("rndd %0, %1" : "=f" (a) : "f"(a));
break;
case float_round_down:
asm("rnddm %0, %1" : "=f" (a) : "f"(a));
break;
case float_round_up:
asm("rnddp %0, %1" : "=f" (a) : "f"(a));
break;
case float_round_to_zero:
asm("rnddz %0, %1" : "=f" (a) : "f"(a));
break;
}
#else
return rint(a);
#endif
}
{
return remainder(a, b);
}
{
return sqrt(a);
}
{
if (a < b) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (a > b) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
{
if (isless(a, b)) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (isgreater(a, b)) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
{
float64u u;
uint64_t a;
u.f = a1;
a = u.i;
return
( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
}
{
float64u u;
uint64_t a;
u.f = a1;
a = u.i;
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
{
return long_to_int32(lrintl(a));
}
{
return (int)a;
}
{
return llrintl(a);
}
{
return (int64_t)a;
}
{
return a;
}
{
return a;
}
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
{
return rintl(a);
}
{
return remainderl(a, b);
}
{
return sqrtl(a);
}
{
if (a < b) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (a > b) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
{
if (isless(a, b)) {
return float_relation_less;
} else if (a == b) {
return float_relation_equal;
} else if (isgreater(a, b)) {
return float_relation_greater;
} else {
return float_relation_unordered;
}
}
{
floatx80u u;
u.f = a1;
return
}
{
floatx80u u;
u.f = a1;
}
#endif