174462Salfred/*	$NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $	*/
274462Salfred
3259118Shrs/*-
4259118Shrs * Copyright (c) 2010, Oracle America, Inc.
58870Srgrimes *
6259118Shrs * Redistribution and use in source and binary forms, with or without
7259118Shrs * modification, are permitted provided that the following conditions are
8259118Shrs * met:
98870Srgrimes *
10259118Shrs *     * Redistributions of source code must retain the above copyright
11259118Shrs *       notice, this list of conditions and the following disclaimer.
12259118Shrs *     * Redistributions in binary form must reproduce the above
13259118Shrs *       copyright notice, this list of conditions and the following
14259118Shrs *       disclaimer in the documentation and/or other materials
15259118Shrs *       provided with the distribution.
16259118Shrs *     * Neither the name of the "Oracle America, Inc." nor the names of its
17259118Shrs *       contributors may be used to endorse or promote products derived
18259118Shrs *       from this software without specific prior written permission.
198870Srgrimes *
20259118Shrs *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21259118Shrs *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22259118Shrs *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23259118Shrs *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24259118Shrs *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25259118Shrs *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26259118Shrs *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27259118Shrs *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28259118Shrs *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29259118Shrs *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30259118Shrs *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31259118Shrs *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
321902Swollman */
331902Swollman
341902Swollman#if defined(LIBC_SCCS) && !defined(lint)
35136582Sobrienstatic char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
3674462Salfredstatic char *sccsid = "@(#)xdr_float.c	2.1 88/07/29 4.0 RPCSRC";
371902Swollman#endif
3892986Sobrien#include <sys/cdefs.h>
3992986Sobrien__FBSDID("$FreeBSD$");
401902Swollman
411902Swollman/*
4274462Salfred * xdr_float.c, Generic XDR routines implementation.
431902Swollman *
441902Swollman * These are the "floating point" xdr routines used to (de)serialize
451902Swollman * most common data items.  See xdr.h for more info on the interface to
461902Swollman * xdr.
471902Swollman */
481902Swollman
4974462Salfred#include "namespace.h"
501902Swollman#include <sys/param.h>
5174462Salfred
5274462Salfred#include <stdio.h>
5374462Salfred
541902Swollman#include <rpc/types.h>
551902Swollman#include <rpc/xdr.h>
5674462Salfred#include "un-namespace.h"
571902Swollman
581902Swollman/*
591902Swollman * NB: Not portable.
6021062Speter * This routine works on machines with IEEE754 FP and Vaxen.
611902Swollman */
621902Swollman
6321062Speter#include <machine/endian.h>
641902Swollman#define IEEEFP
651902Swollman
6674462Salfred#if defined(__vax__)
671902Swollman
681902Swollman/* What IEEE single precision floating point looks like on a Vax */
691902Swollmanstruct	ieee_single {
701902Swollman	unsigned int	mantissa: 23;
711902Swollman	unsigned int	exp     : 8;
721902Swollman	unsigned int	sign    : 1;
731902Swollman};
741902Swollman
751902Swollman/* Vax single precision floating point */
761902Swollmanstruct	vax_single {
771902Swollman	unsigned int	mantissa1 : 7;
781902Swollman	unsigned int	exp       : 8;
791902Swollman	unsigned int	sign      : 1;
801902Swollman	unsigned int	mantissa2 : 16;
811902Swollman};
821902Swollman
831902Swollman#define VAX_SNG_BIAS	0x81
841902Swollman#define IEEE_SNG_BIAS	0x7f
851902Swollman
861902Swollmanstatic struct sgl_limits {
871902Swollman	struct vax_single s;
881902Swollman	struct ieee_single ieee;
891902Swollman} sgl_limits[2] = {
901902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
911902Swollman	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
921902Swollman	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
931902Swollman	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
941902Swollman};
951902Swollman#endif /* vax */
961902Swollman
971902Swollmanbool_t
98288040Srodrigcxdr_float(XDR *xdrs, float *fp)
991902Swollman{
10074462Salfred#ifndef IEEEFP
1011902Swollman	struct ieee_single is;
1021902Swollman	struct vax_single vs, *vsp;
1031902Swollman	struct sgl_limits *lim;
104299183Spfg	u_int i;
1051902Swollman#endif
1061902Swollman	switch (xdrs->x_op) {
1071902Swollman
1081902Swollman	case XDR_ENCODE:
1098870Srgrimes#ifdef IEEEFP
11074462Salfred		return (XDR_PUTINT32(xdrs, (int32_t *)fp));
1111902Swollman#else
1121902Swollman		vs = *((struct vax_single *)fp);
113298120Spfg		for (i = 0, lim = sgl_limits; i < nitems(sgl_limits);
114298120Spfg		    i++, lim++) {
1151902Swollman			if ((vs.mantissa2 == lim->s.mantissa2) &&
1161902Swollman				(vs.exp == lim->s.exp) &&
1171902Swollman				(vs.mantissa1 == lim->s.mantissa1)) {
1181902Swollman				is = lim->ieee;
1191902Swollman				goto shipit;
1201902Swollman			}
1211902Swollman		}
1221902Swollman		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
1231902Swollman		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
1241902Swollman	shipit:
1251902Swollman		is.sign = vs.sign;
12674462Salfred		return (XDR_PUTINT32(xdrs, (int32_t *)&is));
1271902Swollman#endif
1281902Swollman
1291902Swollman	case XDR_DECODE:
1301902Swollman#ifdef IEEEFP
13174462Salfred		return (XDR_GETINT32(xdrs, (int32_t *)fp));
1321902Swollman#else
1331902Swollman		vsp = (struct vax_single *)fp;
13474462Salfred		if (!XDR_GETINT32(xdrs, (int32_t *)&is))
1351902Swollman			return (FALSE);
136298120Spfg		for (i = 0, lim = sgl_limits; i < nitems(sgl_limits);
137298120Spfg		    i++, lim++) {
1381902Swollman			if ((is.exp == lim->ieee.exp) &&
1391902Swollman				(is.mantissa == lim->ieee.mantissa)) {
1401902Swollman				*vsp = lim->s;
1411902Swollman				goto doneit;
1421902Swollman			}
1431902Swollman		}
1441902Swollman		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
1451902Swollman		vsp->mantissa2 = is.mantissa;
1461902Swollman		vsp->mantissa1 = (is.mantissa >> 16);
1471902Swollman	doneit:
1481902Swollman		vsp->sign = is.sign;
1491902Swollman		return (TRUE);
1501902Swollman#endif
1511902Swollman
1521902Swollman	case XDR_FREE:
1531902Swollman		return (TRUE);
1541902Swollman	}
15574462Salfred	/* NOTREACHED */
1561902Swollman	return (FALSE);
1571902Swollman}
1581902Swollman
15974462Salfred#if defined(__vax__)
1601902Swollman/* What IEEE double precision floating point looks like on a Vax */
1611902Swollmanstruct	ieee_double {
1621902Swollman	unsigned int	mantissa1 : 20;
1631902Swollman	unsigned int	exp       : 11;
1641902Swollman	unsigned int	sign      : 1;
1651902Swollman	unsigned int	mantissa2 : 32;
1661902Swollman};
1671902Swollman
1681902Swollman/* Vax double precision floating point */
1691902Swollmanstruct  vax_double {
1701902Swollman	unsigned int	mantissa1 : 7;
1711902Swollman	unsigned int	exp       : 8;
1721902Swollman	unsigned int	sign      : 1;
1731902Swollman	unsigned int	mantissa2 : 16;
1741902Swollman	unsigned int	mantissa3 : 16;
1751902Swollman	unsigned int	mantissa4 : 16;
1761902Swollman};
1771902Swollman
1781902Swollman#define VAX_DBL_BIAS	0x81
1791902Swollman#define IEEE_DBL_BIAS	0x3ff
1801902Swollman#define MASK(nbits)	((1 << nbits) - 1)
1811902Swollman
1821902Swollmanstatic struct dbl_limits {
1831902Swollman	struct	vax_double d;
1841902Swollman	struct	ieee_double ieee;
1851902Swollman} dbl_limits[2] = {
1861902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
1871902Swollman	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
1881902Swollman	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
1891902Swollman	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
1901902Swollman};
1911902Swollman
1921902Swollman#endif /* vax */
1931902Swollman
1941902Swollman
1951902Swollmanbool_t
196283833Srodrigcxdr_double(XDR *xdrs, double *dp)
1971902Swollman{
19821062Speter#ifdef IEEEFP
19974462Salfred	int32_t *i32p;
20021062Speter	bool_t rv;
20121062Speter#else
20274462Salfred	int32_t *lp;
2031902Swollman	struct	ieee_double id;
2041902Swollman	struct	vax_double vd;
20574462Salfred	struct dbl_limits *lim;
206299183Spfg	u_int i;
2071902Swollman#endif
2081902Swollman
2091902Swollman	switch (xdrs->x_op) {
2101902Swollman
2111902Swollman	case XDR_ENCODE:
2121902Swollman#ifdef IEEEFP
21374462Salfred		i32p = (int32_t *)(void *)dp;
2141902Swollman#if BYTE_ORDER == BIG_ENDIAN
21574462Salfred		rv = XDR_PUTINT32(xdrs, i32p);
21621062Speter		if (!rv)
21721062Speter			return (rv);
21874462Salfred		rv = XDR_PUTINT32(xdrs, i32p+1);
2191902Swollman#else
22074462Salfred		rv = XDR_PUTINT32(xdrs, i32p+1);
22121062Speter		if (!rv)
22221062Speter			return (rv);
22374462Salfred		rv = XDR_PUTINT32(xdrs, i32p);
2241902Swollman#endif
22521062Speter		return (rv);
2261902Swollman#else
2271902Swollman		vd = *((struct vax_double *)dp);
228298120Spfg		for (i = 0, lim = dbl_limits; i < nitems(dbl_limits);
229298120Spfg		    i++, lim++) {
2301902Swollman			if ((vd.mantissa4 == lim->d.mantissa4) &&
2311902Swollman				(vd.mantissa3 == lim->d.mantissa3) &&
2321902Swollman				(vd.mantissa2 == lim->d.mantissa2) &&
2331902Swollman				(vd.mantissa1 == lim->d.mantissa1) &&
2341902Swollman				(vd.exp == lim->d.exp)) {
2351902Swollman				id = lim->ieee;
2361902Swollman				goto shipit;
2371902Swollman			}
2381902Swollman		}
2391902Swollman		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
2401902Swollman		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
2411902Swollman		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
2421902Swollman				(vd.mantissa3 << 13) |
2431902Swollman				((vd.mantissa4 >> 3) & MASK(13));
2441902Swollman	shipit:
2451902Swollman		id.sign = vd.sign;
24674462Salfred		lp = (int32_t *)&id;
24774462Salfred		return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
2481902Swollman#endif
2491902Swollman
2501902Swollman	case XDR_DECODE:
2511902Swollman#ifdef IEEEFP
25274462Salfred		i32p = (int32_t *)(void *)dp;
2531902Swollman#if BYTE_ORDER == BIG_ENDIAN
25474462Salfred		rv = XDR_GETINT32(xdrs, i32p);
25521062Speter		if (!rv)
25621062Speter			return (rv);
25774462Salfred		rv = XDR_GETINT32(xdrs, i32p+1);
2581902Swollman#else
25974462Salfred		rv = XDR_GETINT32(xdrs, i32p+1);
26021062Speter		if (!rv)
26121062Speter			return (rv);
26274462Salfred		rv = XDR_GETINT32(xdrs, i32p);
2631902Swollman#endif
26421062Speter		return (rv);
2651902Swollman#else
26674462Salfred		lp = (int32_t *)&id;
26774462Salfred		if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
2681902Swollman			return (FALSE);
269298120Spfg		for (i = 0, lim = dbl_limits; i < nitems(dbl_limits);
270298120Spfg		    i++, lim++) {
2711902Swollman			if ((id.mantissa2 == lim->ieee.mantissa2) &&
2721902Swollman				(id.mantissa1 == lim->ieee.mantissa1) &&
2731902Swollman				(id.exp == lim->ieee.exp)) {
2741902Swollman				vd = lim->d;
2751902Swollman				goto doneit;
2761902Swollman			}
2771902Swollman		}
2781902Swollman		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
2791902Swollman		vd.mantissa1 = (id.mantissa1 >> 13);
2801902Swollman		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
2811902Swollman				(id.mantissa2 >> 29);
2821902Swollman		vd.mantissa3 = (id.mantissa2 >> 13);
2831902Swollman		vd.mantissa4 = (id.mantissa2 << 3);
2841902Swollman	doneit:
2851902Swollman		vd.sign = id.sign;
2861902Swollman		*dp = *((double *)&vd);
2871902Swollman		return (TRUE);
2881902Swollman#endif
2891902Swollman
2901902Swollman	case XDR_FREE:
2911902Swollman		return (TRUE);
2921902Swollman	}
29374462Salfred	/* NOTREACHED */
2941902Swollman	return (FALSE);
2951902Swollman}
296