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