xref: /freebsd/lib/libc/xdr/xdr_float.c (revision a204967a)
18360efbdSAlfred Perlstein /*	$NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $	*/
28360efbdSAlfred Perlstein 
3a204967aSHiroki Sato /*-
4a204967aSHiroki Sato  * Copyright (c) 2010, Oracle America, Inc.
5eae561b3SGarrett Wollman  *
6a204967aSHiroki Sato  * Redistribution and use in source and binary forms, with or without
7a204967aSHiroki Sato  * modification, are permitted provided that the following conditions are
8a204967aSHiroki Sato  * met:
9eae561b3SGarrett Wollman  *
10a204967aSHiroki Sato  *     * Redistributions of source code must retain the above copyright
11a204967aSHiroki Sato  *       notice, this list of conditions and the following disclaimer.
12a204967aSHiroki Sato  *     * Redistributions in binary form must reproduce the above
13a204967aSHiroki Sato  *       copyright notice, this list of conditions and the following
14a204967aSHiroki Sato  *       disclaimer in the documentation and/or other materials
15a204967aSHiroki Sato  *       provided with the distribution.
16a204967aSHiroki Sato  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17a204967aSHiroki Sato  *       contributors may be used to endorse or promote products derived
18a204967aSHiroki Sato  *       from this software without specific prior written permission.
19eae561b3SGarrett Wollman  *
20a204967aSHiroki Sato  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21a204967aSHiroki Sato  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22a204967aSHiroki Sato  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23a204967aSHiroki Sato  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24a204967aSHiroki Sato  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25a204967aSHiroki Sato  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26a204967aSHiroki Sato  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27a204967aSHiroki Sato  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28a204967aSHiroki Sato  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29a204967aSHiroki Sato  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30a204967aSHiroki Sato  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31a204967aSHiroki Sato  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32eae561b3SGarrett Wollman  */
33eae561b3SGarrett Wollman 
34eae561b3SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint)
35a9bdcd37SDavid E. O'Brien static char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
368360efbdSAlfred Perlstein static char *sccsid = "@(#)xdr_float.c	2.1 88/07/29 4.0 RPCSRC";
37eae561b3SGarrett Wollman #endif
38333fc21eSDavid E. O'Brien #include <sys/cdefs.h>
39333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$");
40eae561b3SGarrett Wollman 
41eae561b3SGarrett Wollman /*
428360efbdSAlfred Perlstein  * xdr_float.c, Generic XDR routines implementation.
43eae561b3SGarrett Wollman  *
44eae561b3SGarrett Wollman  * These are the "floating point" xdr routines used to (de)serialize
45eae561b3SGarrett Wollman  * most common data items.  See xdr.h for more info on the interface to
46eae561b3SGarrett Wollman  * xdr.
47eae561b3SGarrett Wollman  */
48eae561b3SGarrett Wollman 
498360efbdSAlfred Perlstein #include "namespace.h"
50eae561b3SGarrett Wollman #include <sys/types.h>
51eae561b3SGarrett Wollman #include <sys/param.h>
528360efbdSAlfred Perlstein 
538360efbdSAlfred Perlstein #include <stdio.h>
548360efbdSAlfred Perlstein 
55eae561b3SGarrett Wollman #include <rpc/types.h>
56eae561b3SGarrett Wollman #include <rpc/xdr.h>
578360efbdSAlfred Perlstein #include "un-namespace.h"
58eae561b3SGarrett Wollman 
59eae561b3SGarrett Wollman /*
60eae561b3SGarrett Wollman  * NB: Not portable.
611ad08a09SPeter Wemm  * This routine works on machines with IEEE754 FP and Vaxen.
62eae561b3SGarrett Wollman  */
63eae561b3SGarrett Wollman 
641ad08a09SPeter Wemm #if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
651ad08a09SPeter Wemm     defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
661d7c6c33SOlivier Houchard     defined(__arm__) || defined(__ppc__) || defined(__ia64__) || \
67f7f1bb14SPeter Wemm     defined(__arm26__) || defined(__sparc64__) || defined(__amd64__)
681ad08a09SPeter Wemm #include <machine/endian.h>
69eae561b3SGarrett Wollman #define IEEEFP
70eae561b3SGarrett Wollman #endif
71eae561b3SGarrett Wollman 
728360efbdSAlfred Perlstein #if defined(__vax__)
73eae561b3SGarrett Wollman 
74eae561b3SGarrett Wollman /* What IEEE single precision floating point looks like on a Vax */
75eae561b3SGarrett Wollman struct	ieee_single {
76eae561b3SGarrett Wollman 	unsigned int	mantissa: 23;
77eae561b3SGarrett Wollman 	unsigned int	exp     : 8;
78eae561b3SGarrett Wollman 	unsigned int	sign    : 1;
79eae561b3SGarrett Wollman };
80eae561b3SGarrett Wollman 
81eae561b3SGarrett Wollman /* Vax single precision floating point */
82eae561b3SGarrett Wollman struct	vax_single {
83eae561b3SGarrett Wollman 	unsigned int	mantissa1 : 7;
84eae561b3SGarrett Wollman 	unsigned int	exp       : 8;
85eae561b3SGarrett Wollman 	unsigned int	sign      : 1;
86eae561b3SGarrett Wollman 	unsigned int	mantissa2 : 16;
87eae561b3SGarrett Wollman };
88eae561b3SGarrett Wollman 
89eae561b3SGarrett Wollman #define VAX_SNG_BIAS	0x81
90eae561b3SGarrett Wollman #define IEEE_SNG_BIAS	0x7f
91eae561b3SGarrett Wollman 
92eae561b3SGarrett Wollman static struct sgl_limits {
93eae561b3SGarrett Wollman 	struct vax_single s;
94eae561b3SGarrett Wollman 	struct ieee_single ieee;
95eae561b3SGarrett Wollman } sgl_limits[2] = {
96eae561b3SGarrett Wollman 	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
97eae561b3SGarrett Wollman 	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
98eae561b3SGarrett Wollman 	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
99eae561b3SGarrett Wollman 	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
100eae561b3SGarrett Wollman };
101eae561b3SGarrett Wollman #endif /* vax */
102eae561b3SGarrett Wollman 
103eae561b3SGarrett Wollman bool_t
104eae561b3SGarrett Wollman xdr_float(xdrs, fp)
1058360efbdSAlfred Perlstein 	XDR *xdrs;
1068360efbdSAlfred Perlstein 	float *fp;
107eae561b3SGarrett Wollman {
1088360efbdSAlfred Perlstein #ifndef IEEEFP
109eae561b3SGarrett Wollman 	struct ieee_single is;
110eae561b3SGarrett Wollman 	struct vax_single vs, *vsp;
111eae561b3SGarrett Wollman 	struct sgl_limits *lim;
112eae561b3SGarrett Wollman 	int i;
113eae561b3SGarrett Wollman #endif
114eae561b3SGarrett Wollman 	switch (xdrs->x_op) {
115eae561b3SGarrett Wollman 
116eae561b3SGarrett Wollman 	case XDR_ENCODE:
117eae561b3SGarrett Wollman #ifdef IEEEFP
1188360efbdSAlfred Perlstein 		return (XDR_PUTINT32(xdrs, (int32_t *)fp));
119eae561b3SGarrett Wollman #else
120eae561b3SGarrett Wollman 		vs = *((struct vax_single *)fp);
121eae561b3SGarrett Wollman 		for (i = 0, lim = sgl_limits;
122eae561b3SGarrett Wollman 			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
123eae561b3SGarrett Wollman 			i++, lim++) {
124eae561b3SGarrett Wollman 			if ((vs.mantissa2 == lim->s.mantissa2) &&
125eae561b3SGarrett Wollman 				(vs.exp == lim->s.exp) &&
126eae561b3SGarrett Wollman 				(vs.mantissa1 == lim->s.mantissa1)) {
127eae561b3SGarrett Wollman 				is = lim->ieee;
128eae561b3SGarrett Wollman 				goto shipit;
129eae561b3SGarrett Wollman 			}
130eae561b3SGarrett Wollman 		}
131eae561b3SGarrett Wollman 		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
132eae561b3SGarrett Wollman 		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
133eae561b3SGarrett Wollman 	shipit:
134eae561b3SGarrett Wollman 		is.sign = vs.sign;
1358360efbdSAlfred Perlstein 		return (XDR_PUTINT32(xdrs, (int32_t *)&is));
136eae561b3SGarrett Wollman #endif
137eae561b3SGarrett Wollman 
138eae561b3SGarrett Wollman 	case XDR_DECODE:
139eae561b3SGarrett Wollman #ifdef IEEEFP
1408360efbdSAlfred Perlstein 		return (XDR_GETINT32(xdrs, (int32_t *)fp));
141eae561b3SGarrett Wollman #else
142eae561b3SGarrett Wollman 		vsp = (struct vax_single *)fp;
1438360efbdSAlfred Perlstein 		if (!XDR_GETINT32(xdrs, (int32_t *)&is))
144eae561b3SGarrett Wollman 			return (FALSE);
145eae561b3SGarrett Wollman 		for (i = 0, lim = sgl_limits;
146eae561b3SGarrett Wollman 			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
147eae561b3SGarrett Wollman 			i++, lim++) {
148eae561b3SGarrett Wollman 			if ((is.exp == lim->ieee.exp) &&
149eae561b3SGarrett Wollman 				(is.mantissa == lim->ieee.mantissa)) {
150eae561b3SGarrett Wollman 				*vsp = lim->s;
151eae561b3SGarrett Wollman 				goto doneit;
152eae561b3SGarrett Wollman 			}
153eae561b3SGarrett Wollman 		}
154eae561b3SGarrett Wollman 		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
155eae561b3SGarrett Wollman 		vsp->mantissa2 = is.mantissa;
156eae561b3SGarrett Wollman 		vsp->mantissa1 = (is.mantissa >> 16);
157eae561b3SGarrett Wollman 	doneit:
158eae561b3SGarrett Wollman 		vsp->sign = is.sign;
159eae561b3SGarrett Wollman 		return (TRUE);
160eae561b3SGarrett Wollman #endif
161eae561b3SGarrett Wollman 
162eae561b3SGarrett Wollman 	case XDR_FREE:
163eae561b3SGarrett Wollman 		return (TRUE);
164eae561b3SGarrett Wollman 	}
1658360efbdSAlfred Perlstein 	/* NOTREACHED */
166eae561b3SGarrett Wollman 	return (FALSE);
167eae561b3SGarrett Wollman }
168eae561b3SGarrett Wollman 
1698360efbdSAlfred Perlstein #if defined(__vax__)
170eae561b3SGarrett Wollman /* What IEEE double precision floating point looks like on a Vax */
171eae561b3SGarrett Wollman struct	ieee_double {
172eae561b3SGarrett Wollman 	unsigned int	mantissa1 : 20;
173eae561b3SGarrett Wollman 	unsigned int	exp       : 11;
174eae561b3SGarrett Wollman 	unsigned int	sign      : 1;
175eae561b3SGarrett Wollman 	unsigned int	mantissa2 : 32;
176eae561b3SGarrett Wollman };
177eae561b3SGarrett Wollman 
178eae561b3SGarrett Wollman /* Vax double precision floating point */
179eae561b3SGarrett Wollman struct  vax_double {
180eae561b3SGarrett Wollman 	unsigned int	mantissa1 : 7;
181eae561b3SGarrett Wollman 	unsigned int	exp       : 8;
182eae561b3SGarrett Wollman 	unsigned int	sign      : 1;
183eae561b3SGarrett Wollman 	unsigned int	mantissa2 : 16;
184eae561b3SGarrett Wollman 	unsigned int	mantissa3 : 16;
185eae561b3SGarrett Wollman 	unsigned int	mantissa4 : 16;
186eae561b3SGarrett Wollman };
187eae561b3SGarrett Wollman 
188eae561b3SGarrett Wollman #define VAX_DBL_BIAS	0x81
189eae561b3SGarrett Wollman #define IEEE_DBL_BIAS	0x3ff
190eae561b3SGarrett Wollman #define MASK(nbits)	((1 << nbits) - 1)
191eae561b3SGarrett Wollman 
192eae561b3SGarrett Wollman static struct dbl_limits {
193eae561b3SGarrett Wollman 	struct	vax_double d;
194eae561b3SGarrett Wollman 	struct	ieee_double ieee;
195eae561b3SGarrett Wollman } dbl_limits[2] = {
196eae561b3SGarrett Wollman 	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
197eae561b3SGarrett Wollman 	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
198eae561b3SGarrett Wollman 	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
199eae561b3SGarrett Wollman 	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
200eae561b3SGarrett Wollman };
201eae561b3SGarrett Wollman 
202eae561b3SGarrett Wollman #endif /* vax */
203eae561b3SGarrett Wollman 
204eae561b3SGarrett Wollman 
205eae561b3SGarrett Wollman bool_t
206eae561b3SGarrett Wollman xdr_double(xdrs, dp)
2078360efbdSAlfred Perlstein 	XDR *xdrs;
208eae561b3SGarrett Wollman 	double *dp;
209eae561b3SGarrett Wollman {
2101ad08a09SPeter Wemm #ifdef IEEEFP
2118360efbdSAlfred Perlstein 	int32_t *i32p;
2121ad08a09SPeter Wemm 	bool_t rv;
2131ad08a09SPeter Wemm #else
2148360efbdSAlfred Perlstein 	int32_t *lp;
215eae561b3SGarrett Wollman 	struct	ieee_double id;
216eae561b3SGarrett Wollman 	struct	vax_double vd;
2178360efbdSAlfred Perlstein 	struct dbl_limits *lim;
218eae561b3SGarrett Wollman 	int i;
219eae561b3SGarrett Wollman #endif
220eae561b3SGarrett Wollman 
221eae561b3SGarrett Wollman 	switch (xdrs->x_op) {
222eae561b3SGarrett Wollman 
223eae561b3SGarrett Wollman 	case XDR_ENCODE:
224eae561b3SGarrett Wollman #ifdef IEEEFP
2258360efbdSAlfred Perlstein 		i32p = (int32_t *)(void *)dp;
226eae561b3SGarrett Wollman #if BYTE_ORDER == BIG_ENDIAN
2278360efbdSAlfred Perlstein 		rv = XDR_PUTINT32(xdrs, i32p);
2281ad08a09SPeter Wemm 		if (!rv)
2291ad08a09SPeter Wemm 			return (rv);
2308360efbdSAlfred Perlstein 		rv = XDR_PUTINT32(xdrs, i32p+1);
231eae561b3SGarrett Wollman #else
2328360efbdSAlfred Perlstein 		rv = XDR_PUTINT32(xdrs, i32p+1);
2331ad08a09SPeter Wemm 		if (!rv)
2341ad08a09SPeter Wemm 			return (rv);
2358360efbdSAlfred Perlstein 		rv = XDR_PUTINT32(xdrs, i32p);
236eae561b3SGarrett Wollman #endif
2371ad08a09SPeter Wemm 		return (rv);
238eae561b3SGarrett Wollman #else
239eae561b3SGarrett Wollman 		vd = *((struct vax_double *)dp);
240eae561b3SGarrett Wollman 		for (i = 0, lim = dbl_limits;
241eae561b3SGarrett Wollman 			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
242eae561b3SGarrett Wollman 			i++, lim++) {
243eae561b3SGarrett Wollman 			if ((vd.mantissa4 == lim->d.mantissa4) &&
244eae561b3SGarrett Wollman 				(vd.mantissa3 == lim->d.mantissa3) &&
245eae561b3SGarrett Wollman 				(vd.mantissa2 == lim->d.mantissa2) &&
246eae561b3SGarrett Wollman 				(vd.mantissa1 == lim->d.mantissa1) &&
247eae561b3SGarrett Wollman 				(vd.exp == lim->d.exp)) {
248eae561b3SGarrett Wollman 				id = lim->ieee;
249eae561b3SGarrett Wollman 				goto shipit;
250eae561b3SGarrett Wollman 			}
251eae561b3SGarrett Wollman 		}
252eae561b3SGarrett Wollman 		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
253eae561b3SGarrett Wollman 		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
254eae561b3SGarrett Wollman 		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
255eae561b3SGarrett Wollman 				(vd.mantissa3 << 13) |
256eae561b3SGarrett Wollman 				((vd.mantissa4 >> 3) & MASK(13));
257eae561b3SGarrett Wollman 	shipit:
258eae561b3SGarrett Wollman 		id.sign = vd.sign;
2598360efbdSAlfred Perlstein 		lp = (int32_t *)&id;
2608360efbdSAlfred Perlstein 		return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
261eae561b3SGarrett Wollman #endif
262eae561b3SGarrett Wollman 
263eae561b3SGarrett Wollman 	case XDR_DECODE:
264eae561b3SGarrett Wollman #ifdef IEEEFP
2658360efbdSAlfred Perlstein 		i32p = (int32_t *)(void *)dp;
266eae561b3SGarrett Wollman #if BYTE_ORDER == BIG_ENDIAN
2678360efbdSAlfred Perlstein 		rv = XDR_GETINT32(xdrs, i32p);
2681ad08a09SPeter Wemm 		if (!rv)
2691ad08a09SPeter Wemm 			return (rv);
2708360efbdSAlfred Perlstein 		rv = XDR_GETINT32(xdrs, i32p+1);
271eae561b3SGarrett Wollman #else
2728360efbdSAlfred Perlstein 		rv = XDR_GETINT32(xdrs, i32p+1);
2731ad08a09SPeter Wemm 		if (!rv)
2741ad08a09SPeter Wemm 			return (rv);
2758360efbdSAlfred Perlstein 		rv = XDR_GETINT32(xdrs, i32p);
276eae561b3SGarrett Wollman #endif
2771ad08a09SPeter Wemm 		return (rv);
278eae561b3SGarrett Wollman #else
2798360efbdSAlfred Perlstein 		lp = (int32_t *)&id;
2808360efbdSAlfred Perlstein 		if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
281eae561b3SGarrett Wollman 			return (FALSE);
282eae561b3SGarrett Wollman 		for (i = 0, lim = dbl_limits;
283eae561b3SGarrett Wollman 			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
284eae561b3SGarrett Wollman 			i++, lim++) {
285eae561b3SGarrett Wollman 			if ((id.mantissa2 == lim->ieee.mantissa2) &&
286eae561b3SGarrett Wollman 				(id.mantissa1 == lim->ieee.mantissa1) &&
287eae561b3SGarrett Wollman 				(id.exp == lim->ieee.exp)) {
288eae561b3SGarrett Wollman 				vd = lim->d;
289eae561b3SGarrett Wollman 				goto doneit;
290eae561b3SGarrett Wollman 			}
291eae561b3SGarrett Wollman 		}
292eae561b3SGarrett Wollman 		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
293eae561b3SGarrett Wollman 		vd.mantissa1 = (id.mantissa1 >> 13);
294eae561b3SGarrett Wollman 		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
295eae561b3SGarrett Wollman 				(id.mantissa2 >> 29);
296eae561b3SGarrett Wollman 		vd.mantissa3 = (id.mantissa2 >> 13);
297eae561b3SGarrett Wollman 		vd.mantissa4 = (id.mantissa2 << 3);
298eae561b3SGarrett Wollman 	doneit:
299eae561b3SGarrett Wollman 		vd.sign = id.sign;
300eae561b3SGarrett Wollman 		*dp = *((double *)&vd);
301eae561b3SGarrett Wollman 		return (TRUE);
302eae561b3SGarrett Wollman #endif
303eae561b3SGarrett Wollman 
304eae561b3SGarrett Wollman 	case XDR_FREE:
305eae561b3SGarrett Wollman 		return (TRUE);
306eae561b3SGarrett Wollman 	}
3078360efbdSAlfred Perlstein 	/* NOTREACHED */
308eae561b3SGarrett Wollman 	return (FALSE);
309eae561b3SGarrett Wollman }
310