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