sparc64 fpu unsigned -> long double conversions
Otto Moerbeek
otto at drijf.net
Thu Oct 7 12:16:08 PDT 2004
Hi,
I sent this message to people that have been doing commits the the
libc/sparc64 dir, but without response. So I'm dropping it here, in the
hope someone will pick it up,
-Otto
=====================================================================
Hi,
I suspect unsigned to long double conversion are broken on FreeBSD.
You might be interested in this diff, recently committed to OpenBSD
-Otto
#include <limits.h>
#include <stdio.h>
void
utold(unsigned u)
{
printf("%u %Lf\n", u, (long double) u);
}
void
ultold(unsigned long u)
{
printf("%lu %Lf\n", u, (long double) u);
}
void
ulltold(unsigned long long u)
{
printf("%llu %Lf\n", u, (long double) u);
}
main()
{
int i;
for (i = 0; i < 20; i++) {
utold(i);
ultold(i);
ulltold(i);
}
utold(UINT_MAX/2);
ultold(ULONG_MAX/2);
ulltold(ULLONG_MAX/2);
utold(UINT_MAX);
ultold(ULONG_MAX);
ulltold(ULLONG_MAX);
}
Index: fpu_explode.c
===================================================================
RCS file: /cvs/src/lib/libc/arch/sparc64/fpu/fpu_explode.c,v
retrieving revision 1.4
diff -u -p -r1.4 fpu_explode.c
--- fpu_explode.c 24 Mar 2004 15:54:16 -0000 1.4
+++ fpu_explode.c 28 Sep 2004 18:02:14 -0000
@@ -113,6 +113,32 @@ __fpu_itof(fp, i)
}
/*
+ * uint -> fpn.
+ */
+int
+__fpu_uitof(fp, i)
+ struct fpn *fp;
+ u_int i;
+{
+
+ if (i == 0)
+ return (FPC_ZERO);
+ /*
+ * The value FP_1 represents 2^FP_LG, so set the exponent
+ * there and let normalization fix it up.
+ * Note that this relies on fpu_norm()'s handling of
+ * `supernormals'; see fpu_subr.c.
+ */
+ fp->fp_exp = FP_LG;
+ fp->fp_mant[0] = i;
+ fp->fp_mant[1] = 0;
+ fp->fp_mant[2] = 0;
+ fp->fp_mant[3] = 0;
+ __fpu_norm(fp);
+ return (FPC_NUM);
+}
+
+/*
* 64-bit int -> fpn.
*/
int
@@ -131,6 +157,32 @@ __fpu_xtof(fp, i)
*/
fp->fp_exp = FP_LG2;
i = ((int64_t)i < 0) ? -i : i;
+ fp->fp_mant[0] = (i >> 32) & 0xffffffff;
+ fp->fp_mant[1] = (i >> 0) & 0xffffffff;
+ fp->fp_mant[2] = 0;
+ fp->fp_mant[3] = 0;
+ __fpu_norm(fp);
+ return (FPC_NUM);
+}
+
+/*
+ * 64-bit uint -> fpn.
+ */
+int
+__fpu_uxtof(fp, i)
+ struct fpn *fp;
+ u_int64_t i;
+{
+
+ if (i == 0)
+ return (FPC_ZERO);
+ /*
+ * The value FP_1 represents 2^FP_LG, so set the exponent
+ * there and let normalization fix it up.
+ * Note that this relies on fpu_norm()'s handling of
+ * `supernormals'; see fpu_subr.c.
+ */
+ fp->fp_exp = FP_LG2;
fp->fp_mant[0] = (i >> 32) & 0xffffffff;
fp->fp_mant[1] = (i >> 0) & 0xffffffff;
fp->fp_mant[2] = 0;
Index: fpu_extern.h
===================================================================
RCS file: /cvs/src/lib/libc/arch/sparc64/fpu/fpu_extern.h,v
retrieving revision 1.1
diff -u -p -r1.1 fpu_extern.h
--- fpu_extern.h 21 Jul 2003 18:41:30 -0000 1.1
+++ fpu_extern.h 28 Sep 2004 18:02:14 -0000
@@ -61,7 +61,9 @@ struct fpn *__fpu_div(struct fpemu *);
/* fpu_explode.c */
int __fpu_itof(struct fpn *, u_int);
+int __fpu_uitof(struct fpn *, u_int);
int __fpu_xtof(struct fpn *, u_int64_t);
+int __fpu_uxtof(struct fpn *, u_int64_t);
int __fpu_stof(struct fpn *, u_int);
int __fpu_dtof(struct fpn *, u_int, u_int );
int __fpu_qtof(struct fpn *, u_int, u_int , u_int , u_int );
Index: fpu_qp.c
===================================================================
RCS file: /cvs/src/lib/libc/arch/sparc64/fpu/fpu_qp.c,v
retrieving revision 1.1
diff -u -p -r1.1 fpu_qp.c
--- fpu_qp.c 21 Jul 2003 18:41:30 -0000 1.1
+++ fpu_qp.c 28 Sep 2004 18:02:14 -0000
@@ -55,7 +55,7 @@ _Qp_ ## op(u_int *c, u_int *a, u_int *b)
c[0] = __fpu_ftoq(&fe, r, c); \
}
-#define _QP_TTOQ(qname, fname, ntype, atype, ...) \
+#define _QP_TTOQ(qname, fname, ntype, atype, signed, ...) \
void _Qp_ ## qname ## toq(u_int *c, ntype n); \
void \
_Qp_ ## qname ## toq(u_int *c, ntype n) \
@@ -64,7 +64,7 @@ _Qp_ ## qname ## toq(u_int *c, ntype n)
atype *a; \
__asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
a = (atype *)&n; \
- fe.fe_f1.fp_sign = a[0] >> 31; \
+ fe.fe_f1.fp_sign = signed ? a[0] >> 31 : 0; \
fe.fe_f1.fp_sticky = 0; \
fe.fe_f1.fp_class = __fpu_ ## fname ## tof(&fe.fe_f1, __VA_ARGS__); \
c[0] = __fpu_ftoq(&fe, &fe.fe_f1, c); \
@@ -166,12 +166,12 @@ _QP_OP(div)
_QP_OP(mul)
_QP_OP(sub)
-_QP_TTOQ(d, d, double, u_int, a[0], a[1])
-_QP_TTOQ(i, i, int, u_int, a[0])
-_QP_TTOQ(s, s, float, u_int, a[0])
-_QP_TTOQ(x, x, long, u_long, a[0])
-_QP_TTOQ(ui, i, u_int, u_int, a[0])
-_QP_TTOQ(ux, x, u_long, u_long, a[0])
+_QP_TTOQ(d, d, double, u_int, 1, a[0], a[1])
+_QP_TTOQ(i, i, int, u_int, 1, a[0])
+_QP_TTOQ(s, s, float, u_int, 1, a[0])
+_QP_TTOQ(x, x, long, u_long, 1, a[0])
+_QP_TTOQ(ui, ui, u_int, u_int, 0, a[0])
+_QP_TTOQ(ux, ux, u_long, u_long, 0, a[0])
_QP_QTOT4(d, d, double, a)
_QP_QTOT3(i, i, int)
More information about the freebsd-sparc64
mailing list