http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55372
--- Comment #1 from stevenbaker94 at rocketmail dot com 2013-05-01 10:16:56 UTC
---
This version handles negative numbers as well:
static inline float _fpos(const float f)
{
union {
float f;
uint32_t i;
} x;
x.f = f;
uint32_t r;
float f_out;
asm ("lui %0, %1"
: "=d" (r)
: "K" (x.i >> 16));
asm ("mtc1 %1, %0"
: "=f" (f_out)
: "d" (r));
return f_out;
}
static inline float _fneg(const float f)
{
union {
float f;
uint32_t i;
} x;
x.f = f;
uint32_t r;
float f_out;
asm ("lui %0, %1"
: "=d" (r)
: "K" (0x8000 ^ (x.i >> 16)));
asm ("mtc1 %1, %0"
: "=f" (f_out)
: "d" (r));
return f_out;
}
static inline float f(const float f)
{
return f >= 0 ? _fpos(f) : _fneg(-f);
}
Actually, it doesn't always discard fractional bits. It works for e.g. f(0.25)
as well, since the floating-point representation still only has 0s in the lower
16 bits.