/* $NetBSD: fpu_arith.h,v 1.4 2005/12/24 20:07:28 perry Exp $ */12/*-3* SPDX-License-Identifier: BSD-3-Clause4*5* Copyright (c) 1992, 19936* The Regents of the University of California. All rights reserved.7*8* This software was developed by the Computer Systems Engineering group9* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and10* contributed to Berkeley.11*12* All advertising materials mentioning features or use of this software13* must display the following acknowledgement:14* This product includes software developed by the University of15* California, Lawrence Berkeley Laboratory.16*17* Redistribution and use in source and binary forms, with or without18* modification, are permitted provided that the following conditions19* are met:20* 1. Redistributions of source code must retain the above copyright21* notice, this list of conditions and the following disclaimer.22* 2. Redistributions in binary form must reproduce the above copyright23* notice, this list of conditions and the following disclaimer in the24* documentation and/or other materials provided with the distribution.25* 3. Neither the name of the University nor the names of its contributors26* may be used to endorse or promote products derived from this software27* without specific prior written permission.28*29* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND30* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE31* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE32* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE33* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL34* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS35* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)36* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT37* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY38* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF39* SUCH DAMAGE.40*/4142/*43* Extended-precision arithmetic.44*45* We hold the notion of a `carry register', which may or may not be a46* machine carry bit or register. On the SPARC, it is just the machine's47* carry bit.48*49* In the worst case, you can compute the carry from x+y as50* (unsigned)(x + y) < (unsigned)x51* and from x+y+c as52* ((unsigned)(x + y + c) <= (unsigned)x && (y|c) != 0)53* for example.54*/5556#ifndef FPE_USE_ASM5758/* set up for extended-precision arithemtic */59#define FPU_DECL_CARRY quad_t fpu_carry, fpu_tmp;6061/*62* We have three kinds of add:63* add with carry: r = x + y + c64* add (ignoring current carry) and set carry: c'r = x + y + 065* add with carry and set carry: c'r = x + y + c66* The macros use `C' for `use carry' and `S' for `set carry'.67* Note that the state of the carry is undefined after ADDC and SUBC,68* so if all you have for these is `add with carry and set carry',69* that is OK.70*71* The same goes for subtract, except that we compute x - y - c.72*73* Finally, we have a way to get the carry into a `regular' variable,74* or set it from a value. SET_CARRY turns 0 into no-carry, nonzero75* into carry; GET_CARRY sets its argument to 0 or 1.76*/77#define FPU_ADDC(r, x, y) \78(r) = (x) + (y) + (!!fpu_carry)79#define FPU_ADDS(r, x, y) \80{ \81fpu_tmp = (quad_t)(x) + (quad_t)(y); \82(r) = (u_int)fpu_tmp; \83fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \84}85#define FPU_ADDCS(r, x, y) \86{ \87fpu_tmp = (quad_t)(x) + (quad_t)(y) + (!!fpu_carry); \88(r) = (u_int)fpu_tmp; \89fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \90}91#define FPU_SUBC(r, x, y) \92(r) = (x) - (y) - (!!fpu_carry)93#define FPU_SUBS(r, x, y) \94{ \95fpu_tmp = (quad_t)(x) - (quad_t)(y); \96(r) = (u_int)fpu_tmp; \97fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \98}99#define FPU_SUBCS(r, x, y) \100{ \101fpu_tmp = (quad_t)(x) - (quad_t)(y) - (!!fpu_carry); \102(r) = (u_int)fpu_tmp; \103fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \104}105106#define FPU_GET_CARRY(r) (r) = (!!fpu_carry)107#define FPU_SET_CARRY(v) fpu_carry = ((v) != 0)108109#else110/* set up for extended-precision arithemtic */111#define FPU_DECL_CARRY112113/*114* We have three kinds of add:115* add with carry: r = x + y + c116* add (ignoring current carry) and set carry: c'r = x + y + 0117* add with carry and set carry: c'r = x + y + c118* The macros use `C' for `use carry' and `S' for `set carry'.119* Note that the state of the carry is undefined after ADDC and SUBC,120* so if all you have for these is `add with carry and set carry',121* that is OK.122*123* The same goes for subtract, except that we compute x - y - c.124*125* Finally, we have a way to get the carry into a `regular' variable,126* or set it from a value. SET_CARRY turns 0 into no-carry, nonzero127* into carry; GET_CARRY sets its argument to 0 or 1.128*/129#define FPU_ADDC(r, x, y) \130__asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))131#define FPU_ADDS(r, x, y) \132__asm volatile("addc %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))133#define FPU_ADDCS(r, x, y) \134__asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y))135#define FPU_SUBC(r, x, y) \136__asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))137#define FPU_SUBS(r, x, y) \138__asm volatile("subfc %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))139#define FPU_SUBCS(r, x, y) \140__asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y))141142#define FPU_GET_CARRY(r) __asm volatile("li %0,0; addie %0,%0,0" : "=r"(r))143/* This one needs to destroy a temp register. */144#define FPU_SET_CARRY(v) do { int __tmp; \145__asm volatile("addic %0,%0,-1" : "r"(__tmp) : "r"(v)); \146} while (0)147148#define FPU_SHL1_BY_ADD /* shift left 1 faster by ADDC than (a<<1)|(b>>31) */149#endif150151152