1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * Portions of this source code were derived from Berkeley 31 * 4.3 BSD under license from the Regents of the University of 32 * California. 33 */ 34 /* 35 * Copyright 2011 Jason King. All rights reserved 36 */ 37 38 /* 39 * Generic XDR routines impelmentation. 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 "mt.h" 47 #include <sys/types.h> 48 #include <stdio.h> 49 #include <values.h> 50 #include <rpc/types.h> 51 #include <rpc/xdr.h> 52 #include <sys/byteorder.h> 53 54 #ifdef _IEEE_754 55 56 /* 57 * The OTW format is IEEE 754 with big endian ordering. 58 */ 59 bool_t 60 xdr_float(XDR *xdrs, float *fp) 61 { 62 switch (xdrs->x_op) { 63 64 case XDR_ENCODE: 65 return (XDR_PUTINT32(xdrs, (int *)fp)); 66 67 case XDR_DECODE: 68 return (XDR_GETINT32(xdrs, (int *)fp)); 69 70 case XDR_FREE: 71 return (TRUE); 72 } 73 return (FALSE); 74 } 75 76 bool_t 77 xdr_double(XDR *xdrs, double *dp) 78 { 79 int64_t *i64p = (int64_t *)dp; 80 int64_t val; 81 bool_t ret; 82 83 switch (xdrs->x_op) { 84 85 case XDR_ENCODE: 86 val = BE_64(*i64p); 87 return (XDR_PUTBYTES(xdrs, (char *)&val, sizeof (val))); 88 89 case XDR_DECODE: 90 ret = XDR_GETBYTES(xdrs, (char *)dp, sizeof (double)); 91 if (ret) 92 *i64p = BE_64(*i64p); 93 return (ret); 94 95 case XDR_FREE: 96 return (TRUE); 97 } 98 99 return (FALSE); 100 } 101 102 /* ARGSUSED */ 103 bool_t 104 xdr_quadruple(XDR *xdrs, long double *fp) 105 { 106 /* 107 * The Sparc uses IEEE FP encoding, so just do a byte copy 108 */ 109 110 #if !defined(sparc) 111 return (FALSE); 112 #else 113 switch (xdrs->x_op) { 114 case XDR_ENCODE: 115 return (XDR_PUTBYTES(xdrs, (char *)fp, sizeof (long double))); 116 case XDR_DECODE: 117 return (XDR_GETBYTES(xdrs, (char *)fp, sizeof (long double))); 118 case XDR_FREE: 119 return (TRUE); 120 } 121 return (FALSE); 122 #endif 123 } 124 125 #else 126 127 #warn No platform specific implementation defined for floats 128 129 bool_t 130 xdr_float(XDR *xdrs, float *fp) 131 { 132 /* 133 * Every machine can do this, its just not very efficient. 134 * In addtion, some rounding errors may occur do to the 135 * calculations involved. 136 */ 137 float f; 138 int neg = 0; 139 int exp = 0; 140 int32_t val; 141 142 switch (xdrs->x_op) { 143 case XDR_ENCODE: 144 f = *fp; 145 if (f == 0) { 146 val = 0; 147 return (XDR_PUTINT32(xdrs, &val)); 148 } 149 if (f < 0) { 150 f = 0 - f; 151 neg = 1; 152 } 153 while (f < 1) { 154 f = f * 2; 155 --exp; 156 } 157 while (f >= 2) { 158 f = f/2; 159 ++exp; 160 } 161 if ((exp > 128) || (exp < -127)) { 162 /* over or under flowing ieee exponent */ 163 return (FALSE); 164 } 165 val = neg; 166 val = val << 8; /* for the exponent */ 167 val += 127 + exp; /* 127 is the bias */ 168 val = val << 23; /* for the mantissa */ 169 val += (int32_t)((f - 1) * 8388608); /* 2 ^ 23 */ 170 return (XDR_PUTINT32(xdrs, &val)); 171 172 case XDR_DECODE: 173 /* 174 * It assumes that the decoding machine's float can represent 175 * any value in the range of 176 * ieee largest float = (2 ^ 128) * 0x1.fffff 177 * to 178 * ieee smallest float = (2 ^ -127) * 0x1.00000 179 * In addtion, some rounding errors may occur do to the 180 * calculations involved. 181 */ 182 183 if (!XDR_GETINT32(xdrs, (int32_t *)&val)) 184 return (FALSE); 185 neg = val & 0x80000000; 186 exp = (val & 0x7f800000) >> 23; 187 exp -= 127; /* subtract exponent base */ 188 f = (val & 0x007fffff) * 0.00000011920928955078125; 189 /* 2 ^ -23 */ 190 f++; 191 192 while (exp != 0) { 193 if (exp < 0) { 194 f = f/2.0; 195 ++exp; 196 } else { 197 f = f * 2.0; 198 --exp; 199 } 200 } 201 202 if (neg) 203 f = 0 - f; 204 205 *fp = f; 206 return (TRUE); 207 208 case XDR_FREE: 209 return (TRUE); 210 } 211 212 return (FALSE); 213 } 214 215 bool_t 216 xdr_double(XDR *xdrs, double *dp) 217 { 218 /* 219 * Every machine can do this, its just not very efficient. 220 * In addtion, some rounding errors may occur do to the 221 * calculations involved. 222 */ 223 224 int *lp; 225 double d; 226 int neg = 0; 227 int exp = 0; 228 int32_t val[2]; 229 230 switch (xdrs->x_op) { 231 case XDR_ENCODE: 232 d = *dp; 233 if (d == 0) { 234 val[0] = 0; 235 val[1] = 0; 236 lp = val; 237 return (XDR_PUTINT32(xdrs, lp++) && 238 XDR_PUTINT32(xdrs, lp)); 239 } 240 if (d < 0) { 241 d = 0 - d; 242 neg = 1; 243 } 244 while (d < 1) { 245 d = d * 2; 246 --exp; 247 } 248 while (d >= 2) { 249 d = d/2; 250 ++exp; 251 } 252 if ((exp > 1024) || (exp < -1023)) { 253 /* over or under flowing ieee exponent */ 254 return (FALSE); 255 } 256 val[0] = (neg << 11); /* for the exponent */ 257 val[0] += 1023 + exp; /* 1023 is the bias */ 258 val[0] = val[0] << 20; /* for the mantissa */ 259 val[0] += (int32_t)((d - 1) * 1048576); /* 2 ^ 20 */ 260 val[1] += (uint32_t)((((d - 1) * 1048576) - val[0]) * 261 4294967296); /* 2 ^ 32 */ 262 lp = val; 263 264 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 265 266 case XDR_DECODE: 267 /* 268 * It assumes that the decoding machine's 269 * double can represent any value in the range of 270 * ieee largest double = (2 ^ 1024) * 0x1.fffffffffffff 271 * to 272 * ieee smallest double = (2 ^ -1023) * 0x1.0000000000000 273 * In addtion, some rounding errors may occur do to the 274 * calculations involved. 275 */ 276 277 lp = val; 278 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 279 return (FALSE); 280 neg = val[0] & 0x80000000; 281 exp = (val[0] & 0x7ff00000) >> 20; 282 exp -= 1023; /* subtract exponent base */ 283 d = (val[0] & 0x000fffff) * 0.00000095367431640625; 284 /* 2 ^ -20 */ 285 d += (val[1] * 0.0000000000000002220446049250313); 286 /* 2 ^ -52 */ 287 d++; 288 while (exp != 0) { 289 if (exp < 0) { 290 d = d/2.0; 291 ++exp; 292 } else { 293 d = d * 2.0; 294 --exp; 295 } 296 } 297 if (neg) 298 d = 0 - d; 299 300 *dp = d; 301 return (TRUE); 302 303 case XDR_FREE: 304 return (TRUE); 305 } 306 307 return (FALSE); 308 } 309 310 bool_t 311 xdr_quadruple(XDR *xdrs, long double *fp) 312 { 313 return (FALSE); 314 } 315 316 #endif /* _IEEE_754 */ 317