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
xdr_float(XDR * xdrs,float * fp)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
xdr_double(XDR * xdrs,double * dp)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
xdr_quadruple(XDR * xdrs,long double * fp)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
xdr_float(XDR * xdrs,float * fp)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
xdr_double(XDR * xdrs,double * dp)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
xdr_quadruple(XDR * xdrs,long double * fp)311 xdr_quadruple(XDR *xdrs, long double *fp)
312 {
313 return (FALSE);
314 }
315
316 #endif /* _IEEE_754 */
317