xdr_float.c revision 74462
1181638Skmacy/* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ */ 2181638Skmacy 3181638Skmacy/* 4181638Skmacy * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5181638Skmacy * unrestricted use provided that this legend is included on all tape 6181638Skmacy * media and as a part of the software program in whole or part. Users 7181638Skmacy * may copy or modify Sun RPC without charge, but are not authorized 8181638Skmacy * to license or distribute it to anyone else except as part of a product or 9181638Skmacy * program developed by the user. 10181638Skmacy * 11181638Skmacy * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12181638Skmacy * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13181638Skmacy * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14181638Skmacy * 15181638Skmacy * Sun RPC is provided with no support and without any obligation on the 16181638Skmacy * part of Sun Microsystems, Inc. to assist in its use, correction, 17181638Skmacy * modification or enhancement. 18181638Skmacy * 19181638Skmacy * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20181638Skmacy * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21181638Skmacy * OR ANY PART THEREOF. 22181638Skmacy * 23181638Skmacy * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24181638Skmacy * or profits or other special, indirect and consequential damages, even if 25181638Skmacy * Sun has been advised of the possibility of such damages. 26181638Skmacy * 27181638Skmacy * Sun Microsystems, Inc. 28181638Skmacy * 2550 Garcia Avenue 29181638Skmacy * Mountain View, California 94043 30181638Skmacy */ 31181638Skmacy 32181638Skmacy#include <sys/cdefs.h> 33181638Skmacy#if defined(LIBC_SCCS) && !defined(lint) 34181638Skmacystatic char *sccsid = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; 35181638Skmacystatic char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC"; 36181638Skmacystatic char *rcsid = "$FreeBSD: head/lib/libc/xdr/xdr_float.c 74462 2001-03-19 12:50:13Z alfred $"; 37181638Skmacy#endif 38181638Skmacy 39181638Skmacy/* 40181638Skmacy * xdr_float.c, Generic XDR routines implementation. 41181638Skmacy * 42181638Skmacy * Copyright (C) 1984, Sun Microsystems, Inc. 43181638Skmacy * 44181638Skmacy * These are the "floating point" xdr routines used to (de)serialize 45181638Skmacy * most common data items. See xdr.h for more info on the interface to 46181638Skmacy * xdr. 47181638Skmacy */ 48181638Skmacy 49181638Skmacy#include "namespace.h" 50181638Skmacy#include <sys/types.h> 51181638Skmacy#include <sys/param.h> 52181638Skmacy 53181638Skmacy#include <stdio.h> 54181638Skmacy 55181638Skmacy#include <rpc/types.h> 56181638Skmacy#include <rpc/xdr.h> 57181638Skmacy#include "un-namespace.h" 58181638Skmacy 59181638Skmacy/* 60181638Skmacy * NB: Not portable. 61181638Skmacy * This routine works on machines with IEEE754 FP and Vaxen. 62181638Skmacy */ 63181638Skmacy 64181638Skmacy#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ 65181638Skmacy defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ 66181638Skmacy defined(__arm32__) || defined(__ppc__) || defined(__ia64__) || \ 67181638Skmacy defined(__arm26__) 68181638Skmacy#include <machine/endian.h> 69181638Skmacy#define IEEEFP 70181638Skmacy#endif 71181638Skmacy 72181638Skmacy#if defined(__vax__) 73181638Skmacy 74181638Skmacy/* What IEEE single precision floating point looks like on a Vax */ 75181638Skmacystruct ieee_single { 76181638Skmacy unsigned int mantissa: 23; 77181638Skmacy unsigned int exp : 8; 78181638Skmacy unsigned int sign : 1; 79181638Skmacy}; 80181638Skmacy 81181638Skmacy/* Vax single precision floating point */ 82181638Skmacystruct vax_single { 83181638Skmacy unsigned int mantissa1 : 7; 84181638Skmacy unsigned int exp : 8; 85181638Skmacy unsigned int sign : 1; 86181638Skmacy unsigned int mantissa2 : 16; 87181638Skmacy}; 88181638Skmacy 89181638Skmacy#define VAX_SNG_BIAS 0x81 90181638Skmacy#define IEEE_SNG_BIAS 0x7f 91181638Skmacy 92181638Skmacystatic struct sgl_limits { 93181638Skmacy struct vax_single s; 94181638Skmacy struct ieee_single ieee; 95181638Skmacy} sgl_limits[2] = { 96181638Skmacy {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 97181638Skmacy { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 98181638Skmacy {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 99181638Skmacy { 0x0, 0x0, 0x0 }} /* Min IEEE */ 100181638Skmacy}; 101181638Skmacy#endif /* vax */ 102181638Skmacy 103181638Skmacybool_t 104181638Skmacyxdr_float(xdrs, fp) 105181638Skmacy XDR *xdrs; 106181638Skmacy float *fp; 107181638Skmacy{ 108181638Skmacy#ifndef IEEEFP 109181638Skmacy struct ieee_single is; 110181638Skmacy struct vax_single vs, *vsp; 111181638Skmacy struct sgl_limits *lim; 112181638Skmacy int i; 113181638Skmacy#endif 114181638Skmacy switch (xdrs->x_op) { 115181638Skmacy 116181638Skmacy case XDR_ENCODE: 117181638Skmacy#ifdef IEEEFP 118181638Skmacy return (XDR_PUTINT32(xdrs, (int32_t *)fp)); 119181638Skmacy#else 120181638Skmacy vs = *((struct vax_single *)fp); 121181638Skmacy for (i = 0, lim = sgl_limits; 122181638Skmacy i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 123181638Skmacy i++, lim++) { 124181638Skmacy if ((vs.mantissa2 == lim->s.mantissa2) && 125181638Skmacy (vs.exp == lim->s.exp) && 126181638Skmacy (vs.mantissa1 == lim->s.mantissa1)) { 127181638Skmacy is = lim->ieee; 128181638Skmacy goto shipit; 129181638Skmacy } 130181638Skmacy } 131181638Skmacy is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; 132181638Skmacy is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 133181638Skmacy shipit: 134181638Skmacy is.sign = vs.sign; 135181638Skmacy return (XDR_PUTINT32(xdrs, (int32_t *)&is)); 136181638Skmacy#endif 137181638Skmacy 138181638Skmacy case XDR_DECODE: 139181638Skmacy#ifdef IEEEFP 140 return (XDR_GETINT32(xdrs, (int32_t *)fp)); 141#else 142 vsp = (struct vax_single *)fp; 143 if (!XDR_GETINT32(xdrs, (int32_t *)&is)) 144 return (FALSE); 145 for (i = 0, lim = sgl_limits; 146 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 147 i++, lim++) { 148 if ((is.exp == lim->ieee.exp) && 149 (is.mantissa == lim->ieee.mantissa)) { 150 *vsp = lim->s; 151 goto doneit; 152 } 153 } 154 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 155 vsp->mantissa2 = is.mantissa; 156 vsp->mantissa1 = (is.mantissa >> 16); 157 doneit: 158 vsp->sign = is.sign; 159 return (TRUE); 160#endif 161 162 case XDR_FREE: 163 return (TRUE); 164 } 165 /* NOTREACHED */ 166 return (FALSE); 167} 168 169#if defined(__vax__) 170/* What IEEE double precision floating point looks like on a Vax */ 171struct ieee_double { 172 unsigned int mantissa1 : 20; 173 unsigned int exp : 11; 174 unsigned int sign : 1; 175 unsigned int mantissa2 : 32; 176}; 177 178/* Vax double precision floating point */ 179struct vax_double { 180 unsigned int mantissa1 : 7; 181 unsigned int exp : 8; 182 unsigned int sign : 1; 183 unsigned int mantissa2 : 16; 184 unsigned int mantissa3 : 16; 185 unsigned int mantissa4 : 16; 186}; 187 188#define VAX_DBL_BIAS 0x81 189#define IEEE_DBL_BIAS 0x3ff 190#define MASK(nbits) ((1 << nbits) - 1) 191 192static struct dbl_limits { 193 struct vax_double d; 194 struct ieee_double ieee; 195} dbl_limits[2] = { 196 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 197 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 198 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 199 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 200}; 201 202#endif /* vax */ 203 204 205bool_t 206xdr_double(xdrs, dp) 207 XDR *xdrs; 208 double *dp; 209{ 210#ifdef IEEEFP 211 int32_t *i32p; 212 bool_t rv; 213#else 214 int32_t *lp; 215 struct ieee_double id; 216 struct vax_double vd; 217 struct dbl_limits *lim; 218 int i; 219#endif 220 221 switch (xdrs->x_op) { 222 223 case XDR_ENCODE: 224#ifdef IEEEFP 225 i32p = (int32_t *)(void *)dp; 226#if BYTE_ORDER == BIG_ENDIAN 227 rv = XDR_PUTINT32(xdrs, i32p); 228 if (!rv) 229 return (rv); 230 rv = XDR_PUTINT32(xdrs, i32p+1); 231#else 232 rv = XDR_PUTINT32(xdrs, i32p+1); 233 if (!rv) 234 return (rv); 235 rv = XDR_PUTINT32(xdrs, i32p); 236#endif 237 return (rv); 238#else 239 vd = *((struct vax_double *)dp); 240 for (i = 0, lim = dbl_limits; 241 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 242 i++, lim++) { 243 if ((vd.mantissa4 == lim->d.mantissa4) && 244 (vd.mantissa3 == lim->d.mantissa3) && 245 (vd.mantissa2 == lim->d.mantissa2) && 246 (vd.mantissa1 == lim->d.mantissa1) && 247 (vd.exp == lim->d.exp)) { 248 id = lim->ieee; 249 goto shipit; 250 } 251 } 252 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 253 id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); 254 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 255 (vd.mantissa3 << 13) | 256 ((vd.mantissa4 >> 3) & MASK(13)); 257 shipit: 258 id.sign = vd.sign; 259 lp = (int32_t *)&id; 260 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 261#endif 262 263 case XDR_DECODE: 264#ifdef IEEEFP 265 i32p = (int32_t *)(void *)dp; 266#if BYTE_ORDER == BIG_ENDIAN 267 rv = XDR_GETINT32(xdrs, i32p); 268 if (!rv) 269 return (rv); 270 rv = XDR_GETINT32(xdrs, i32p+1); 271#else 272 rv = XDR_GETINT32(xdrs, i32p+1); 273 if (!rv) 274 return (rv); 275 rv = XDR_GETINT32(xdrs, i32p); 276#endif 277 return (rv); 278#else 279 lp = (int32_t *)&id; 280 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 281 return (FALSE); 282 for (i = 0, lim = dbl_limits; 283 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 284 i++, lim++) { 285 if ((id.mantissa2 == lim->ieee.mantissa2) && 286 (id.mantissa1 == lim->ieee.mantissa1) && 287 (id.exp == lim->ieee.exp)) { 288 vd = lim->d; 289 goto doneit; 290 } 291 } 292 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 293 vd.mantissa1 = (id.mantissa1 >> 13); 294 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 295 (id.mantissa2 >> 29); 296 vd.mantissa3 = (id.mantissa2 >> 13); 297 vd.mantissa4 = (id.mantissa2 << 3); 298 doneit: 299 vd.sign = id.sign; 300 *dp = *((double *)&vd); 301 return (TRUE); 302#endif 303 304 case XDR_FREE: 305 return (TRUE); 306 } 307 /* NOTREACHED */ 308 return (FALSE); 309} 310