#ifndef _LIBM_INLINES_H
#define _LIBM_INLINES_H
#ifdef __GNUC__
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <sys/ieeefp.h>
extern __GNU_INLINE float
__inline_sqrtf(float a)
{
float ret;
__asm__ __volatile__("sqrtss %1, %0\n\t" : "=x" (ret) : "x" (a));
return (ret);
}
extern __GNU_INLINE double
__inline_sqrt(double a)
{
double ret;
__asm__ __volatile__("sqrtsd %1, %0\n\t" : "=x" (ret) : "x" (a));
return (ret);
}
extern __GNU_INLINE double
__ieee754_sqrt(double a)
{
return (__inline_sqrt(a));
}
extern __GNU_INLINE int
__swapRP(int i)
{
int ret;
uint16_t cw;
__asm__ __volatile__("fstcw %0\n\t" : "=m" (cw));
ret = (cw >> 8) & 0x3;
cw = (cw & 0xfcff) | ((i & 0x3) << 8);
__asm__ __volatile__("fldcw %0\n\t" : : "m" (cw));
return (ret);
}
extern __GNU_INLINE enum fp_direction_type
__swap87RD(enum fp_direction_type i)
{
int ret;
uint16_t cw;
__asm__ __volatile__("fstcw %0\n\t" : "=m" (cw));
ret = (cw >> 10) & 0x3;
cw = (cw & 0xf3ff) | ((i & 0x3) << 10);
__asm__ __volatile__("fldcw %0\n\t" : : "m" (cw));
return (ret);
}
extern __GNU_INLINE int
abs(int i)
{
int ret;
__asm__ __volatile__(
"movl %1, %0\n\t"
"negl %1\n\t"
"cmovnsl %1, %0\n\t"
: "=r" (ret), "+r" (i)
:
: "cc");
return (ret);
}
extern __GNU_INLINE double
copysign(double d1, double d2)
{
double tmpd;
__asm__ __volatile__(
"movd %3, %1\n\t"
"andpd %1, %0\n\t"
"andnpd %2, %1\n\t"
"orpd %1, %0\n\t"
: "+&x" (d1), "=&x" (tmpd)
: "x" (d2), "r" (0x7fffffffffffffff));
return (d1);
}
extern __GNU_INLINE double
fabs(double d)
{
double tmp;
__asm__ __volatile__(
"movd %2, %1\n\t"
"andpd %1, %0"
: "+x" (d), "=&x" (tmp)
: "r" (0x7fffffffffffffff));
return (d);
}
extern __GNU_INLINE float
fabsf(float d)
{
__asm__ __volatile__(
"andpd %1, %0"
: "+x" (d)
: "x" (0x7fffffff));
return (d);
}
extern __GNU_INLINE int
finite(double d)
{
long ret = 0x7fffffffffffffff;
uint64_t tmp;
__asm__ __volatile__(
"movq %2, %1\n\t"
"andq %1, %0\n\t"
"movq $0x7ff0000000000000, %1\n\t"
"subq %1, %0\n\t"
"shrq $63, %0\n\t"
: "+r" (ret), "=r" (tmp)
: "x" (d)
: "cc");
return (ret);
}
extern __GNU_INLINE int
signbit(double d)
{
long ret;
__asm__ __volatile__(
"movmskpd %1, %0\n\t"
"andq $1, %0\n\t"
: "=r" (ret)
: "x" (d)
: "cc");
return (ret);
}
extern __GNU_INLINE double
sqrt(double d)
{
return (__inline_sqrt(d));
}
extern __GNU_INLINE float
sqrtf(float f)
{
return (__inline_sqrtf(f));
}
#ifdef __cplusplus
}
#endif
#endif
#endif