xdr_float.c revision 1902
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";*/
33static 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 */
64struct	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 */
71struct	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
81static 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
92bool_t
93xdr_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 */
163struct	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 */
171struct  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
184static 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
197bool_t
198xdr_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