xref: /freebsd/sys/powerpc/fpu/fpu_emu.h (revision 29363fb446372cb3f10bc98664e9767c53fbb457)
17e76048aSMarcel Moolenaar /*	$NetBSD: fpu_emu.h,v 1.3 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  * Floating point emulator (tailored for SPARC, but structurally
457e76048aSMarcel Moolenaar  * machine-independent).
467e76048aSMarcel Moolenaar  *
477e76048aSMarcel Moolenaar  * Floating point numbers are carried around internally in an `expanded'
487e76048aSMarcel Moolenaar  * or `unpacked' form consisting of:
497e76048aSMarcel Moolenaar  *	- sign
507e76048aSMarcel Moolenaar  *	- unbiased exponent
517e76048aSMarcel Moolenaar  *	- mantissa (`1.' + 112-bit fraction + guard + round)
527e76048aSMarcel Moolenaar  *	- sticky bit
537e76048aSMarcel Moolenaar  * Any implied `1' bit is inserted, giving a 113-bit mantissa that is
547e76048aSMarcel Moolenaar  * always nonzero.  Additional low-order `guard' and `round' bits are
557e76048aSMarcel Moolenaar  * scrunched in, making the entire mantissa 115 bits long.  This is divided
567e76048aSMarcel Moolenaar  * into four 32-bit words, with `spare' bits left over in the upper part
577e76048aSMarcel Moolenaar  * of the top word (the high bits of fp_mant[0]).  An internal `exploded'
587e76048aSMarcel Moolenaar  * number is thus kept within the half-open interval [1.0,2.0) (but see
597e76048aSMarcel Moolenaar  * the `number classes' below).  This holds even for denormalized numbers:
607e76048aSMarcel Moolenaar  * when we explode an external denorm, we normalize it, introducing low-order
617e76048aSMarcel Moolenaar  * zero bits, so that the rest of the code always sees normalized values.
627e76048aSMarcel Moolenaar  *
637e76048aSMarcel Moolenaar  * Note that a number of our algorithms use the `spare' bits at the top.
647e76048aSMarcel Moolenaar  * The most demanding algorithm---the one for sqrt---depends on two such
657e76048aSMarcel Moolenaar  * bits, so that it can represent values up to (but not including) 8.0,
667e76048aSMarcel Moolenaar  * and then it needs a carry on top of that, so that we need three `spares'.
677e76048aSMarcel Moolenaar  *
687e76048aSMarcel Moolenaar  * The sticky-word is 32 bits so that we can use `OR' operators to goosh
697e76048aSMarcel Moolenaar  * whole words from the mantissa into it.
707e76048aSMarcel Moolenaar  *
717e76048aSMarcel Moolenaar  * All operations are done in this internal extended precision.  According
727e76048aSMarcel Moolenaar  * to Hennesey & Patterson, Appendix A, rounding can be repeated---that is,
737e76048aSMarcel Moolenaar  * it is OK to do a+b in extended precision and then round the result to
747e76048aSMarcel Moolenaar  * single precision---provided single, double, and extended precisions are
757e76048aSMarcel Moolenaar  * `far enough apart' (they always are), but we will try to avoid any such
767e76048aSMarcel Moolenaar  * extra work where possible.
777e76048aSMarcel Moolenaar  */
787e76048aSMarcel Moolenaar struct fpn {
797e76048aSMarcel Moolenaar 	int	fp_class;		/* see below */
807e76048aSMarcel Moolenaar 	int	fp_sign;		/* 0 => positive, 1 => negative */
817e76048aSMarcel Moolenaar 	int	fp_exp;			/* exponent (unbiased) */
827e76048aSMarcel Moolenaar 	int	fp_sticky;		/* nonzero bits lost at right end */
837e76048aSMarcel Moolenaar 	u_int	fp_mant[4];		/* 115-bit mantissa */
847e76048aSMarcel Moolenaar };
857e76048aSMarcel Moolenaar 
867e76048aSMarcel Moolenaar #define	FP_NMANT	115		/* total bits in mantissa (incl g,r) */
877e76048aSMarcel Moolenaar #define	FP_NG		2		/* number of low-order guard bits */
887e76048aSMarcel Moolenaar #define	FP_LG		((FP_NMANT - 1) & 31)	/* log2(1.0) for fp_mant[0] */
897e76048aSMarcel Moolenaar #define	FP_LG2		((FP_NMANT - 1) & 63)	/* log2(1.0) for fp_mant[0] and fp_mant[1] */
907e76048aSMarcel Moolenaar #define	FP_QUIETBIT	(1 << (FP_LG - 1))	/* Quiet bit in NaNs (0.5) */
917e76048aSMarcel Moolenaar #define	FP_1		(1 << FP_LG)		/* 1.0 in fp_mant[0] */
927e76048aSMarcel Moolenaar #define	FP_2		(1 << (FP_LG + 1))	/* 2.0 in fp_mant[0] */
937e76048aSMarcel Moolenaar 
947e76048aSMarcel Moolenaar /*
957e76048aSMarcel Moolenaar  * Number classes.  Since zero, Inf, and NaN cannot be represented using
967e76048aSMarcel Moolenaar  * the above layout, we distinguish these from other numbers via a class.
977e76048aSMarcel Moolenaar  * In addition, to make computation easier and to follow Appendix N of
987e76048aSMarcel Moolenaar  * the SPARC Version 8 standard, we give each kind of NaN a separate class.
997e76048aSMarcel Moolenaar  */
1007e76048aSMarcel Moolenaar #define	FPC_SNAN	-2		/* signalling NaN (sign irrelevant) */
1017e76048aSMarcel Moolenaar #define	FPC_QNAN	-1		/* quiet NaN (sign irrelevant) */
1027e76048aSMarcel Moolenaar #define	FPC_ZERO	0		/* zero (sign matters) */
1037e76048aSMarcel Moolenaar #define	FPC_NUM		1		/* number (sign matters) */
1047e76048aSMarcel Moolenaar #define	FPC_INF		2		/* infinity (sign matters) */
1057e76048aSMarcel Moolenaar 
1067e76048aSMarcel Moolenaar #define	ISSNAN(fp)	((fp)->fp_class == FPC_SNAN)
1077e76048aSMarcel Moolenaar #define	ISQNAN(fp)	((fp)->fp_class == FPC_QNAN)
1087e76048aSMarcel Moolenaar #define	ISNAN(fp)	((fp)->fp_class < 0)
1097e76048aSMarcel Moolenaar #define	ISZERO(fp)	((fp)->fp_class == 0)
1107e76048aSMarcel Moolenaar #define	ISINF(fp)	((fp)->fp_class == FPC_INF)
1117e76048aSMarcel Moolenaar 
1127e76048aSMarcel Moolenaar /*
1137e76048aSMarcel Moolenaar  * ORDER(x,y) `sorts' a pair of `fpn *'s so that the right operand (y) points
1147e76048aSMarcel Moolenaar  * to the `more significant' operand for our purposes.  Appendix N says that
1157e76048aSMarcel Moolenaar  * the result of a computation involving two numbers are:
1167e76048aSMarcel Moolenaar  *
1177e76048aSMarcel Moolenaar  *	If both are SNaN: operand 2, converted to Quiet
1187e76048aSMarcel Moolenaar  *	If only one is SNaN: the SNaN operand, converted to Quiet
1197e76048aSMarcel Moolenaar  *	If both are QNaN: operand 2
1207e76048aSMarcel Moolenaar  *	If only one is QNaN: the QNaN operand
1217e76048aSMarcel Moolenaar  *
1227e76048aSMarcel Moolenaar  * In addition, in operations with an Inf operand, the result is usually
1237e76048aSMarcel Moolenaar  * Inf.  The class numbers are carefully arranged so that if
1247e76048aSMarcel Moolenaar  *	(unsigned)class(op1) > (unsigned)class(op2)
1257e76048aSMarcel Moolenaar  * then op1 is the one we want; otherwise op2 is the one we want.
1267e76048aSMarcel Moolenaar  */
1277e76048aSMarcel Moolenaar #define	ORDER(x, y) { \
1287e76048aSMarcel Moolenaar 	if ((u_int)(x)->fp_class > (u_int)(y)->fp_class) \
1297e76048aSMarcel Moolenaar 		SWAP(x, y); \
1307e76048aSMarcel Moolenaar }
1317e76048aSMarcel Moolenaar #define	SWAP(x, y) { \
1327e76048aSMarcel Moolenaar 	struct fpn *swap; \
1337e76048aSMarcel Moolenaar 	swap = (x), (x) = (y), (y) = swap; \
1347e76048aSMarcel Moolenaar }
1357e76048aSMarcel Moolenaar 
1367e76048aSMarcel Moolenaar /*
1377e76048aSMarcel Moolenaar  * Emulator state.
1387e76048aSMarcel Moolenaar  */
1397e76048aSMarcel Moolenaar struct fpemu {
14093312a91SJohn Baldwin 	struct	fpu *fe_fpstate;	/* registers, etc */
1417e76048aSMarcel Moolenaar 	int	fe_fpscr;		/* fpscr copy (modified during op) */
1427e76048aSMarcel Moolenaar 	int	fe_cx;			/* keep track of exceptions */
1437e76048aSMarcel Moolenaar 	struct	fpn fe_f1;		/* operand 1 */
1447e76048aSMarcel Moolenaar 	struct	fpn fe_f2;		/* operand 2, if required */
1457e76048aSMarcel Moolenaar 	struct	fpn fe_f3;		/* available storage for result */
1467e76048aSMarcel Moolenaar };
1477e76048aSMarcel Moolenaar 
1487e76048aSMarcel Moolenaar /*
1497e76048aSMarcel Moolenaar  * Arithmetic functions.
1507e76048aSMarcel Moolenaar  * Each of these may modify its inputs (f1,f2) and/or the temporary.
1517e76048aSMarcel Moolenaar  * Each returns a pointer to the result and/or sets exceptions.
1527e76048aSMarcel Moolenaar  */
1537e76048aSMarcel Moolenaar struct	fpn *fpu_add(struct fpemu *);
1547e76048aSMarcel Moolenaar #define	fpu_sub(fe) ((fe)->fe_f2.fp_sign ^= 1, fpu_add(fe))
1557e76048aSMarcel Moolenaar struct	fpn *fpu_mul(struct fpemu *);
1567e76048aSMarcel Moolenaar struct	fpn *fpu_div(struct fpemu *);
1577e76048aSMarcel Moolenaar struct	fpn *fpu_sqrt(struct fpemu *);
1587e76048aSMarcel Moolenaar 
1597e76048aSMarcel Moolenaar /*
1607e76048aSMarcel Moolenaar  * Other functions.
1617e76048aSMarcel Moolenaar  */
1627e76048aSMarcel Moolenaar 
1637e76048aSMarcel Moolenaar /* Perform a compare instruction (with or without unordered exception). */
1647e76048aSMarcel Moolenaar void	fpu_compare(struct fpemu *, int);
1657e76048aSMarcel Moolenaar 
1667e76048aSMarcel Moolenaar /* Build a new Quiet NaN (sign=0, frac=all 1's). */
1677e76048aSMarcel Moolenaar struct	fpn *fpu_newnan(struct fpemu *);
1687e76048aSMarcel Moolenaar 
169cebb2edbSMarcel Moolenaar void	fpu_norm(struct fpn *);
170cebb2edbSMarcel Moolenaar 
1717e76048aSMarcel Moolenaar /*
1727e76048aSMarcel Moolenaar  * Shift a number right some number of bits, taking care of round/sticky.
1737e76048aSMarcel Moolenaar  * Note that the result is probably not a well-formed number (it will lack
1747e76048aSMarcel Moolenaar  * the normal 1-bit mant[0]&FP_1).
1757e76048aSMarcel Moolenaar  */
1767e76048aSMarcel Moolenaar int	fpu_shr(struct fpn *, int);
1777e76048aSMarcel Moolenaar 
1787e76048aSMarcel Moolenaar void	fpu_explode(struct fpemu *, struct fpn *, int, int);
1797e76048aSMarcel Moolenaar void	fpu_implode(struct fpemu *, struct fpn *, int, u_int *);
1807e76048aSMarcel Moolenaar 
1817e76048aSMarcel Moolenaar #ifdef DEBUG
1827e76048aSMarcel Moolenaar #define	FPE_EX		0x1
1837e76048aSMarcel Moolenaar #define	FPE_INSN	0x2
1847e76048aSMarcel Moolenaar #define	FPE_OP		0x4
1857e76048aSMarcel Moolenaar #define	FPE_REG		0x8
1867e76048aSMarcel Moolenaar extern int fpe_debug;
1877e76048aSMarcel Moolenaar void	fpu_dumpfpn(struct fpn *);
1887e76048aSMarcel Moolenaar #define	DPRINTF(x, y)	if (fpe_debug & (x)) printf y
1897e76048aSMarcel Moolenaar #define DUMPFPN(x, f)	if (fpe_debug & (x)) fpu_dumpfpn((f))
1907e76048aSMarcel Moolenaar #else
1917e76048aSMarcel Moolenaar #define	DPRINTF(x, y)
1927e76048aSMarcel Moolenaar #define DUMPFPN(x, f)
1937e76048aSMarcel Moolenaar #endif
194