summaryrefslogtreecommitdiff
path: root/sysdeps/m68k/fpu/s_llrint.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/m68k/fpu/s_llrint.c')
-rw-r--r--sysdeps/m68k/fpu/s_llrint.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/sysdeps/m68k/fpu/s_llrint.c b/sysdeps/m68k/fpu/s_llrint.c
index f5d0d51122..9dfee644ed 100644
--- a/sysdeps/m68k/fpu/s_llrint.c
+++ b/sysdeps/m68k/fpu/s_llrint.c
@@ -24,36 +24,50 @@
#include "math_private.h"
long long int
-__llrint (long double x)
+__llrint (double x)
{
- int32_t se, sx;
- u_int32_t h, l;
+ int32_t e;
+ u_int32_t h, l, s;
long long int result;
- x = __m81_u(__rintl) (x);
+ x = __m81_u(__rint) (x);
/* We could use __fixxfdi from libgcc, but here we can take advantage of
the known floating point format. */
- GET_LDOUBLE_WORDS (se, h, l, x);
+ EXTRACT_WORDS (h, l, x);
- sx = se & (1 << 15);
- se = (se ^ sx) - 0x3fff;
+ e = ((h >> 20) & 0x7ff) - 0x3ff;
+ if (e < 0)
+ return 0;
+ s = h;
+ h &= 0xfffff;
+ h |= 0x100000;
- if (se < 64)
+ if (e < 63)
{
- if (se > 31)
- result = (((long long int) (h >> (63 - se)) << 32)
- | (l >> (63 - se)) | (h << (se - 31)));
+ if (e > 52)
+ {
+ h <<= e - 52;
+ h |= l >> (84 - e);
+ l <<= e - 52;
+ result = ((long long int) h << 32) | l;
+ }
+ else if (e > 20)
+ {
+ l >>= 52 - e;
+ l |= h << (e - 20);
+ h >>= 52 - e;
+ result = ((long long int) h << 32) | l;
+ }
else
- result = h >> (31 - se);
- if (sx)
+ result = h >> (20 - e);
+ if (s & 0x80000000)
result = -result;
}
else
- /* Too large. The number is either +-inf or NaN or it is too
- large to be effected by rounding. The standard leaves it
- undefined what to return when the number is too large to fit in
- a `long long int'. */
+ /* The number is too large or not finite. The standard leaves it
+ undefined what to return when the number is too large to fit in a
+ `long long int'. */
result = -1LL;
return result;