xref: /freebsd/sys/powerpc/fpu/fpu_arith.h (revision 29363fb446372cb3f10bc98664e9767c53fbb457)
17e76048aSMarcel Moolenaar /*	$NetBSD: fpu_arith.h,v 1.4 2005/12/24 20:07:28 perry 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  * Extended-precision arithmetic.
457e76048aSMarcel Moolenaar  *
467e76048aSMarcel Moolenaar  * We hold the notion of a `carry register', which may or may not be a
477e76048aSMarcel Moolenaar  * machine carry bit or register.  On the SPARC, it is just the machine's
487e76048aSMarcel Moolenaar  * carry bit.
497e76048aSMarcel Moolenaar  *
507e76048aSMarcel Moolenaar  * In the worst case, you can compute the carry from x+y as
517e76048aSMarcel Moolenaar  *	(unsigned)(x + y) < (unsigned)x
527e76048aSMarcel Moolenaar  * and from x+y+c as
537e76048aSMarcel Moolenaar  *	((unsigned)(x + y + c) <= (unsigned)x && (y|c) != 0)
547e76048aSMarcel Moolenaar  * for example.
557e76048aSMarcel Moolenaar  */
567e76048aSMarcel Moolenaar 
577e76048aSMarcel Moolenaar #ifndef FPE_USE_ASM
587e76048aSMarcel Moolenaar 
597e76048aSMarcel Moolenaar /* set up for extended-precision arithemtic */
607e76048aSMarcel Moolenaar #define	FPU_DECL_CARRY quad_t fpu_carry, fpu_tmp;
617e76048aSMarcel Moolenaar 
627e76048aSMarcel Moolenaar /*
637e76048aSMarcel Moolenaar  * We have three kinds of add:
647e76048aSMarcel Moolenaar  *	add with carry:					  r = x + y + c
657e76048aSMarcel Moolenaar  *	add (ignoring current carry) and set carry:	c'r = x + y + 0
667e76048aSMarcel Moolenaar  *	add with carry and set carry:			c'r = x + y + c
677e76048aSMarcel Moolenaar  * The macros use `C' for `use carry' and `S' for `set carry'.
687e76048aSMarcel Moolenaar  * Note that the state of the carry is undefined after ADDC and SUBC,
697e76048aSMarcel Moolenaar  * so if all you have for these is `add with carry and set carry',
707e76048aSMarcel Moolenaar  * that is OK.
717e76048aSMarcel Moolenaar  *
727e76048aSMarcel Moolenaar  * The same goes for subtract, except that we compute x - y - c.
737e76048aSMarcel Moolenaar  *
747e76048aSMarcel Moolenaar  * Finally, we have a way to get the carry into a `regular' variable,
757e76048aSMarcel Moolenaar  * or set it from a value.  SET_CARRY turns 0 into no-carry, nonzero
767e76048aSMarcel Moolenaar  * into carry; GET_CARRY sets its argument to 0 or 1.
777e76048aSMarcel Moolenaar  */
787e76048aSMarcel Moolenaar #define	FPU_ADDC(r, x, y) \
797e76048aSMarcel Moolenaar 	(r) = (x) + (y) + (!!fpu_carry)
807e76048aSMarcel Moolenaar #define	FPU_ADDS(r, x, y) \
817e76048aSMarcel Moolenaar 	{ \
827e76048aSMarcel Moolenaar 		fpu_tmp = (quad_t)(x) + (quad_t)(y); \
837e76048aSMarcel Moolenaar 		(r) = (u_int)fpu_tmp; \
847e76048aSMarcel Moolenaar 		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
857e76048aSMarcel Moolenaar 	}
867e76048aSMarcel Moolenaar #define	FPU_ADDCS(r, x, y) \
877e76048aSMarcel Moolenaar 	{ \
887e76048aSMarcel Moolenaar 		fpu_tmp = (quad_t)(x) + (quad_t)(y) + (!!fpu_carry); \
897e76048aSMarcel Moolenaar 		(r) = (u_int)fpu_tmp; \
907e76048aSMarcel Moolenaar 		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
917e76048aSMarcel Moolenaar 	}
927e76048aSMarcel Moolenaar #define	FPU_SUBC(r, x, y) \
937e76048aSMarcel Moolenaar 	(r) = (x) - (y) - (!!fpu_carry)
947e76048aSMarcel Moolenaar #define	FPU_SUBS(r, x, y) \
957e76048aSMarcel Moolenaar 	{ \
967e76048aSMarcel Moolenaar 		fpu_tmp = (quad_t)(x) - (quad_t)(y); \
977e76048aSMarcel Moolenaar 		(r) = (u_int)fpu_tmp; \
987e76048aSMarcel Moolenaar 		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
997e76048aSMarcel Moolenaar 	}
1007e76048aSMarcel Moolenaar #define	FPU_SUBCS(r, x, y) \
1017e76048aSMarcel Moolenaar 	{ \
1027e76048aSMarcel Moolenaar 		fpu_tmp = (quad_t)(x) - (quad_t)(y) - (!!fpu_carry); \
1037e76048aSMarcel Moolenaar 		(r) = (u_int)fpu_tmp; \
1047e76048aSMarcel Moolenaar 		fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \
1057e76048aSMarcel Moolenaar 	}
1067e76048aSMarcel Moolenaar 
1077e76048aSMarcel Moolenaar #define	FPU_GET_CARRY(r) (r) = (!!fpu_carry)
1087e76048aSMarcel Moolenaar #define	FPU_SET_CARRY(v) fpu_carry = ((v) != 0)
1097e76048aSMarcel Moolenaar 
1107e76048aSMarcel Moolenaar #else
1117e76048aSMarcel Moolenaar /* set up for extended-precision arithemtic */
1127e76048aSMarcel Moolenaar #define	FPU_DECL_CARRY
1137e76048aSMarcel Moolenaar 
1147e76048aSMarcel Moolenaar /*
1157e76048aSMarcel Moolenaar  * We have three kinds of add:
1167e76048aSMarcel Moolenaar  *	add with carry:					  r = x + y + c
1177e76048aSMarcel Moolenaar  *	add (ignoring current carry) and set carry:	c'r = x + y + 0
1187e76048aSMarcel Moolenaar  *	add with carry and set carry:			c'r = x + y + c
1197e76048aSMarcel Moolenaar  * The macros use `C' for `use carry' and `S' for `set carry'.
1207e76048aSMarcel Moolenaar  * Note that the state of the carry is undefined after ADDC and SUBC,
1217e76048aSMarcel Moolenaar  * so if all you have for these is `add with carry and set carry',
1227e76048aSMarcel Moolenaar  * that is OK.
1237e76048aSMarcel Moolenaar  *
1247e76048aSMarcel Moolenaar  * The same goes for subtract, except that we compute x - y - c.
1257e76048aSMarcel Moolenaar  *
1267e76048aSMarcel Moolenaar  * Finally, we have a way to get the carry into a `regular' variable,
1277e76048aSMarcel Moolenaar  * or set it from a value.  SET_CARRY turns 0 into no-carry, nonzero
1287e76048aSMarcel Moolenaar  * into carry; GET_CARRY sets its argument to 0 or 1.
1297e76048aSMarcel Moolenaar  */
1307e76048aSMarcel Moolenaar #define	FPU_ADDC(r, x, y) \
1317e76048aSMarcel Moolenaar 	__asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))
1327e76048aSMarcel Moolenaar #define	FPU_ADDS(r, x, y) \
1337e76048aSMarcel Moolenaar 	__asm volatile("addc %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))
1347e76048aSMarcel Moolenaar #define	FPU_ADDCS(r, x, y) \
1357e76048aSMarcel Moolenaar 	__asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))
1367e76048aSMarcel Moolenaar #define	FPU_SUBC(r, x, y) \
1377e76048aSMarcel Moolenaar 	__asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))
1387e76048aSMarcel Moolenaar #define	FPU_SUBS(r, x, y) \
1397e76048aSMarcel Moolenaar 	__asm volatile("subfc %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))
1407e76048aSMarcel Moolenaar #define	FPU_SUBCS(r, x, y) \
1417e76048aSMarcel Moolenaar 	__asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))
1427e76048aSMarcel Moolenaar 
1437e76048aSMarcel Moolenaar #define	FPU_GET_CARRY(r) __asm volatile("li %0,0; addie %0,%0,0" : "=r"(r))
1447e76048aSMarcel Moolenaar /* This one needs to destroy a temp register. */
1457e76048aSMarcel Moolenaar #define	FPU_SET_CARRY(v) do { int __tmp;				\
1467e76048aSMarcel Moolenaar 		__asm volatile("addic %0,%0,-1" : "r"(__tmp) : "r"(v)); \
1477e76048aSMarcel Moolenaar 	} while (0)
1487e76048aSMarcel Moolenaar 
1497e76048aSMarcel Moolenaar #define	FPU_SHL1_BY_ADD	/* shift left 1 faster by ADDC than (a<<1)|(b>>31) */
1507e76048aSMarcel Moolenaar #endif
151