xdr_float.c revision 136582
174462Salfred/*	$NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $	*/
274462Salfred
31902Swollman/*
41902Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
51902Swollman * unrestricted use provided that this legend is included on all tape
61902Swollman * media and as a part of the software program in whole or part.  Users
71902Swollman * may copy or modify Sun RPC without charge, but are not authorized
81902Swollman * to license or distribute it to anyone else except as part of a product or
91902Swollman * program developed by the user.
108870Srgrimes *
111902Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
121902Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
131902Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
148870Srgrimes *
151902Swollman * Sun RPC is provided with no support and without any obligation on the
161902Swollman * part of Sun Microsystems, Inc. to assist in its use, correction,
171902Swollman * modification or enhancement.
188870Srgrimes *
191902Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
201902Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
211902Swollman * OR ANY PART THEREOF.
228870Srgrimes *
231902Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue
241902Swollman * or profits or other special, indirect and consequential damages, even if
251902Swollman * Sun has been advised of the possibility of such damages.
268870Srgrimes *
271902Swollman * Sun Microsystems, Inc.
281902Swollman * 2550 Garcia Avenue
291902Swollman * Mountain View, California  94043
301902Swollman */
311902Swollman
321902Swollman#if defined(LIBC_SCCS) && !defined(lint)
33136582Sobrienstatic char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
3474462Salfredstatic char *sccsid = "@(#)xdr_float.c	2.1 88/07/29 4.0 RPCSRC";
351902Swollman#endif
3692986Sobrien#include <sys/cdefs.h>
3792986Sobrien__FBSDID("$FreeBSD: head/lib/libc/xdr/xdr_float.c 136582 2004-10-16 06:32:43Z obrien $");
381902Swollman
391902Swollman/*
4074462Salfred * xdr_float.c, Generic XDR routines implementation.
411902Swollman *
421902Swollman * Copyright (C) 1984, Sun Microsystems, Inc.
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/types.h>
511902Swollman#include <sys/param.h>
5274462Salfred
5374462Salfred#include <stdio.h>
5474462Salfred
551902Swollman#include <rpc/types.h>
561902Swollman#include <rpc/xdr.h>
5774462Salfred#include "un-namespace.h"
581902Swollman
591902Swollman/*
601902Swollman * NB: Not portable.
6121062Speter * This routine works on machines with IEEE754 FP and Vaxen.
621902Swollman */
631902Swollman
6421062Speter#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
6521062Speter    defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
66129201Scognet    defined(__arm__) || defined(__ppc__) || defined(__ia64__) || \
67114322Speter    defined(__arm26__) || defined(__sparc64__) || defined(__amd64__)
6821062Speter#include <machine/endian.h>
691902Swollman#define IEEEFP
701902Swollman#endif
711902Swollman
7274462Salfred#if defined(__vax__)
731902Swollman
741902Swollman/* What IEEE single precision floating point looks like on a Vax */
751902Swollmanstruct	ieee_single {
761902Swollman	unsigned int	mantissa: 23;
771902Swollman	unsigned int	exp     : 8;
781902Swollman	unsigned int	sign    : 1;
791902Swollman};
801902Swollman
811902Swollman/* Vax single precision floating point */
821902Swollmanstruct	vax_single {
831902Swollman	unsigned int	mantissa1 : 7;
841902Swollman	unsigned int	exp       : 8;
851902Swollman	unsigned int	sign      : 1;
861902Swollman	unsigned int	mantissa2 : 16;
871902Swollman};
881902Swollman
891902Swollman#define VAX_SNG_BIAS	0x81
901902Swollman#define IEEE_SNG_BIAS	0x7f
911902Swollman
921902Swollmanstatic struct sgl_limits {
931902Swollman	struct vax_single s;
941902Swollman	struct ieee_single ieee;
951902Swollman} sgl_limits[2] = {
961902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
971902Swollman	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
981902Swollman	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
991902Swollman	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
1001902Swollman};
1011902Swollman#endif /* vax */
1021902Swollman
1031902Swollmanbool_t
1041902Swollmanxdr_float(xdrs, fp)
10574462Salfred	XDR *xdrs;
10674462Salfred	float *fp;
1071902Swollman{
10874462Salfred#ifndef IEEEFP
1091902Swollman	struct ieee_single is;
1101902Swollman	struct vax_single vs, *vsp;
1111902Swollman	struct sgl_limits *lim;
1121902Swollman	int i;
1131902Swollman#endif
1141902Swollman	switch (xdrs->x_op) {
1151902Swollman
1161902Swollman	case XDR_ENCODE:
1178870Srgrimes#ifdef IEEEFP
11874462Salfred		return (XDR_PUTINT32(xdrs, (int32_t *)fp));
1191902Swollman#else
1201902Swollman		vs = *((struct vax_single *)fp);
1211902Swollman		for (i = 0, lim = sgl_limits;
1221902Swollman			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
1231902Swollman			i++, lim++) {
1241902Swollman			if ((vs.mantissa2 == lim->s.mantissa2) &&
1251902Swollman				(vs.exp == lim->s.exp) &&
1261902Swollman				(vs.mantissa1 == lim->s.mantissa1)) {
1271902Swollman				is = lim->ieee;
1281902Swollman				goto shipit;
1291902Swollman			}
1301902Swollman		}
1311902Swollman		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
1321902Swollman		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
1331902Swollman	shipit:
1341902Swollman		is.sign = vs.sign;
13574462Salfred		return (XDR_PUTINT32(xdrs, (int32_t *)&is));
1361902Swollman#endif
1371902Swollman
1381902Swollman	case XDR_DECODE:
1391902Swollman#ifdef IEEEFP
14074462Salfred		return (XDR_GETINT32(xdrs, (int32_t *)fp));
1411902Swollman#else
1421902Swollman		vsp = (struct vax_single *)fp;
14374462Salfred		if (!XDR_GETINT32(xdrs, (int32_t *)&is))
1441902Swollman			return (FALSE);
1451902Swollman		for (i = 0, lim = sgl_limits;
1461902Swollman			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
1471902Swollman			i++, lim++) {
1481902Swollman			if ((is.exp == lim->ieee.exp) &&
1491902Swollman				(is.mantissa == lim->ieee.mantissa)) {
1501902Swollman				*vsp = lim->s;
1511902Swollman				goto doneit;
1521902Swollman			}
1531902Swollman		}
1541902Swollman		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
1551902Swollman		vsp->mantissa2 = is.mantissa;
1561902Swollman		vsp->mantissa1 = (is.mantissa >> 16);
1571902Swollman	doneit:
1581902Swollman		vsp->sign = is.sign;
1591902Swollman		return (TRUE);
1601902Swollman#endif
1611902Swollman
1621902Swollman	case XDR_FREE:
1631902Swollman		return (TRUE);
1641902Swollman	}
16574462Salfred	/* NOTREACHED */
1661902Swollman	return (FALSE);
1671902Swollman}
1681902Swollman
16974462Salfred#if defined(__vax__)
1701902Swollman/* What IEEE double precision floating point looks like on a Vax */
1711902Swollmanstruct	ieee_double {
1721902Swollman	unsigned int	mantissa1 : 20;
1731902Swollman	unsigned int	exp       : 11;
1741902Swollman	unsigned int	sign      : 1;
1751902Swollman	unsigned int	mantissa2 : 32;
1761902Swollman};
1771902Swollman
1781902Swollman/* Vax double precision floating point */
1791902Swollmanstruct  vax_double {
1801902Swollman	unsigned int	mantissa1 : 7;
1811902Swollman	unsigned int	exp       : 8;
1821902Swollman	unsigned int	sign      : 1;
1831902Swollman	unsigned int	mantissa2 : 16;
1841902Swollman	unsigned int	mantissa3 : 16;
1851902Swollman	unsigned int	mantissa4 : 16;
1861902Swollman};
1871902Swollman
1881902Swollman#define VAX_DBL_BIAS	0x81
1891902Swollman#define IEEE_DBL_BIAS	0x3ff
1901902Swollman#define MASK(nbits)	((1 << nbits) - 1)
1911902Swollman
1921902Swollmanstatic struct dbl_limits {
1931902Swollman	struct	vax_double d;
1941902Swollman	struct	ieee_double ieee;
1951902Swollman} dbl_limits[2] = {
1961902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
1971902Swollman	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
1981902Swollman	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
1991902Swollman	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
2001902Swollman};
2011902Swollman
2021902Swollman#endif /* vax */
2031902Swollman
2041902Swollman
2051902Swollmanbool_t
2061902Swollmanxdr_double(xdrs, dp)
20774462Salfred	XDR *xdrs;
2081902Swollman	double *dp;
2091902Swollman{
21021062Speter#ifdef IEEEFP
21174462Salfred	int32_t *i32p;
21221062Speter	bool_t rv;
21321062Speter#else
21474462Salfred	int32_t *lp;
2151902Swollman	struct	ieee_double id;
2161902Swollman	struct	vax_double vd;
21774462Salfred	struct dbl_limits *lim;
2181902Swollman	int i;
2191902Swollman#endif
2201902Swollman
2211902Swollman	switch (xdrs->x_op) {
2221902Swollman
2231902Swollman	case XDR_ENCODE:
2241902Swollman#ifdef IEEEFP
22574462Salfred		i32p = (int32_t *)(void *)dp;
2261902Swollman#if BYTE_ORDER == BIG_ENDIAN
22774462Salfred		rv = XDR_PUTINT32(xdrs, i32p);
22821062Speter		if (!rv)
22921062Speter			return (rv);
23074462Salfred		rv = XDR_PUTINT32(xdrs, i32p+1);
2311902Swollman#else
23274462Salfred		rv = XDR_PUTINT32(xdrs, i32p+1);
23321062Speter		if (!rv)
23421062Speter			return (rv);
23574462Salfred		rv = XDR_PUTINT32(xdrs, i32p);
2361902Swollman#endif
23721062Speter		return (rv);
2381902Swollman#else
2391902Swollman		vd = *((struct vax_double *)dp);
2401902Swollman		for (i = 0, lim = dbl_limits;
2411902Swollman			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
2421902Swollman			i++, lim++) {
2431902Swollman			if ((vd.mantissa4 == lim->d.mantissa4) &&
2441902Swollman				(vd.mantissa3 == lim->d.mantissa3) &&
2451902Swollman				(vd.mantissa2 == lim->d.mantissa2) &&
2461902Swollman				(vd.mantissa1 == lim->d.mantissa1) &&
2471902Swollman				(vd.exp == lim->d.exp)) {
2481902Swollman				id = lim->ieee;
2491902Swollman				goto shipit;
2501902Swollman			}
2511902Swollman		}
2521902Swollman		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
2531902Swollman		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
2541902Swollman		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
2551902Swollman				(vd.mantissa3 << 13) |
2561902Swollman				((vd.mantissa4 >> 3) & MASK(13));
2571902Swollman	shipit:
2581902Swollman		id.sign = vd.sign;
25974462Salfred		lp = (int32_t *)&id;
26074462Salfred		return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
2611902Swollman#endif
2621902Swollman
2631902Swollman	case XDR_DECODE:
2641902Swollman#ifdef IEEEFP
26574462Salfred		i32p = (int32_t *)(void *)dp;
2661902Swollman#if BYTE_ORDER == BIG_ENDIAN
26774462Salfred		rv = XDR_GETINT32(xdrs, i32p);
26821062Speter		if (!rv)
26921062Speter			return (rv);
27074462Salfred		rv = XDR_GETINT32(xdrs, i32p+1);
2711902Swollman#else
27274462Salfred		rv = XDR_GETINT32(xdrs, i32p+1);
27321062Speter		if (!rv)
27421062Speter			return (rv);
27574462Salfred		rv = XDR_GETINT32(xdrs, i32p);
2761902Swollman#endif
27721062Speter		return (rv);
2781902Swollman#else
27974462Salfred		lp = (int32_t *)&id;
28074462Salfred		if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
2811902Swollman			return (FALSE);
2821902Swollman		for (i = 0, lim = dbl_limits;
2831902Swollman			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
2841902Swollman			i++, lim++) {
2851902Swollman			if ((id.mantissa2 == lim->ieee.mantissa2) &&
2861902Swollman				(id.mantissa1 == lim->ieee.mantissa1) &&
2871902Swollman				(id.exp == lim->ieee.exp)) {
2881902Swollman				vd = lim->d;
2891902Swollman				goto doneit;
2901902Swollman			}
2911902Swollman		}
2921902Swollman		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
2931902Swollman		vd.mantissa1 = (id.mantissa1 >> 13);
2941902Swollman		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
2951902Swollman				(id.mantissa2 >> 29);
2961902Swollman		vd.mantissa3 = (id.mantissa2 >> 13);
2971902Swollman		vd.mantissa4 = (id.mantissa2 << 3);
2981902Swollman	doneit:
2991902Swollman		vd.sign = id.sign;
3001902Swollman		*dp = *((double *)&vd);
3011902Swollman		return (TRUE);
3021902Swollman#endif
3031902Swollman
3041902Swollman	case XDR_FREE:
3051902Swollman		return (TRUE);
3061902Swollman	}
30774462Salfred	/* NOTREACHED */
3081902Swollman	return (FALSE);
3091902Swollman}
310