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