1176491Smarcel/* $NetBSD: fpu_arith.h,v 1.4 2005/12/24 20:07:28 perry Exp $ */ 2176491Smarcel/* $FreeBSD$ */ 3176491Smarcel 4176491Smarcel/* 5176491Smarcel * Copyright (c) 1992, 1993 6176491Smarcel * The Regents of the University of California. All rights reserved. 7176491Smarcel * 8176491Smarcel * This software was developed by the Computer Systems Engineering group 9176491Smarcel * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10176491Smarcel * contributed to Berkeley. 11176491Smarcel * 12176491Smarcel * All advertising materials mentioning features or use of this software 13176491Smarcel * must display the following acknowledgement: 14176491Smarcel * This product includes software developed by the University of 15176491Smarcel * California, Lawrence Berkeley Laboratory. 16176491Smarcel * 17176491Smarcel * Redistribution and use in source and binary forms, with or without 18176491Smarcel * modification, are permitted provided that the following conditions 19176491Smarcel * are met: 20176491Smarcel * 1. Redistributions of source code must retain the above copyright 21176491Smarcel * notice, this list of conditions and the following disclaimer. 22176491Smarcel * 2. Redistributions in binary form must reproduce the above copyright 23176491Smarcel * notice, this list of conditions and the following disclaimer in the 24176491Smarcel * documentation and/or other materials provided with the distribution. 25176491Smarcel * 3. Neither the name of the University nor the names of its contributors 26176491Smarcel * may be used to endorse or promote products derived from this software 27176491Smarcel * without specific prior written permission. 28176491Smarcel * 29176491Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30176491Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31176491Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32176491Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33176491Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34176491Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35176491Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36176491Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37176491Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38176491Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39176491Smarcel * SUCH DAMAGE. 40176491Smarcel * 41176491Smarcel * @(#)fpu_arith.h 8.1 (Berkeley) 6/11/93 42176491Smarcel */ 43176491Smarcel 44176491Smarcel/* 45176491Smarcel * Extended-precision arithmetic. 46176491Smarcel * 47176491Smarcel * We hold the notion of a `carry register', which may or may not be a 48176491Smarcel * machine carry bit or register. On the SPARC, it is just the machine's 49176491Smarcel * carry bit. 50176491Smarcel * 51176491Smarcel * In the worst case, you can compute the carry from x+y as 52176491Smarcel * (unsigned)(x + y) < (unsigned)x 53176491Smarcel * and from x+y+c as 54176491Smarcel * ((unsigned)(x + y + c) <= (unsigned)x && (y|c) != 0) 55176491Smarcel * for example. 56176491Smarcel */ 57176491Smarcel 58176491Smarcel 59176491Smarcel#ifndef FPE_USE_ASM 60176491Smarcel 61176491Smarcel/* set up for extended-precision arithemtic */ 62176491Smarcel#define FPU_DECL_CARRY quad_t fpu_carry, fpu_tmp; 63176491Smarcel 64176491Smarcel/* 65176491Smarcel * We have three kinds of add: 66176491Smarcel * add with carry: r = x + y + c 67176491Smarcel * add (ignoring current carry) and set carry: c'r = x + y + 0 68176491Smarcel * add with carry and set carry: c'r = x + y + c 69176491Smarcel * The macros use `C' for `use carry' and `S' for `set carry'. 70176491Smarcel * Note that the state of the carry is undefined after ADDC and SUBC, 71176491Smarcel * so if all you have for these is `add with carry and set carry', 72176491Smarcel * that is OK. 73176491Smarcel * 74176491Smarcel * The same goes for subtract, except that we compute x - y - c. 75176491Smarcel * 76176491Smarcel * Finally, we have a way to get the carry into a `regular' variable, 77176491Smarcel * or set it from a value. SET_CARRY turns 0 into no-carry, nonzero 78176491Smarcel * into carry; GET_CARRY sets its argument to 0 or 1. 79176491Smarcel */ 80176491Smarcel#define FPU_ADDC(r, x, y) \ 81176491Smarcel (r) = (x) + (y) + (!!fpu_carry) 82176491Smarcel#define FPU_ADDS(r, x, y) \ 83176491Smarcel { \ 84176491Smarcel fpu_tmp = (quad_t)(x) + (quad_t)(y); \ 85176491Smarcel (r) = (u_int)fpu_tmp; \ 86176491Smarcel fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ 87176491Smarcel } 88176491Smarcel#define FPU_ADDCS(r, x, y) \ 89176491Smarcel { \ 90176491Smarcel fpu_tmp = (quad_t)(x) + (quad_t)(y) + (!!fpu_carry); \ 91176491Smarcel (r) = (u_int)fpu_tmp; \ 92176491Smarcel fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ 93176491Smarcel } 94176491Smarcel#define FPU_SUBC(r, x, y) \ 95176491Smarcel (r) = (x) - (y) - (!!fpu_carry) 96176491Smarcel#define FPU_SUBS(r, x, y) \ 97176491Smarcel { \ 98176491Smarcel fpu_tmp = (quad_t)(x) - (quad_t)(y); \ 99176491Smarcel (r) = (u_int)fpu_tmp; \ 100176491Smarcel fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ 101176491Smarcel } 102176491Smarcel#define FPU_SUBCS(r, x, y) \ 103176491Smarcel { \ 104176491Smarcel fpu_tmp = (quad_t)(x) - (quad_t)(y) - (!!fpu_carry); \ 105176491Smarcel (r) = (u_int)fpu_tmp; \ 106176491Smarcel fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ 107176491Smarcel } 108176491Smarcel 109176491Smarcel#define FPU_GET_CARRY(r) (r) = (!!fpu_carry) 110176491Smarcel#define FPU_SET_CARRY(v) fpu_carry = ((v) != 0) 111176491Smarcel 112176491Smarcel#else 113176491Smarcel/* set up for extended-precision arithemtic */ 114176491Smarcel#define FPU_DECL_CARRY 115176491Smarcel 116176491Smarcel/* 117176491Smarcel * We have three kinds of add: 118176491Smarcel * add with carry: r = x + y + c 119176491Smarcel * add (ignoring current carry) and set carry: c'r = x + y + 0 120176491Smarcel * add with carry and set carry: c'r = x + y + c 121176491Smarcel * The macros use `C' for `use carry' and `S' for `set carry'. 122176491Smarcel * Note that the state of the carry is undefined after ADDC and SUBC, 123176491Smarcel * so if all you have for these is `add with carry and set carry', 124176491Smarcel * that is OK. 125176491Smarcel * 126176491Smarcel * The same goes for subtract, except that we compute x - y - c. 127176491Smarcel * 128176491Smarcel * Finally, we have a way to get the carry into a `regular' variable, 129176491Smarcel * or set it from a value. SET_CARRY turns 0 into no-carry, nonzero 130176491Smarcel * into carry; GET_CARRY sets its argument to 0 or 1. 131176491Smarcel */ 132176491Smarcel#define FPU_ADDC(r, x, y) \ 133176491Smarcel __asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y)) 134176491Smarcel#define FPU_ADDS(r, x, y) \ 135176491Smarcel __asm volatile("addc %0,%1,%2" : "=r"(r) : "r"(x), "r"(y)) 136176491Smarcel#define FPU_ADDCS(r, x, y) \ 137176491Smarcel __asm volatile("adde %0,%1,%2" : "=r"(r) : "r"(x), "r"(y)) 138176491Smarcel#define FPU_SUBC(r, x, y) \ 139176491Smarcel __asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y)) 140176491Smarcel#define FPU_SUBS(r, x, y) \ 141176491Smarcel __asm volatile("subfc %0,%2,%1" : "=r"(r) : "r"(x), "r"(y)) 142176491Smarcel#define FPU_SUBCS(r, x, y) \ 143176491Smarcel __asm volatile("subfe %0,%2,%1" : "=r"(r) : "r"(x), "r"(y)) 144176491Smarcel 145176491Smarcel#define FPU_GET_CARRY(r) __asm volatile("li %0,0; addie %0,%0,0" : "=r"(r)) 146176491Smarcel/* This one needs to destroy a temp register. */ 147176491Smarcel#define FPU_SET_CARRY(v) do { int __tmp; \ 148176491Smarcel __asm volatile("addic %0,%0,-1" : "r"(__tmp) : "r"(v)); \ 149176491Smarcel } while (0) 150176491Smarcel 151176491Smarcel#define FPU_SHL1_BY_ADD /* shift left 1 faster by ADDC than (a<<1)|(b>>31) */ 152176491Smarcel#endif 153