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