1 /* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (c) 2010, Oracle America, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials 17 * provided with the distribution. 18 * * Neither the name of the "Oracle America, Inc." nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 29 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #if defined(LIBC_SCCS) && !defined(lint) 37 static char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; 38 static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC"; 39 #endif 40 /* 41 * xdr_float.c, Generic XDR routines implementation. 42 * 43 * These are the "floating point" xdr routines used to (de)serialize 44 * most common data items. See xdr.h for more info on the interface to 45 * xdr. 46 */ 47 48 #include "namespace.h" 49 #include <sys/param.h> 50 51 #include <stdio.h> 52 53 #include <rpc/types.h> 54 #include <rpc/xdr.h> 55 #include "un-namespace.h" 56 57 /* 58 * NB: Not portable. 59 * This routine works on machines with IEEE754 FP and Vaxen. 60 */ 61 62 #include <machine/endian.h> 63 #define IEEEFP 64 65 #if defined(__vax__) 66 67 /* What IEEE single precision floating point looks like on a Vax */ 68 struct ieee_single { 69 unsigned int mantissa: 23; 70 unsigned int exp : 8; 71 unsigned int sign : 1; 72 }; 73 74 /* Vax single precision floating point */ 75 struct vax_single { 76 unsigned int mantissa1 : 7; 77 unsigned int exp : 8; 78 unsigned int sign : 1; 79 unsigned int mantissa2 : 16; 80 }; 81 82 #define VAX_SNG_BIAS 0x81 83 #define IEEE_SNG_BIAS 0x7f 84 85 static struct sgl_limits { 86 struct vax_single s; 87 struct ieee_single ieee; 88 } sgl_limits[2] = { 89 {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 90 { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 91 {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 92 { 0x0, 0x0, 0x0 }} /* Min IEEE */ 93 }; 94 #endif /* vax */ 95 96 bool_t 97 xdr_float(XDR *xdrs, float *fp) 98 { 99 #ifndef IEEEFP 100 struct ieee_single is; 101 struct vax_single vs, *vsp; 102 struct sgl_limits *lim; 103 u_int i; 104 #endif 105 switch (xdrs->x_op) { 106 107 case XDR_ENCODE: 108 #ifdef IEEEFP 109 return (XDR_PUTINT32(xdrs, (int32_t *)fp)); 110 #else 111 vs = *((struct vax_single *)fp); 112 for (i = 0, lim = sgl_limits; i < nitems(sgl_limits); 113 i++, lim++) { 114 if ((vs.mantissa2 == lim->s.mantissa2) && 115 (vs.exp == lim->s.exp) && 116 (vs.mantissa1 == lim->s.mantissa1)) { 117 is = lim->ieee; 118 goto shipit; 119 } 120 } 121 is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; 122 is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 123 shipit: 124 is.sign = vs.sign; 125 return (XDR_PUTINT32(xdrs, (int32_t *)&is)); 126 #endif 127 128 case XDR_DECODE: 129 #ifdef IEEEFP 130 return (XDR_GETINT32(xdrs, (int32_t *)fp)); 131 #else 132 vsp = (struct vax_single *)fp; 133 if (!XDR_GETINT32(xdrs, (int32_t *)&is)) 134 return (FALSE); 135 for (i = 0, lim = sgl_limits; i < nitems(sgl_limits); 136 i++, lim++) { 137 if ((is.exp == lim->ieee.exp) && 138 (is.mantissa == lim->ieee.mantissa)) { 139 *vsp = lim->s; 140 goto doneit; 141 } 142 } 143 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 144 vsp->mantissa2 = is.mantissa; 145 vsp->mantissa1 = (is.mantissa >> 16); 146 doneit: 147 vsp->sign = is.sign; 148 return (TRUE); 149 #endif 150 151 case XDR_FREE: 152 return (TRUE); 153 } 154 /* NOTREACHED */ 155 return (FALSE); 156 } 157 158 #if defined(__vax__) 159 /* What IEEE double precision floating point looks like on a Vax */ 160 struct ieee_double { 161 unsigned int mantissa1 : 20; 162 unsigned int exp : 11; 163 unsigned int sign : 1; 164 unsigned int mantissa2 : 32; 165 }; 166 167 /* Vax double precision floating point */ 168 struct vax_double { 169 unsigned int mantissa1 : 7; 170 unsigned int exp : 8; 171 unsigned int sign : 1; 172 unsigned int mantissa2 : 16; 173 unsigned int mantissa3 : 16; 174 unsigned int mantissa4 : 16; 175 }; 176 177 #define VAX_DBL_BIAS 0x81 178 #define IEEE_DBL_BIAS 0x3ff 179 #define MASK(nbits) ((1 << nbits) - 1) 180 181 static struct dbl_limits { 182 struct vax_double d; 183 struct ieee_double ieee; 184 } dbl_limits[2] = { 185 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 186 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 187 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 188 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 189 }; 190 191 #endif /* vax */ 192 193 194 bool_t 195 xdr_double(XDR *xdrs, double *dp) 196 { 197 #ifdef IEEEFP 198 int32_t *i32p; 199 bool_t rv; 200 #else 201 int32_t *lp; 202 struct ieee_double id; 203 struct vax_double vd; 204 struct dbl_limits *lim; 205 u_int i; 206 #endif 207 208 switch (xdrs->x_op) { 209 210 case XDR_ENCODE: 211 #ifdef IEEEFP 212 i32p = (int32_t *)(void *)dp; 213 #if BYTE_ORDER == BIG_ENDIAN 214 rv = XDR_PUTINT32(xdrs, i32p); 215 if (!rv) 216 return (rv); 217 rv = XDR_PUTINT32(xdrs, i32p+1); 218 #else 219 rv = XDR_PUTINT32(xdrs, i32p+1); 220 if (!rv) 221 return (rv); 222 rv = XDR_PUTINT32(xdrs, i32p); 223 #endif 224 return (rv); 225 #else 226 vd = *((struct vax_double *)dp); 227 for (i = 0, lim = dbl_limits; i < nitems(dbl_limits); 228 i++, lim++) { 229 if ((vd.mantissa4 == lim->d.mantissa4) && 230 (vd.mantissa3 == lim->d.mantissa3) && 231 (vd.mantissa2 == lim->d.mantissa2) && 232 (vd.mantissa1 == lim->d.mantissa1) && 233 (vd.exp == lim->d.exp)) { 234 id = lim->ieee; 235 goto shipit; 236 } 237 } 238 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 239 id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); 240 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 241 (vd.mantissa3 << 13) | 242 ((vd.mantissa4 >> 3) & MASK(13)); 243 shipit: 244 id.sign = vd.sign; 245 lp = (int32_t *)&id; 246 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 247 #endif 248 249 case XDR_DECODE: 250 #ifdef IEEEFP 251 i32p = (int32_t *)(void *)dp; 252 #if BYTE_ORDER == BIG_ENDIAN 253 rv = XDR_GETINT32(xdrs, i32p); 254 if (!rv) 255 return (rv); 256 rv = XDR_GETINT32(xdrs, i32p+1); 257 #else 258 rv = XDR_GETINT32(xdrs, i32p+1); 259 if (!rv) 260 return (rv); 261 rv = XDR_GETINT32(xdrs, i32p); 262 #endif 263 return (rv); 264 #else 265 lp = (int32_t *)&id; 266 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 267 return (FALSE); 268 for (i = 0, lim = dbl_limits; i < nitems(dbl_limits); 269 i++, lim++) { 270 if ((id.mantissa2 == lim->ieee.mantissa2) && 271 (id.mantissa1 == lim->ieee.mantissa1) && 272 (id.exp == lim->ieee.exp)) { 273 vd = lim->d; 274 goto doneit; 275 } 276 } 277 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 278 vd.mantissa1 = (id.mantissa1 >> 13); 279 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 280 (id.mantissa2 >> 29); 281 vd.mantissa3 = (id.mantissa2 >> 13); 282 vd.mantissa4 = (id.mantissa2 << 3); 283 doneit: 284 vd.sign = id.sign; 285 *dp = *((double *)&vd); 286 return (TRUE); 287 #endif 288 289 case XDR_FREE: 290 return (TRUE); 291 } 292 /* NOTREACHED */ 293 return (FALSE); 294 } 295