xref: /freebsd/sys/powerpc/fpu/fpu_explode.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
17e76048aSMarcel Moolenaar /*	$NetBSD: fpu_explode.c,v 1.6 2005/12/11 12:18:42 christos Exp $ */
27e76048aSMarcel Moolenaar 
3*51369649SPedro F. Giffuni /*-
4*51369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
5*51369649SPedro F. Giffuni  *
67e76048aSMarcel Moolenaar  * Copyright (c) 1992, 1993
77e76048aSMarcel Moolenaar  *	The Regents of the University of California.  All rights reserved.
87e76048aSMarcel Moolenaar  *
97e76048aSMarcel Moolenaar  * This software was developed by the Computer Systems Engineering group
107e76048aSMarcel Moolenaar  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
117e76048aSMarcel Moolenaar  * contributed to Berkeley.
127e76048aSMarcel Moolenaar  *
137e76048aSMarcel Moolenaar  * All advertising materials mentioning features or use of this software
147e76048aSMarcel Moolenaar  * must display the following acknowledgement:
157e76048aSMarcel Moolenaar  *	This product includes software developed by the University of
167e76048aSMarcel Moolenaar  *	California, Lawrence Berkeley Laboratory.
177e76048aSMarcel Moolenaar  *
187e76048aSMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
197e76048aSMarcel Moolenaar  * modification, are permitted provided that the following conditions
207e76048aSMarcel Moolenaar  * are met:
217e76048aSMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
227e76048aSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
237e76048aSMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
247e76048aSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
257e76048aSMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
267e76048aSMarcel Moolenaar  * 3. Neither the name of the University nor the names of its contributors
277e76048aSMarcel Moolenaar  *    may be used to endorse or promote products derived from this software
287e76048aSMarcel Moolenaar  *    without specific prior written permission.
297e76048aSMarcel Moolenaar  *
307e76048aSMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
317e76048aSMarcel Moolenaar  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
327e76048aSMarcel Moolenaar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
337e76048aSMarcel Moolenaar  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
347e76048aSMarcel Moolenaar  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
357e76048aSMarcel Moolenaar  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
367e76048aSMarcel Moolenaar  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
377e76048aSMarcel Moolenaar  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
387e76048aSMarcel Moolenaar  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
397e76048aSMarcel Moolenaar  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
407e76048aSMarcel Moolenaar  * SUCH DAMAGE.
417e76048aSMarcel Moolenaar  */
427e76048aSMarcel Moolenaar 
437e76048aSMarcel Moolenaar /*
447e76048aSMarcel Moolenaar  * FPU subroutines: `explode' the machine's `packed binary' format numbers
457e76048aSMarcel Moolenaar  * into our internal format.
467e76048aSMarcel Moolenaar  */
477e76048aSMarcel Moolenaar 
487e76048aSMarcel Moolenaar #include <sys/types.h>
492aa95aceSPeter Grehan #include <sys/systm.h>
507e76048aSMarcel Moolenaar 
517e76048aSMarcel Moolenaar #include <machine/fpu.h>
527e76048aSMarcel Moolenaar #include <machine/ieee.h>
53aa59d767SJohn Baldwin #include <machine/pcb.h>
547e76048aSMarcel Moolenaar 
557e76048aSMarcel Moolenaar #include <powerpc/fpu/fpu_arith.h>
567e76048aSMarcel Moolenaar #include <powerpc/fpu/fpu_emu.h>
577e76048aSMarcel Moolenaar #include <powerpc/fpu/fpu_extern.h>
587e76048aSMarcel Moolenaar #include <powerpc/fpu/fpu_instr.h>
597e76048aSMarcel Moolenaar 
607e76048aSMarcel Moolenaar /*
617e76048aSMarcel Moolenaar  * N.B.: in all of the following, we assume the FP format is
627e76048aSMarcel Moolenaar  *
637e76048aSMarcel Moolenaar  *	---------------------------
647e76048aSMarcel Moolenaar  *	| s | exponent | fraction |
657e76048aSMarcel Moolenaar  *	---------------------------
667e76048aSMarcel Moolenaar  *
677e76048aSMarcel Moolenaar  * (which represents -1**s * 1.fraction * 2**exponent), so that the
687e76048aSMarcel Moolenaar  * sign bit is way at the top (bit 31), the exponent is next, and
697e76048aSMarcel Moolenaar  * then the remaining bits mark the fraction.  A zero exponent means
707e76048aSMarcel Moolenaar  * zero or denormalized (0.fraction rather than 1.fraction), and the
717e76048aSMarcel Moolenaar  * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
727e76048aSMarcel Moolenaar  *
737e76048aSMarcel Moolenaar  * Since the sign bit is always the topmost bit---this holds even for
747e76048aSMarcel Moolenaar  * integers---we set that outside all the *tof functions.  Each function
757e76048aSMarcel Moolenaar  * returns the class code for the new number (but note that we use
767e76048aSMarcel Moolenaar  * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
777e76048aSMarcel Moolenaar  */
787e76048aSMarcel Moolenaar 
797e76048aSMarcel Moolenaar /*
807e76048aSMarcel Moolenaar  * int -> fpn.
817e76048aSMarcel Moolenaar  */
827e76048aSMarcel Moolenaar int
fpu_itof(struct fpn * fp,u_int i)837e76048aSMarcel Moolenaar fpu_itof(struct fpn *fp, u_int i)
847e76048aSMarcel Moolenaar {
857e76048aSMarcel Moolenaar 
867e76048aSMarcel Moolenaar 	if (i == 0)
877e76048aSMarcel Moolenaar 		return (FPC_ZERO);
887e76048aSMarcel Moolenaar 	/*
897e76048aSMarcel Moolenaar 	 * The value FP_1 represents 2^FP_LG, so set the exponent
907e76048aSMarcel Moolenaar 	 * there and let normalization fix it up.  Convert negative
917e76048aSMarcel Moolenaar 	 * numbers to sign-and-magnitude.  Note that this relies on
927e76048aSMarcel Moolenaar 	 * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
937e76048aSMarcel Moolenaar 	 */
947e76048aSMarcel Moolenaar 	fp->fp_exp = FP_LG;
957e76048aSMarcel Moolenaar 	fp->fp_mant[0] = (int)i < 0 ? -i : i;
967e76048aSMarcel Moolenaar 	fp->fp_mant[1] = 0;
977e76048aSMarcel Moolenaar 	fp->fp_mant[2] = 0;
987e76048aSMarcel Moolenaar 	fp->fp_mant[3] = 0;
997e76048aSMarcel Moolenaar 	fpu_norm(fp);
1007e76048aSMarcel Moolenaar 	return (FPC_NUM);
1017e76048aSMarcel Moolenaar }
1027e76048aSMarcel Moolenaar 
1037e76048aSMarcel Moolenaar /*
1047e76048aSMarcel Moolenaar  * 64-bit int -> fpn.
1057e76048aSMarcel Moolenaar  */
1067e76048aSMarcel Moolenaar int
fpu_xtof(struct fpn * fp,u_int64_t i)1077e76048aSMarcel Moolenaar fpu_xtof(struct fpn *fp, u_int64_t i)
1087e76048aSMarcel Moolenaar {
1097e76048aSMarcel Moolenaar 
1107e76048aSMarcel Moolenaar 	if (i == 0)
1117e76048aSMarcel Moolenaar 		return (FPC_ZERO);
1127e76048aSMarcel Moolenaar 	/*
1137e76048aSMarcel Moolenaar 	 * The value FP_1 represents 2^FP_LG, so set the exponent
1147e76048aSMarcel Moolenaar 	 * there and let normalization fix it up.  Convert negative
1157e76048aSMarcel Moolenaar 	 * numbers to sign-and-magnitude.  Note that this relies on
1167e76048aSMarcel Moolenaar 	 * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
1177e76048aSMarcel Moolenaar 	 */
1187e76048aSMarcel Moolenaar 	fp->fp_exp = FP_LG2;
1197e76048aSMarcel Moolenaar 	*((int64_t*)fp->fp_mant) = (int64_t)i < 0 ? -i : i;
1207e76048aSMarcel Moolenaar 	fp->fp_mant[2] = 0;
1217e76048aSMarcel Moolenaar 	fp->fp_mant[3] = 0;
1227e76048aSMarcel Moolenaar 	fpu_norm(fp);
1237e76048aSMarcel Moolenaar 	return (FPC_NUM);
1247e76048aSMarcel Moolenaar }
1257e76048aSMarcel Moolenaar 
1267e76048aSMarcel Moolenaar #define	mask(nbits) ((1L << (nbits)) - 1)
1277e76048aSMarcel Moolenaar 
1287e76048aSMarcel Moolenaar /*
1297e76048aSMarcel Moolenaar  * All external floating formats convert to internal in the same manner,
1307e76048aSMarcel Moolenaar  * as defined here.  Note that only normals get an implied 1.0 inserted.
1317e76048aSMarcel Moolenaar  */
1327e76048aSMarcel Moolenaar #define	FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
1337e76048aSMarcel Moolenaar 	if (exp == 0) { \
1347e76048aSMarcel Moolenaar 		if (allfrac == 0) \
1357e76048aSMarcel Moolenaar 			return (FPC_ZERO); \
1367e76048aSMarcel Moolenaar 		fp->fp_exp = 1 - expbias; \
1377e76048aSMarcel Moolenaar 		fp->fp_mant[0] = f0; \
1387e76048aSMarcel Moolenaar 		fp->fp_mant[1] = f1; \
1397e76048aSMarcel Moolenaar 		fp->fp_mant[2] = f2; \
1407e76048aSMarcel Moolenaar 		fp->fp_mant[3] = f3; \
1417e76048aSMarcel Moolenaar 		fpu_norm(fp); \
1427e76048aSMarcel Moolenaar 		return (FPC_NUM); \
1437e76048aSMarcel Moolenaar 	} \
1447e76048aSMarcel Moolenaar 	if (exp == (2 * expbias + 1)) { \
1457e76048aSMarcel Moolenaar 		if (allfrac == 0) \
1467e76048aSMarcel Moolenaar 			return (FPC_INF); \
1477e76048aSMarcel Moolenaar 		fp->fp_mant[0] = f0; \
1487e76048aSMarcel Moolenaar 		fp->fp_mant[1] = f1; \
1497e76048aSMarcel Moolenaar 		fp->fp_mant[2] = f2; \
1507e76048aSMarcel Moolenaar 		fp->fp_mant[3] = f3; \
1517e76048aSMarcel Moolenaar 		return (FPC_QNAN); \
1527e76048aSMarcel Moolenaar 	} \
1537e76048aSMarcel Moolenaar 	fp->fp_exp = exp - expbias; \
1547e76048aSMarcel Moolenaar 	fp->fp_mant[0] = FP_1 | f0; \
1557e76048aSMarcel Moolenaar 	fp->fp_mant[1] = f1; \
1567e76048aSMarcel Moolenaar 	fp->fp_mant[2] = f2; \
1577e76048aSMarcel Moolenaar 	fp->fp_mant[3] = f3; \
1587e76048aSMarcel Moolenaar 	return (FPC_NUM)
1597e76048aSMarcel Moolenaar 
1607e76048aSMarcel Moolenaar /*
1617e76048aSMarcel Moolenaar  * 32-bit single precision -> fpn.
1627e76048aSMarcel Moolenaar  * We assume a single occupies at most (64-FP_LG) bits in the internal
1637e76048aSMarcel Moolenaar  * format: i.e., needs at most fp_mant[0] and fp_mant[1].
1647e76048aSMarcel Moolenaar  */
1657e76048aSMarcel Moolenaar int
fpu_stof(struct fpn * fp,u_int i)1667e76048aSMarcel Moolenaar fpu_stof(struct fpn *fp, u_int i)
1677e76048aSMarcel Moolenaar {
1687e76048aSMarcel Moolenaar 	int exp;
1697e76048aSMarcel Moolenaar 	u_int frac, f0, f1;
1707e76048aSMarcel Moolenaar #define SNG_SHIFT (SNG_FRACBITS - FP_LG)
1717e76048aSMarcel Moolenaar 
1727e76048aSMarcel Moolenaar 	exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
1737e76048aSMarcel Moolenaar 	frac = i & mask(SNG_FRACBITS);
1747e76048aSMarcel Moolenaar 	f0 = frac >> SNG_SHIFT;
1757e76048aSMarcel Moolenaar 	f1 = frac << (32 - SNG_SHIFT);
1767e76048aSMarcel Moolenaar 	FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
1777e76048aSMarcel Moolenaar }
1787e76048aSMarcel Moolenaar 
1797e76048aSMarcel Moolenaar /*
1807e76048aSMarcel Moolenaar  * 64-bit double -> fpn.
1817e76048aSMarcel Moolenaar  * We assume this uses at most (96-FP_LG) bits.
1827e76048aSMarcel Moolenaar  */
1837e76048aSMarcel Moolenaar int
fpu_dtof(struct fpn * fp,u_int i,u_int j)1847e76048aSMarcel Moolenaar fpu_dtof(struct fpn *fp, u_int i, u_int j)
1857e76048aSMarcel Moolenaar {
1867e76048aSMarcel Moolenaar 	int exp;
1877e76048aSMarcel Moolenaar 	u_int frac, f0, f1, f2;
1887e76048aSMarcel Moolenaar #define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
1897e76048aSMarcel Moolenaar 
1907e76048aSMarcel Moolenaar 	exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
1917e76048aSMarcel Moolenaar 	frac = i & mask(DBL_FRACBITS - 32);
1927e76048aSMarcel Moolenaar 	f0 = frac >> DBL_SHIFT;
1937e76048aSMarcel Moolenaar 	f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
1947e76048aSMarcel Moolenaar 	f2 = j << (32 - DBL_SHIFT);
1957e76048aSMarcel Moolenaar 	frac |= j;
1967e76048aSMarcel Moolenaar 	FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
1977e76048aSMarcel Moolenaar }
1987e76048aSMarcel Moolenaar 
1997e76048aSMarcel Moolenaar /*
2007e76048aSMarcel Moolenaar  * Explode the contents of a register / regpair / regquad.
2017e76048aSMarcel Moolenaar  * If the input is a signalling NaN, an NV (invalid) exception
2027e76048aSMarcel Moolenaar  * will be set.  (Note that nothing but NV can occur until ALU
2037e76048aSMarcel Moolenaar  * operations are performed.)
2047e76048aSMarcel Moolenaar  */
2057e76048aSMarcel Moolenaar void
fpu_explode(struct fpemu * fe,struct fpn * fp,int type,int reg)2067e76048aSMarcel Moolenaar fpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg)
2077e76048aSMarcel Moolenaar {
2087e76048aSMarcel Moolenaar 	u_int s, *space;
2097e76048aSMarcel Moolenaar 	u_int64_t l, *xspace;
2107e76048aSMarcel Moolenaar 
211aa59d767SJohn Baldwin 	xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr;
2127e76048aSMarcel Moolenaar 	l = xspace[0];
213aa59d767SJohn Baldwin 	space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr;
2147e76048aSMarcel Moolenaar 	s = space[0];
2157e76048aSMarcel Moolenaar 	fp->fp_sign = s >> 31;
2167e76048aSMarcel Moolenaar 	fp->fp_sticky = 0;
2177e76048aSMarcel Moolenaar 	switch (type) {
2187e76048aSMarcel Moolenaar 	case FTYPE_LNG:
2197e76048aSMarcel Moolenaar 		s = fpu_xtof(fp, l);
2207e76048aSMarcel Moolenaar 		break;
2217e76048aSMarcel Moolenaar 
2227e76048aSMarcel Moolenaar 	case FTYPE_INT:
2237e76048aSMarcel Moolenaar 		s = fpu_itof(fp, space[1]);
2247e76048aSMarcel Moolenaar 		break;
2257e76048aSMarcel Moolenaar 
2267e76048aSMarcel Moolenaar 	case FTYPE_SNG:
2277e76048aSMarcel Moolenaar 		s = fpu_stof(fp, s);
2287e76048aSMarcel Moolenaar 		break;
2297e76048aSMarcel Moolenaar 
2307e76048aSMarcel Moolenaar 	case FTYPE_DBL:
2317e76048aSMarcel Moolenaar 		s = fpu_dtof(fp, s, space[1]);
2327e76048aSMarcel Moolenaar 		break;
2337e76048aSMarcel Moolenaar 
234b8201e1cSNathan Whitehorn 	default:
2357e76048aSMarcel Moolenaar 		panic("fpu_explode");
2367e76048aSMarcel Moolenaar 		panic("fpu_explode: invalid type %d", type);
2377e76048aSMarcel Moolenaar 	}
2387e76048aSMarcel Moolenaar 
2397e76048aSMarcel Moolenaar 	if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
2407e76048aSMarcel Moolenaar 		/*
2417e76048aSMarcel Moolenaar 		 * Input is a signalling NaN.  All operations that return
2427e76048aSMarcel Moolenaar 		 * an input NaN operand put it through a ``NaN conversion'',
2437e76048aSMarcel Moolenaar 		 * which basically just means ``turn on the quiet bit''.
2447e76048aSMarcel Moolenaar 		 * We do this here so that all NaNs internally look quiet
2457e76048aSMarcel Moolenaar 		 * (we can tell signalling ones by their class).
2467e76048aSMarcel Moolenaar 		 */
2477e76048aSMarcel Moolenaar 		fp->fp_mant[0] |= FP_QUIETBIT;
2487e76048aSMarcel Moolenaar 		fe->fe_cx = FPSCR_VXSNAN;	/* assert invalid operand */
2497e76048aSMarcel Moolenaar 		s = FPC_SNAN;
2507e76048aSMarcel Moolenaar 	}
2517e76048aSMarcel Moolenaar 	fp->fp_class = s;
2527e76048aSMarcel Moolenaar 	DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' :
2537e76048aSMarcel Moolenaar 		((type == FTYPE_INT) ? 'i' :
2547e76048aSMarcel Moolenaar 			((type == FTYPE_SNG) ? 's' :
2557e76048aSMarcel Moolenaar 				((type == FTYPE_DBL) ? 'd' : '?'))),
2567e76048aSMarcel Moolenaar 		reg));
2577e76048aSMarcel Moolenaar 	DUMPFPN(FPE_REG, fp);
2587e76048aSMarcel Moolenaar 	DPRINTF(FPE_REG, ("\n"));
2597e76048aSMarcel Moolenaar }
260