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