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