1 /* $NetBSD: xdr_float.c,v 1.13 1997/07/21 14:08:44 jtc Exp $ */ 2 3 /* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32 #include <sys/cdefs.h> 33 #if defined(LIBC_SCCS) && !defined(lint) 34 #if 0 35 static char *sccsid = "@(#)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 #else 38 __RCSID("$NetBSD: xdr_float.c,v 1.13 1997/07/21 14:08:44 jtc Exp $"); 39 #endif 40 #endif 41 42 /* 43 * xdr_float.c, Generic XDR routines impelmentation. 44 * 45 * Copyright (C) 1984, Sun Microsystems, Inc. 46 * 47 * These are the "floating point" xdr routines used to (de)serialize 48 * most common data items. See xdr.h for more info on the interface to 49 * xdr. 50 */ 51 52 #include "namespace.h" 53 #include <stdio.h> 54 #include <sys/types.h> 55 #include <sys/param.h> 56 #include <rpc/types.h> 57 #include <rpc/xdr.h> 58 59 #ifdef __weak_alias 60 __weak_alias(xdr_double,_xdr_double); 61 __weak_alias(xdr_float,_xdr_float); 62 #endif 63 64 /* 65 * NB: Not portable. 66 * This routine works on machines with IEEE754 FP and Vaxen. 67 */ 68 69 #if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ 70 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ 71 defined(__arm32__) || defined(__powerpc__) 72 #include <machine/endian.h> 73 #define IEEEFP 74 #endif 75 76 #ifdef vax 77 78 /* What IEEE single precision floating point looks like on a Vax */ 79 struct ieee_single { 80 unsigned int mantissa: 23; 81 unsigned int exp : 8; 82 unsigned int sign : 1; 83 }; 84 85 /* Vax single precision floating point */ 86 struct vax_single { 87 unsigned int mantissa1 : 7; 88 unsigned int exp : 8; 89 unsigned int sign : 1; 90 unsigned int mantissa2 : 16; 91 }; 92 93 #define VAX_SNG_BIAS 0x81 94 #define IEEE_SNG_BIAS 0x7f 95 96 static struct sgl_limits { 97 struct vax_single s; 98 struct ieee_single ieee; 99 } sgl_limits[2] = { 100 {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 101 { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 102 {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 103 { 0x0, 0x0, 0x0 }} /* Min IEEE */ 104 }; 105 #endif /* vax */ 106 107 bool_t 108 xdr_float(xdrs, fp) 109 register XDR *xdrs; 110 register float *fp; 111 { 112 #ifdef IEEEFP 113 bool_t rv; 114 long tmpl; 115 #else 116 struct ieee_single is; 117 struct vax_single vs, *vsp; 118 struct sgl_limits *lim; 119 int i; 120 #endif 121 switch (xdrs->x_op) { 122 123 case XDR_ENCODE: 124 #ifdef IEEEFP 125 tmpl = *(int32_t *)fp; 126 return (XDR_PUTLONG(xdrs, &tmpl)); 127 #else 128 vs = *((struct vax_single *)fp); 129 for (i = 0, lim = sgl_limits; 130 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 131 i++, lim++) { 132 if ((vs.mantissa2 == lim->s.mantissa2) && 133 (vs.exp == lim->s.exp) && 134 (vs.mantissa1 == lim->s.mantissa1)) { 135 is = lim->ieee; 136 goto shipit; 137 } 138 } 139 is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; 140 is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 141 shipit: 142 is.sign = vs.sign; 143 return (XDR_PUTLONG(xdrs, (long *)&is)); 144 #endif 145 146 case XDR_DECODE: 147 #ifdef IEEEFP 148 rv = XDR_GETLONG(xdrs, &tmpl); 149 *(int32_t *)fp = tmpl; 150 return (rv); 151 #else 152 vsp = (struct vax_single *)fp; 153 if (!XDR_GETLONG(xdrs, (long *)&is)) 154 return (FALSE); 155 for (i = 0, lim = sgl_limits; 156 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 157 i++, lim++) { 158 if ((is.exp == lim->ieee.exp) && 159 (is.mantissa == lim->ieee.mantissa)) { 160 *vsp = lim->s; 161 goto doneit; 162 } 163 } 164 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 165 vsp->mantissa2 = is.mantissa; 166 vsp->mantissa1 = (is.mantissa >> 16); 167 doneit: 168 vsp->sign = is.sign; 169 return (TRUE); 170 #endif 171 172 case XDR_FREE: 173 return (TRUE); 174 } 175 return (FALSE); 176 } 177 178 #ifdef vax 179 /* What IEEE double precision floating point looks like on a Vax */ 180 struct ieee_double { 181 unsigned int mantissa1 : 20; 182 unsigned int exp : 11; 183 unsigned int sign : 1; 184 unsigned int mantissa2 : 32; 185 }; 186 187 /* Vax double precision floating point */ 188 struct vax_double { 189 unsigned int mantissa1 : 7; 190 unsigned int exp : 8; 191 unsigned int sign : 1; 192 unsigned int mantissa2 : 16; 193 unsigned int mantissa3 : 16; 194 unsigned int mantissa4 : 16; 195 }; 196 197 #define VAX_DBL_BIAS 0x81 198 #define IEEE_DBL_BIAS 0x3ff 199 #define MASK(nbits) ((1 << nbits) - 1) 200 201 static struct dbl_limits { 202 struct vax_double d; 203 struct ieee_double ieee; 204 } dbl_limits[2] = { 205 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 206 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 207 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 208 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 209 }; 210 211 #endif /* vax */ 212 213 214 bool_t 215 xdr_double(xdrs, dp) 216 register XDR *xdrs; 217 double *dp; 218 { 219 #ifdef IEEEFP 220 register int32_t *i32p; 221 bool_t rv; 222 long tmpl; 223 #else 224 register long *lp; 225 struct ieee_double id; 226 struct vax_double vd; 227 register struct dbl_limits *lim; 228 int i; 229 #endif 230 231 switch (xdrs->x_op) { 232 233 case XDR_ENCODE: 234 #ifdef IEEEFP 235 i32p = (int32_t *)dp; 236 #if BYTE_ORDER == BIG_ENDIAN 237 tmpl = *i32p++; 238 rv = XDR_PUTLONG(xdrs, &tmpl); 239 if (!rv) 240 return (rv); 241 tmpl = *i32p; 242 rv = XDR_PUTLONG(xdrs, &tmpl); 243 #else 244 tmpl = *(i32p+1); 245 rv = XDR_PUTLONG(xdrs, &tmpl); 246 if (!rv) 247 return (rv); 248 tmpl = *i32p; 249 rv = XDR_PUTLONG(xdrs, &tmpl); 250 #endif 251 return (rv); 252 #else 253 vd = *((struct vax_double *)dp); 254 for (i = 0, lim = dbl_limits; 255 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 256 i++, lim++) { 257 if ((vd.mantissa4 == lim->d.mantissa4) && 258 (vd.mantissa3 == lim->d.mantissa3) && 259 (vd.mantissa2 == lim->d.mantissa2) && 260 (vd.mantissa1 == lim->d.mantissa1) && 261 (vd.exp == lim->d.exp)) { 262 id = lim->ieee; 263 goto shipit; 264 } 265 } 266 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 267 id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); 268 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 269 (vd.mantissa3 << 13) | 270 ((vd.mantissa4 >> 3) & MASK(13)); 271 shipit: 272 id.sign = vd.sign; 273 lp = (long *)&id; 274 return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); 275 #endif 276 277 case XDR_DECODE: 278 #ifdef IEEEFP 279 i32p = (int32_t *)dp; 280 #if BYTE_ORDER == BIG_ENDIAN 281 rv = XDR_GETLONG(xdrs, &tmpl); 282 *i32p++ = tmpl; 283 if (!rv) 284 return (rv); 285 rv = XDR_GETLONG(xdrs, &tmpl); 286 *i32p = tmpl; 287 #else 288 rv = XDR_GETLONG(xdrs, &tmpl); 289 *(i32p+1) = tmpl; 290 if (!rv) 291 return (rv); 292 rv = XDR_GETLONG(xdrs, &tmpl); 293 *i32p = tmpl; 294 #endif 295 return (rv); 296 #else 297 lp = (long *)&id; 298 if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) 299 return (FALSE); 300 for (i = 0, lim = dbl_limits; 301 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 302 i++, lim++) { 303 if ((id.mantissa2 == lim->ieee.mantissa2) && 304 (id.mantissa1 == lim->ieee.mantissa1) && 305 (id.exp == lim->ieee.exp)) { 306 vd = lim->d; 307 goto doneit; 308 } 309 } 310 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 311 vd.mantissa1 = (id.mantissa1 >> 13); 312 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 313 (id.mantissa2 >> 29); 314 vd.mantissa3 = (id.mantissa2 >> 13); 315 vd.mantissa4 = (id.mantissa2 << 3); 316 doneit: 317 vd.sign = id.sign; 318 *dp = *((double *)&vd); 319 return (TRUE); 320 #endif 321 322 case XDR_FREE: 323 return (TRUE); 324 } 325 return (FALSE); 326 } 327