sparc: soft-float support library
No sparc implementation actually has "long double" implemented in hardware. The instructions are defined in the spec, but they are caught and emulated by traps. gcc even bypasses the traps and calls the support functions directly. Import the required functions from FreeBSD (they implement the operations as specified in the sparc ABI) and link them into the kernel, for now (they will also need to be in libroot). Change-Id: Ifc21faa29fffa4bf5d3941468b62d81229a44971 Reviewed-on: https://review.haiku-os.org/c/1137 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
@@ -21,6 +21,17 @@ KernelMergeObject kernel_lib_posix_arch_$(TARGET_ARCH).o :
|
||||
siglongjmp.S
|
||||
sigsetjmp.S
|
||||
|
||||
fpu_add.c
|
||||
fpu_compare.c
|
||||
fpu_div.c
|
||||
fpu_explode.c
|
||||
fpu_implode.c
|
||||
fpu_mul.c
|
||||
fpu_reg.S
|
||||
fpu_sqrt.c
|
||||
fpu_subr.c
|
||||
softfloat.c
|
||||
|
||||
memcpy.c
|
||||
memset.c
|
||||
: $(TARGET_KERNEL_PIC_CCFLAGS)
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_add.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_add.c,v 1.3 1996/03/14 19:41:52 christos Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* Perform an FPU add (return x + y).
|
||||
*
|
||||
* To subtract, negate y and call add.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fsr.h"
|
||||
#include "instr.h"
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
struct fpn *
|
||||
__fpu_add(fe)
|
||||
struct fpemu *fe;
|
||||
{
|
||||
struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2, *r;
|
||||
uint32_t r0, r1, r2, r3;
|
||||
int rd;
|
||||
|
||||
/*
|
||||
* Put the `heavier' operand on the right (see fpu_emu.h).
|
||||
* Then we will have one of the following cases, taken in the
|
||||
* following order:
|
||||
*
|
||||
* - y = NaN. Implied: if only one is a signalling NaN, y is.
|
||||
* The result is y.
|
||||
* - y = Inf. Implied: x != NaN (is 0, number, or Inf: the NaN
|
||||
* case was taken care of earlier).
|
||||
* If x = -y, the result is NaN. Otherwise the result
|
||||
* is y (an Inf of whichever sign).
|
||||
* - y is 0. Implied: x = 0.
|
||||
* If x and y differ in sign (one positive, one negative),
|
||||
* the result is +0 except when rounding to -Inf. If same:
|
||||
* +0 + +0 = +0; -0 + -0 = -0.
|
||||
* - x is 0. Implied: y != 0.
|
||||
* Result is y.
|
||||
* - other. Implied: both x and y are numbers.
|
||||
* Do addition a la Hennessey & Patterson.
|
||||
*/
|
||||
ORDER(x, y);
|
||||
if (ISNAN(y))
|
||||
return (y);
|
||||
if (ISINF(y)) {
|
||||
if (ISINF(x) && x->fp_sign != y->fp_sign)
|
||||
return (__fpu_newnan(fe));
|
||||
return (y);
|
||||
}
|
||||
rd = FSR_GET_RD(fe->fe_fsr);
|
||||
if (ISZERO(y)) {
|
||||
if (rd != FSR_RD_NINF) /* only -0 + -0 gives -0 */
|
||||
y->fp_sign &= x->fp_sign;
|
||||
else /* any -0 operand gives -0 */
|
||||
y->fp_sign |= x->fp_sign;
|
||||
return (y);
|
||||
}
|
||||
if (ISZERO(x))
|
||||
return (y);
|
||||
/*
|
||||
* We really have two numbers to add, although their signs may
|
||||
* differ. Make the exponents match, by shifting the smaller
|
||||
* number right (e.g., 1.011 => 0.1011) and increasing its
|
||||
* exponent (2^3 => 2^4). Note that we do not alter the exponents
|
||||
* of x and y here.
|
||||
*/
|
||||
r = &fe->fe_f3;
|
||||
r->fp_class = FPC_NUM;
|
||||
if (x->fp_exp == y->fp_exp) {
|
||||
r->fp_exp = x->fp_exp;
|
||||
r->fp_sticky = 0;
|
||||
} else {
|
||||
if (x->fp_exp < y->fp_exp) {
|
||||
/*
|
||||
* Try to avoid subtract case iii (see below).
|
||||
* This also guarantees that x->fp_sticky = 0.
|
||||
*/
|
||||
SWAP(x, y);
|
||||
}
|
||||
/* now x->fp_exp > y->fp_exp */
|
||||
r->fp_exp = x->fp_exp;
|
||||
r->fp_sticky = __fpu_shr(y, x->fp_exp - y->fp_exp);
|
||||
}
|
||||
r->fp_sign = x->fp_sign;
|
||||
if (x->fp_sign == y->fp_sign) {
|
||||
FPU_DECL_CARRY
|
||||
|
||||
/*
|
||||
* The signs match, so we simply add the numbers. The result
|
||||
* may be `supernormal' (as big as 1.111...1 + 1.111...1, or
|
||||
* 11.111...0). If so, a single bit shift-right will fix it
|
||||
* (but remember to adjust the exponent).
|
||||
*/
|
||||
/* r->fp_mant = x->fp_mant + y->fp_mant */
|
||||
FPU_ADDS(r->fp_mant[3], x->fp_mant[3], y->fp_mant[3]);
|
||||
FPU_ADDCS(r->fp_mant[2], x->fp_mant[2], y->fp_mant[2]);
|
||||
FPU_ADDCS(r->fp_mant[1], x->fp_mant[1], y->fp_mant[1]);
|
||||
FPU_ADDC(r0, x->fp_mant[0], y->fp_mant[0]);
|
||||
if ((r->fp_mant[0] = r0) >= FP_2) {
|
||||
(void) __fpu_shr(r, 1);
|
||||
r->fp_exp++;
|
||||
}
|
||||
} else {
|
||||
FPU_DECL_CARRY
|
||||
|
||||
/*
|
||||
* The signs differ, so things are rather more difficult.
|
||||
* H&P would have us negate the negative operand and add;
|
||||
* this is the same as subtracting the negative operand.
|
||||
* This is quite a headache. Instead, we will subtract
|
||||
* y from x, regardless of whether y itself is the negative
|
||||
* operand. When this is done one of three conditions will
|
||||
* hold, depending on the magnitudes of x and y:
|
||||
* case i) |x| > |y|. The result is just x - y,
|
||||
* with x's sign, but it may need to be normalized.
|
||||
* case ii) |x| = |y|. The result is 0 (maybe -0)
|
||||
* so must be fixed up.
|
||||
* case iii) |x| < |y|. We goofed; the result should
|
||||
* be (y - x), with the same sign as y.
|
||||
* We could compare |x| and |y| here and avoid case iii,
|
||||
* but that would take just as much work as the subtract.
|
||||
* We can tell case iii has occurred by an overflow.
|
||||
*
|
||||
* N.B.: since x->fp_exp >= y->fp_exp, x->fp_sticky = 0.
|
||||
*/
|
||||
/* r->fp_mant = x->fp_mant - y->fp_mant */
|
||||
FPU_SET_CARRY(y->fp_sticky);
|
||||
FPU_SUBCS(r3, x->fp_mant[3], y->fp_mant[3]);
|
||||
FPU_SUBCS(r2, x->fp_mant[2], y->fp_mant[2]);
|
||||
FPU_SUBCS(r1, x->fp_mant[1], y->fp_mant[1]);
|
||||
FPU_SUBC(r0, x->fp_mant[0], y->fp_mant[0]);
|
||||
if (r0 < FP_2) {
|
||||
/* cases i and ii */
|
||||
if ((r0 | r1 | r2 | r3) == 0) {
|
||||
/* case ii */
|
||||
r->fp_class = FPC_ZERO;
|
||||
r->fp_sign = rd == FSR_RD_NINF;
|
||||
return (r);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Oops, case iii. This can only occur when the
|
||||
* exponents were equal, in which case neither
|
||||
* x nor y have sticky bits set. Flip the sign
|
||||
* (to y's sign) and negate the result to get y - x.
|
||||
*/
|
||||
#ifdef DIAGNOSTIC
|
||||
if (x->fp_exp != y->fp_exp || r->fp_sticky)
|
||||
__utrap_panic("fpu_add");
|
||||
#endif
|
||||
r->fp_sign = y->fp_sign;
|
||||
FPU_SUBS(r3, 0, r3);
|
||||
FPU_SUBCS(r2, 0, r2);
|
||||
FPU_SUBCS(r1, 0, r1);
|
||||
FPU_SUBC(r0, 0, r0);
|
||||
}
|
||||
r->fp_mant[3] = r3;
|
||||
r->fp_mant[2] = r2;
|
||||
r->fp_mant[1] = r1;
|
||||
r->fp_mant[0] = r0;
|
||||
if (r0 < FP_1)
|
||||
__fpu_norm(r);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_arith.h 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_arith.h,v 1.3 2000/07/24 04:11:03 mycroft Exp $
|
||||
* $FreeBSD: head/lib/libc/sparc64/fpu/fpu_arith.h 165903 2007-01-09 00:28:16Z imp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extended-precision arithmetic.
|
||||
*
|
||||
* We hold the notion of a `carry register', which may or may not be a
|
||||
* machine carry bit or register. On the SPARC, it is just the machine's
|
||||
* carry bit.
|
||||
*
|
||||
* In the worst case, you can compute the carry from x+y as
|
||||
* (unsigned)(x + y) < (unsigned)x
|
||||
* and from x+y+c as
|
||||
* ((unsigned)(x + y + c) <= (unsigned)x && (y|c) != 0)
|
||||
* for example.
|
||||
*/
|
||||
|
||||
/* set up for extended-precision arithemtic */
|
||||
#define FPU_DECL_CARRY
|
||||
|
||||
/*
|
||||
* We have three kinds of add:
|
||||
* add with carry: r = x + y + c
|
||||
* add (ignoring current carry) and set carry: c'r = x + y + 0
|
||||
* add with carry and set carry: c'r = x + y + c
|
||||
* The macros use `C' for `use carry' and `S' for `set carry'.
|
||||
* Note that the state of the carry is undefined after ADDC and SUBC,
|
||||
* so if all you have for these is `add with carry and set carry',
|
||||
* that is OK.
|
||||
*
|
||||
* The same goes for subtract, except that we compute x - y - c.
|
||||
*
|
||||
* Finally, we have a way to get the carry into a `regular' variable,
|
||||
* or set it from a value. SET_CARRY turns 0 into no-carry, nonzero
|
||||
* into carry; GET_CARRY sets its argument to 0 or 1.
|
||||
*/
|
||||
#define FPU_ADDC(r, x, y) \
|
||||
__asm __volatile("addx %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
|
||||
#define FPU_ADDS(r, x, y) \
|
||||
__asm __volatile("addcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
|
||||
#define FPU_ADDCS(r, x, y) \
|
||||
__asm __volatile("addxcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
|
||||
#define FPU_SUBC(r, x, y) \
|
||||
__asm __volatile("subx %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
|
||||
#define FPU_SUBS(r, x, y) \
|
||||
__asm __volatile("subcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
|
||||
#define FPU_SUBCS(r, x, y) \
|
||||
__asm __volatile("subxcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
|
||||
|
||||
#define FPU_GET_CARRY(r) __asm __volatile("addx %%g0,%%g0,%0" : "=r"(r))
|
||||
#define FPU_SET_CARRY(v) __asm __volatile("addcc %0,-1,%%g0" : : "r"(v))
|
||||
|
||||
#define FPU_SHL1_BY_ADD /* shift left 1 faster by ADDC than (a<<1)|(b>>31) */
|
||||
@@ -0,0 +1,176 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_compare.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_compare.c,v 1.3 2001/08/26 05:46:31 eeh Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* CMP and CMPE instructions.
|
||||
*
|
||||
* These rely on the fact that our internal wide format is achieved by
|
||||
* adding zero bits to the end of narrower mantissas.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "fsr.h"
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
static u_long fcc_nmask[] = {
|
||||
~FSR_FCC0_MASK,
|
||||
~FSR_FCC1_MASK,
|
||||
~FSR_FCC2_MASK,
|
||||
~FSR_FCC3_MASK
|
||||
};
|
||||
|
||||
/* XXX: we don't use the FSR_FCCx macros here; it's much easier this way. */
|
||||
static int fcc_shift[] = {
|
||||
FSR_FCC0_SHIFT,
|
||||
FSR_FCC1_SHIFT,
|
||||
FSR_FCC2_SHIFT,
|
||||
FSR_FCC3_SHIFT
|
||||
};
|
||||
|
||||
/*
|
||||
* Perform a compare instruction (with or without unordered exception).
|
||||
* This updates the fcc field in the fsr.
|
||||
*
|
||||
* If either operand is NaN, the result is unordered. For cmpe, this
|
||||
* causes an NV exception. Everything else is ordered:
|
||||
* |Inf| > |numbers| > |0|.
|
||||
* We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0),
|
||||
* so we get this directly. Note, however, that two zeros compare equal
|
||||
* regardless of sign, while everything else depends on sign.
|
||||
*
|
||||
* Incidentally, two Infs of the same sign compare equal (per the 80387
|
||||
* manual---it would be nice if the SPARC documentation were more
|
||||
* complete).
|
||||
*/
|
||||
void
|
||||
__fpu_compare(struct fpemu *fe, int cmpe, int fcc)
|
||||
{
|
||||
struct fpn *a, *b;
|
||||
int cc;
|
||||
FPU_DECL_CARRY
|
||||
|
||||
a = &fe->fe_f1;
|
||||
b = &fe->fe_f2;
|
||||
|
||||
if (ISNAN(a) || ISNAN(b)) {
|
||||
/*
|
||||
* In any case, we already got an exception for signalling
|
||||
* NaNs; here we may replace that one with an identical
|
||||
* exception, but so what?.
|
||||
*/
|
||||
if (cmpe)
|
||||
fe->fe_cx = FSR_NV;
|
||||
cc = FSR_CC_UO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must handle both-zero early to avoid sign goofs. Otherwise,
|
||||
* at most one is 0, and if the signs differ we are done.
|
||||
*/
|
||||
if (ISZERO(a) && ISZERO(b)) {
|
||||
cc = FSR_CC_EQ;
|
||||
goto done;
|
||||
}
|
||||
if (a->fp_sign) { /* a < 0 (or -0) */
|
||||
if (!b->fp_sign) { /* b >= 0 (or if a = -0, b > 0) */
|
||||
cc = FSR_CC_LT;
|
||||
goto done;
|
||||
}
|
||||
} else { /* a > 0 (or +0) */
|
||||
if (b->fp_sign) { /* b <= -0 (or if a = +0, b < 0) */
|
||||
cc = FSR_CC_GT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now the signs are the same (but may both be negative). All
|
||||
* we have left are these cases:
|
||||
*
|
||||
* |a| < |b| [classes or values differ]
|
||||
* |a| > |b| [classes or values differ]
|
||||
* |a| == |b| [classes and values identical]
|
||||
*
|
||||
* We define `diff' here to expand these as:
|
||||
*
|
||||
* |a| < |b|, a,b >= 0: a < b => FSR_CC_LT
|
||||
* |a| < |b|, a,b < 0: a > b => FSR_CC_GT
|
||||
* |a| > |b|, a,b >= 0: a > b => FSR_CC_GT
|
||||
* |a| > |b|, a,b < 0: a < b => FSR_CC_LT
|
||||
*/
|
||||
#define opposite_cc(cc) ((cc) == FSR_CC_LT ? FSR_CC_GT : FSR_CC_LT)
|
||||
#define diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) : (magnitude))
|
||||
if (a->fp_class < b->fp_class) { /* |a| < |b| */
|
||||
cc = diff(FSR_CC_LT);
|
||||
goto done;
|
||||
}
|
||||
if (a->fp_class > b->fp_class) { /* |a| > |b| */
|
||||
cc = diff(FSR_CC_GT);
|
||||
goto done;
|
||||
}
|
||||
/* now none can be 0: only Inf and numbers remain */
|
||||
if (ISINF(a)) { /* |Inf| = |Inf| */
|
||||
cc = FSR_CC_EQ;
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* Only numbers remain. To compare two numbers in magnitude, we
|
||||
* simply subtract them.
|
||||
*/
|
||||
a = __fpu_sub(fe);
|
||||
if (a->fp_class == FPC_ZERO)
|
||||
cc = FSR_CC_EQ;
|
||||
else
|
||||
cc = diff(FSR_CC_GT);
|
||||
|
||||
done:
|
||||
fe->fe_fsr = (fe->fe_fsr & fcc_nmask[fcc]) |
|
||||
((u_long)cc << fcc_shift[fcc]);
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_div.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_div.c,v 1.2 1994/11/20 20:52:38 deraadt Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* Perform an FPU divide (return x / y).
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "fsr.h"
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
/*
|
||||
* Division of normal numbers is done as follows:
|
||||
*
|
||||
* x and y are floating point numbers, i.e., in the form 1.bbbb * 2^e.
|
||||
* If X and Y are the mantissas (1.bbbb's), the quotient is then:
|
||||
*
|
||||
* q = (X / Y) * 2^((x exponent) - (y exponent))
|
||||
*
|
||||
* Since X and Y are both in [1.0,2.0), the quotient's mantissa (X / Y)
|
||||
* will be in [0.5,2.0). Moreover, it will be less than 1.0 if and only
|
||||
* if X < Y. In that case, it will have to be shifted left one bit to
|
||||
* become a normal number, and the exponent decremented. Thus, the
|
||||
* desired exponent is:
|
||||
*
|
||||
* left_shift = x->fp_mant < y->fp_mant;
|
||||
* result_exp = x->fp_exp - y->fp_exp - left_shift;
|
||||
*
|
||||
* The quotient mantissa X/Y can then be computed one bit at a time
|
||||
* using the following algorithm:
|
||||
*
|
||||
* Q = 0; -- Initial quotient.
|
||||
* R = X; -- Initial remainder,
|
||||
* if (left_shift) -- but fixed up in advance.
|
||||
* R *= 2;
|
||||
* for (bit = FP_NMANT; --bit >= 0; R *= 2) {
|
||||
* if (R >= Y) {
|
||||
* Q |= 1 << bit;
|
||||
* R -= Y;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The subtraction R -= Y always removes the uppermost bit from R (and
|
||||
* can sometimes remove additional lower-order 1 bits); this proof is
|
||||
* left to the reader.
|
||||
*
|
||||
* This loop correctly calculates the guard and round bits since they are
|
||||
* included in the expanded internal representation. The sticky bit
|
||||
* is to be set if and only if any other bits beyond guard and round
|
||||
* would be set. From the above it is obvious that this is true if and
|
||||
* only if the remainder R is nonzero when the loop terminates.
|
||||
*
|
||||
* Examining the loop above, we can see that the quotient Q is built
|
||||
* one bit at a time ``from the top down''. This means that we can
|
||||
* dispense with the multi-word arithmetic and just build it one word
|
||||
* at a time, writing each result word when it is done.
|
||||
*
|
||||
* Furthermore, since X and Y are both in [1.0,2.0), we know that,
|
||||
* initially, R >= Y. (Recall that, if X < Y, R is set to X * 2 and
|
||||
* is therefore at in [2.0,4.0).) Thus Q is sure to have bit FP_NMANT-1
|
||||
* set, and R can be set initially to either X - Y (when X >= Y) or
|
||||
* 2X - Y (when X < Y). In addition, comparing R and Y is difficult,
|
||||
* so we will simply calculate R - Y and see if that underflows.
|
||||
* This leads to the following revised version of the algorithm:
|
||||
*
|
||||
* R = X;
|
||||
* bit = FP_1;
|
||||
* D = R - Y;
|
||||
* if (D >= 0) {
|
||||
* result_exp = x->fp_exp - y->fp_exp;
|
||||
* R = D;
|
||||
* q = bit;
|
||||
* bit >>= 1;
|
||||
* } else {
|
||||
* result_exp = x->fp_exp - y->fp_exp - 1;
|
||||
* q = 0;
|
||||
* }
|
||||
* R <<= 1;
|
||||
* do {
|
||||
* D = R - Y;
|
||||
* if (D >= 0) {
|
||||
* q |= bit;
|
||||
* R = D;
|
||||
* }
|
||||
* R <<= 1;
|
||||
* } while ((bit >>= 1) != 0);
|
||||
* Q[0] = q;
|
||||
* for (i = 1; i < 4; i++) {
|
||||
* q = 0, bit = 1 << 31;
|
||||
* do {
|
||||
* D = R - Y;
|
||||
* if (D >= 0) {
|
||||
* q |= bit;
|
||||
* R = D;
|
||||
* }
|
||||
* R <<= 1;
|
||||
* } while ((bit >>= 1) != 0);
|
||||
* Q[i] = q;
|
||||
* }
|
||||
*
|
||||
* This can be refined just a bit further by moving the `R <<= 1'
|
||||
* calculations to the front of the do-loops and eliding the first one.
|
||||
* The process can be terminated immediately whenever R becomes 0, but
|
||||
* this is relatively rare, and we do not bother.
|
||||
*/
|
||||
|
||||
struct fpn *
|
||||
__fpu_div(fe)
|
||||
struct fpemu *fe;
|
||||
{
|
||||
struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
|
||||
u_int q, bit;
|
||||
u_int r0, r1, r2, r3, d0, d1, d2, d3, y0, y1, y2, y3;
|
||||
FPU_DECL_CARRY
|
||||
|
||||
/*
|
||||
* Since divide is not commutative, we cannot just use ORDER.
|
||||
* Check either operand for NaN first; if there is at least one,
|
||||
* order the signalling one (if only one) onto the right, then
|
||||
* return it. Otherwise we have the following cases:
|
||||
*
|
||||
* Inf / Inf = NaN, plus NV exception
|
||||
* Inf / num = Inf [i.e., return x #]
|
||||
* Inf / 0 = Inf [i.e., return x #]
|
||||
* 0 / Inf = 0 [i.e., return x #]
|
||||
* 0 / num = 0 [i.e., return x #]
|
||||
* 0 / 0 = NaN, plus NV exception
|
||||
* num / Inf = 0 #
|
||||
* num / num = num (do the divide)
|
||||
* num / 0 = Inf #, plus DZ exception
|
||||
*
|
||||
* # Sign of result is XOR of operand signs.
|
||||
*/
|
||||
if (ISNAN(x) || ISNAN(y)) {
|
||||
ORDER(x, y);
|
||||
return (y);
|
||||
}
|
||||
if (ISINF(x) || ISZERO(x)) {
|
||||
if (x->fp_class == y->fp_class)
|
||||
return (__fpu_newnan(fe));
|
||||
x->fp_sign ^= y->fp_sign;
|
||||
return (x);
|
||||
}
|
||||
|
||||
x->fp_sign ^= y->fp_sign;
|
||||
if (ISINF(y)) {
|
||||
x->fp_class = FPC_ZERO;
|
||||
return (x);
|
||||
}
|
||||
if (ISZERO(y)) {
|
||||
fe->fe_cx = FSR_DZ;
|
||||
x->fp_class = FPC_INF;
|
||||
return (x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Macros for the divide. See comments at top for algorithm.
|
||||
* Note that we expand R, D, and Y here.
|
||||
*/
|
||||
|
||||
#define SUBTRACT /* D = R - Y */ \
|
||||
FPU_SUBS(d3, r3, y3); FPU_SUBCS(d2, r2, y2); \
|
||||
FPU_SUBCS(d1, r1, y1); FPU_SUBC(d0, r0, y0)
|
||||
|
||||
#define NONNEGATIVE /* D >= 0 */ \
|
||||
((int)d0 >= 0)
|
||||
|
||||
#ifdef FPU_SHL1_BY_ADD
|
||||
#define SHL1 /* R <<= 1 */ \
|
||||
FPU_ADDS(r3, r3, r3); FPU_ADDCS(r2, r2, r2); \
|
||||
FPU_ADDCS(r1, r1, r1); FPU_ADDC(r0, r0, r0)
|
||||
#else
|
||||
#define SHL1 \
|
||||
r0 = (r0 << 1) | (r1 >> 31), r1 = (r1 << 1) | (r2 >> 31), \
|
||||
r2 = (r2 << 1) | (r3 >> 31), r3 <<= 1
|
||||
#endif
|
||||
|
||||
#define LOOP /* do ... while (bit >>= 1) */ \
|
||||
do { \
|
||||
SHL1; \
|
||||
SUBTRACT; \
|
||||
if (NONNEGATIVE) { \
|
||||
q |= bit; \
|
||||
r0 = d0, r1 = d1, r2 = d2, r3 = d3; \
|
||||
} \
|
||||
} while ((bit >>= 1) != 0)
|
||||
|
||||
#define WORD(r, i) /* calculate r->fp_mant[i] */ \
|
||||
q = 0; \
|
||||
bit = 1 << 31; \
|
||||
LOOP; \
|
||||
(x)->fp_mant[i] = q
|
||||
|
||||
/* Setup. Note that we put our result in x. */
|
||||
r0 = x->fp_mant[0];
|
||||
r1 = x->fp_mant[1];
|
||||
r2 = x->fp_mant[2];
|
||||
r3 = x->fp_mant[3];
|
||||
y0 = y->fp_mant[0];
|
||||
y1 = y->fp_mant[1];
|
||||
y2 = y->fp_mant[2];
|
||||
y3 = y->fp_mant[3];
|
||||
|
||||
bit = FP_1;
|
||||
SUBTRACT;
|
||||
if (NONNEGATIVE) {
|
||||
x->fp_exp -= y->fp_exp;
|
||||
r0 = d0, r1 = d1, r2 = d2, r3 = d3;
|
||||
q = bit;
|
||||
bit >>= 1;
|
||||
} else {
|
||||
x->fp_exp -= y->fp_exp + 1;
|
||||
q = 0;
|
||||
}
|
||||
LOOP;
|
||||
x->fp_mant[0] = q;
|
||||
WORD(x, 1);
|
||||
WORD(x, 2);
|
||||
WORD(x, 3);
|
||||
x->fp_sticky = r0 | r1 | r2 | r3;
|
||||
|
||||
return (x);
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_emu.h 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_emu.h,v 1.4 2000/08/03 18:32:07 eeh Exp $
|
||||
* $FreeBSD: head/lib/libc/sparc64/fpu/fpu_emu.h 326025 2017-11-20 19:49:47Z pfg $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Floating point emulator (tailored for SPARC, but structurally
|
||||
* machine-independent).
|
||||
*
|
||||
* Floating point numbers are carried around internally in an `expanded'
|
||||
* or `unpacked' form consisting of:
|
||||
* - sign
|
||||
* - unbiased exponent
|
||||
* - mantissa (`1.' + 112-bit fraction + guard + round)
|
||||
* - sticky bit
|
||||
* Any implied `1' bit is inserted, giving a 113-bit mantissa that is
|
||||
* always nonzero. Additional low-order `guard' and `round' bits are
|
||||
* scrunched in, making the entire mantissa 115 bits long. This is divided
|
||||
* into four 32-bit words, with `spare' bits left over in the upper part
|
||||
* of the top word (the high bits of fp_mant[0]). An internal `exploded'
|
||||
* number is thus kept within the half-open interval [1.0,2.0) (but see
|
||||
* the `number classes' below). This holds even for denormalized numbers:
|
||||
* when we explode an external denorm, we normalize it, introducing low-order
|
||||
* zero bits, so that the rest of the code always sees normalized values.
|
||||
*
|
||||
* Note that a number of our algorithms use the `spare' bits at the top.
|
||||
* The most demanding algorithm---the one for sqrt---depends on two such
|
||||
* bits, so that it can represent values up to (but not including) 8.0,
|
||||
* and then it needs a carry on top of that, so that we need three `spares'.
|
||||
*
|
||||
* The sticky-word is 32 bits so that we can use `OR' operators to goosh
|
||||
* whole words from the mantissa into it.
|
||||
*
|
||||
* All operations are done in this internal extended precision. According
|
||||
* to Hennesey & Patterson, Appendix A, rounding can be repeated---that is,
|
||||
* it is OK to do a+b in extended precision and then round the result to
|
||||
* single precision---provided single, double, and extended precisions are
|
||||
* `far enough apart' (they always are), but we will try to avoid any such
|
||||
* extra work where possible.
|
||||
*/
|
||||
|
||||
#ifndef _SPARC64_FPU_FPU_EMU_H_
|
||||
#define _SPARC64_FPU_FPU_EMU_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fpu_reg.h"
|
||||
|
||||
struct fpn {
|
||||
int fp_class; /* see below */
|
||||
int fp_sign; /* 0 => positive, 1 => negative */
|
||||
int fp_exp; /* exponent (unbiased) */
|
||||
int fp_sticky; /* nonzero bits lost at right end */
|
||||
uint32_t fp_mant[4]; /* 115-bit mantissa */
|
||||
};
|
||||
|
||||
#define FP_NMANT 115 /* total bits in mantissa (incl g,r) */
|
||||
#define FP_NG 2 /* number of low-order guard bits */
|
||||
#define FP_LG ((FP_NMANT - 1) & 31) /* log2(1.0) for fp_mant[0] */
|
||||
#define FP_LG2 ((FP_NMANT - 1) & 63) /* log2(1.0) for fp_mant[0] and fp_mant[1] */
|
||||
#define FP_QUIETBIT (1 << (FP_LG - 1)) /* Quiet bit in NaNs (0.5) */
|
||||
#define FP_1 (1 << FP_LG) /* 1.0 in fp_mant[0] */
|
||||
#define FP_2 (1 << (FP_LG + 1)) /* 2.0 in fp_mant[0] */
|
||||
|
||||
/*
|
||||
* Number classes. Since zero, Inf, and NaN cannot be represented using
|
||||
* the above layout, we distinguish these from other numbers via a class.
|
||||
* In addition, to make computation easier and to follow Appendix N of
|
||||
* the SPARC Version 8 standard, we give each kind of NaN a separate class.
|
||||
*/
|
||||
#define FPC_SNAN -2 /* signalling NaN (sign irrelevant) */
|
||||
#define FPC_QNAN -1 /* quiet NaN (sign irrelevant) */
|
||||
#define FPC_ZERO 0 /* zero (sign matters) */
|
||||
#define FPC_NUM 1 /* number (sign matters) */
|
||||
#define FPC_INF 2 /* infinity (sign matters) */
|
||||
|
||||
#define ISNAN(fp) ((fp)->fp_class < 0)
|
||||
#define ISZERO(fp) ((fp)->fp_class == 0)
|
||||
#define ISINF(fp) ((fp)->fp_class == FPC_INF)
|
||||
|
||||
/*
|
||||
* ORDER(x,y) `sorts' a pair of `fpn *'s so that the right operand (y) points
|
||||
* to the `more significant' operand for our purposes. Appendix N says that
|
||||
* the result of a computation involving two numbers are:
|
||||
*
|
||||
* If both are SNaN: operand 2, converted to Quiet
|
||||
* If only one is SNaN: the SNaN operand, converted to Quiet
|
||||
* If both are QNaN: operand 2
|
||||
* If only one is QNaN: the QNaN operand
|
||||
*
|
||||
* In addition, in operations with an Inf operand, the result is usually
|
||||
* Inf. The class numbers are carefully arranged so that if
|
||||
* (unsigned)class(op1) > (unsigned)class(op2)
|
||||
* then op1 is the one we want; otherwise op2 is the one we want.
|
||||
*/
|
||||
#define ORDER(x, y) { \
|
||||
if ((uint32_t)(x)->fp_class > (uint32_t)(y)->fp_class) \
|
||||
SWAP(x, y); \
|
||||
}
|
||||
#define SWAP(x, y) { \
|
||||
register struct fpn *swap; \
|
||||
swap = (x), (x) = (y), (y) = swap; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Floating point operand types. FTYPE_LNG is syntethic (it does not occur in
|
||||
* instructions).
|
||||
*/
|
||||
#define FTYPE_INT INSFP_i
|
||||
#define FTYPE_SNG INSFP_s
|
||||
#define FTYPE_DBL INSFP_d
|
||||
#define FTYPE_EXT INSFP_q
|
||||
#define FTYPE_LNG 4
|
||||
|
||||
/*
|
||||
* Emulator state.
|
||||
*/
|
||||
struct fpemu {
|
||||
uint64_t fe_fsr; /* fsr copy (modified during op) */
|
||||
int fe_cx; /* exceptions */
|
||||
int pad; /* align access to following fields */
|
||||
struct fpn fe_f1; /* operand 1 */
|
||||
struct fpn fe_f2; /* operand 2, if required */
|
||||
struct fpn fe_f3; /* available storage for result */
|
||||
};
|
||||
|
||||
/*
|
||||
* Arithmetic functions.
|
||||
* Each of these may modify its inputs (f1,f2) and/or the temporary.
|
||||
* Each returns a pointer to the result and/or sets exceptions.
|
||||
*/
|
||||
#define __fpu_sub(fe) (ISNAN(&(fe)->fe_f2) ? 0 : ((fe)->fe_f2.fp_sign ^= 1), \
|
||||
__fpu_add(fe))
|
||||
|
||||
#ifdef FPU_DEBUG
|
||||
#define FPE_INSN 0x1
|
||||
#define FPE_REG 0x2
|
||||
extern int __fpe_debug;
|
||||
void __fpu_dumpfpn(struct fpn *);
|
||||
#define DPRINTF(x, y) if (__fpe_debug & (x)) printf y
|
||||
#define DUMPFPN(x, f) if (__fpe_debug & (x)) __fpu_dumpfpn((f))
|
||||
#else
|
||||
#define DPRINTF(x, y)
|
||||
#define DUMPFPN(x, f)
|
||||
#endif
|
||||
|
||||
#endif /* !_SPARC64_FPU_FPU_EXTERN_H_ */
|
||||
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_explode.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_explode.c,v 1.5 2000/08/03 18:32:08 eeh Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* FPU subroutines: `explode' the machine's `packed binary' format numbers
|
||||
* into our internal format.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifdef FPU_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "fsr.h"
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
#include "ieee.h"
|
||||
#include "instr.h"
|
||||
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
extern void panic(const char*, ...);
|
||||
#else
|
||||
#include <OS.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* N.B.: in all of the following, we assume the FP format is
|
||||
*
|
||||
* ---------------------------
|
||||
* | s | exponent | fraction |
|
||||
* ---------------------------
|
||||
*
|
||||
* (which represents -1**s * 1.fraction * 2**exponent), so that the
|
||||
* sign bit is way at the top (bit 31), the exponent is next, and
|
||||
* then the remaining bits mark the fraction. A zero exponent means
|
||||
* zero or denormalized (0.fraction rather than 1.fraction), and the
|
||||
* maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
|
||||
*
|
||||
* Since the sign bit is always the topmost bit---this holds even for
|
||||
* integers---we set that outside all the *tof functions. Each function
|
||||
* returns the class code for the new number (but note that we use
|
||||
* FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
|
||||
*/
|
||||
|
||||
/*
|
||||
* int -> fpn.
|
||||
*/
|
||||
int
|
||||
__fpu_itof(fp, i)
|
||||
struct fpn *fp;
|
||||
uint32_t i;
|
||||
{
|
||||
|
||||
if (i == 0)
|
||||
return (FPC_ZERO);
|
||||
/*
|
||||
* The value FP_1 represents 2^FP_LG, so set the exponent
|
||||
* there and let normalization fix it up. Convert negative
|
||||
* numbers to sign-and-magnitude. Note that this relies on
|
||||
* fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
|
||||
*/
|
||||
fp->fp_exp = FP_LG;
|
||||
/*
|
||||
* The sign bit decides whether i should be interpreted as
|
||||
* a signed or unsigned entity.
|
||||
*/
|
||||
if (fp->fp_sign && (int)i < 0)
|
||||
fp->fp_mant[0] = -i;
|
||||
else
|
||||
fp->fp_mant[0] = i;
|
||||
fp->fp_mant[1] = 0;
|
||||
fp->fp_mant[2] = 0;
|
||||
fp->fp_mant[3] = 0;
|
||||
__fpu_norm(fp);
|
||||
return (FPC_NUM);
|
||||
}
|
||||
|
||||
/*
|
||||
* 64-bit int -> fpn.
|
||||
*/
|
||||
int
|
||||
__fpu_xtof(fp, i)
|
||||
struct fpn *fp;
|
||||
uint64_t i;
|
||||
{
|
||||
|
||||
if (i == 0)
|
||||
return (FPC_ZERO);
|
||||
/*
|
||||
* The value FP_1 represents 2^FP_LG, so set the exponent
|
||||
* there and let normalization fix it up. Convert negative
|
||||
* numbers to sign-and-magnitude. Note that this relies on
|
||||
* fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
|
||||
*/
|
||||
fp->fp_exp = FP_LG2;
|
||||
/*
|
||||
* The sign bit decides whether i should be interpreted as
|
||||
* a signed or unsigned entity.
|
||||
*/
|
||||
if (fp->fp_sign && (int64_t)i < 0)
|
||||
*((int64_t *)fp->fp_mant) = -i;
|
||||
else
|
||||
*((int64_t *)fp->fp_mant) = i;
|
||||
fp->fp_mant[2] = 0;
|
||||
fp->fp_mant[3] = 0;
|
||||
__fpu_norm(fp);
|
||||
return (FPC_NUM);
|
||||
}
|
||||
|
||||
#define mask(nbits) ((1L << (nbits)) - 1)
|
||||
|
||||
/*
|
||||
* All external floating formats convert to internal in the same manner,
|
||||
* as defined here. Note that only normals get an implied 1.0 inserted.
|
||||
*/
|
||||
#define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
|
||||
if (exp == 0) { \
|
||||
if (allfrac == 0) \
|
||||
return (FPC_ZERO); \
|
||||
fp->fp_exp = 1 - expbias; \
|
||||
fp->fp_mant[0] = f0; \
|
||||
fp->fp_mant[1] = f1; \
|
||||
fp->fp_mant[2] = f2; \
|
||||
fp->fp_mant[3] = f3; \
|
||||
__fpu_norm(fp); \
|
||||
return (FPC_NUM); \
|
||||
} \
|
||||
if (exp == (2 * expbias + 1)) { \
|
||||
if (allfrac == 0) \
|
||||
return (FPC_INF); \
|
||||
fp->fp_mant[0] = f0; \
|
||||
fp->fp_mant[1] = f1; \
|
||||
fp->fp_mant[2] = f2; \
|
||||
fp->fp_mant[3] = f3; \
|
||||
return (FPC_QNAN); \
|
||||
} \
|
||||
fp->fp_exp = exp - expbias; \
|
||||
fp->fp_mant[0] = FP_1 | f0; \
|
||||
fp->fp_mant[1] = f1; \
|
||||
fp->fp_mant[2] = f2; \
|
||||
fp->fp_mant[3] = f3; \
|
||||
return (FPC_NUM)
|
||||
|
||||
/*
|
||||
* 32-bit single precision -> fpn.
|
||||
* We assume a single occupies at most (64-FP_LG) bits in the internal
|
||||
* format: i.e., needs at most fp_mant[0] and fp_mant[1].
|
||||
*/
|
||||
int
|
||||
__fpu_stof(fp, i)
|
||||
struct fpn *fp;
|
||||
uint32_t i;
|
||||
{
|
||||
int exp;
|
||||
uint32_t frac, f0, f1;
|
||||
#define SNG_SHIFT (SNG_FRACBITS - FP_LG)
|
||||
|
||||
exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
|
||||
frac = i & mask(SNG_FRACBITS);
|
||||
f0 = frac >> SNG_SHIFT;
|
||||
f1 = frac << (32 - SNG_SHIFT);
|
||||
FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 64-bit double -> fpn.
|
||||
* We assume this uses at most (96-FP_LG) bits.
|
||||
*/
|
||||
int
|
||||
__fpu_dtof(fp, i, j)
|
||||
struct fpn *fp;
|
||||
uint32_t i, j;
|
||||
{
|
||||
int exp;
|
||||
uint32_t frac, f0, f1, f2;
|
||||
#define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
|
||||
|
||||
exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
|
||||
frac = i & mask(DBL_FRACBITS - 32);
|
||||
f0 = frac >> DBL_SHIFT;
|
||||
f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
|
||||
f2 = j << (32 - DBL_SHIFT);
|
||||
frac |= j;
|
||||
FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 128-bit extended -> fpn.
|
||||
*/
|
||||
int
|
||||
__fpu_qtof(fp, i, j, k, l)
|
||||
struct fpn *fp;
|
||||
uint32_t i, j, k, l;
|
||||
{
|
||||
int exp;
|
||||
uint32_t frac, f0, f1, f2, f3;
|
||||
#define EXT_SHIFT (-(EXT_FRACBITS - 3 * 32 - FP_LG)) /* left shift! */
|
||||
|
||||
/*
|
||||
* Note that ext and fpn `line up', hence no shifting needed.
|
||||
*/
|
||||
exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS);
|
||||
frac = i & mask(EXT_FRACBITS - 3 * 32);
|
||||
f0 = (frac << EXT_SHIFT) | (j >> (32 - EXT_SHIFT));
|
||||
f1 = (j << EXT_SHIFT) | (k >> (32 - EXT_SHIFT));
|
||||
f2 = (k << EXT_SHIFT) | (l >> (32 - EXT_SHIFT));
|
||||
f3 = l << EXT_SHIFT;
|
||||
frac |= j | k | l;
|
||||
FP_TOF(exp, EXT_EXP_BIAS, frac, f0, f1, f2, f3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Explode the contents of a / regpair / regquad.
|
||||
* If the input is a signalling NaN, an NV (invalid) exception
|
||||
* will be set. (Note that nothing but NV can occur until ALU
|
||||
* operations are performed.)
|
||||
*/
|
||||
void
|
||||
__fpu_explode(fe, fp, type, reg)
|
||||
struct fpemu *fe;
|
||||
struct fpn *fp;
|
||||
int type, reg;
|
||||
{
|
||||
uint64_t l0 = 0, l1;
|
||||
uint32_t s = 0;
|
||||
|
||||
if (type == FTYPE_LNG || type == FTYPE_DBL || type == FTYPE_EXT) {
|
||||
l0 = __fpu_getreg64(reg & ~1);
|
||||
fp->fp_sign = l0 >> 63;
|
||||
} else {
|
||||
s = __fpu_getreg(reg);
|
||||
fp->fp_sign = s >> 31;
|
||||
}
|
||||
fp->fp_sticky = 0;
|
||||
switch (type) {
|
||||
case FTYPE_LNG:
|
||||
s = __fpu_xtof(fp, l0);
|
||||
break;
|
||||
|
||||
case FTYPE_INT:
|
||||
s = __fpu_itof(fp, s);
|
||||
break;
|
||||
|
||||
case FTYPE_SNG:
|
||||
s = __fpu_stof(fp, s);
|
||||
break;
|
||||
|
||||
case FTYPE_DBL:
|
||||
s = __fpu_dtof(fp, l0 >> 32, l0 & 0xffffffff);
|
||||
break;
|
||||
|
||||
case FTYPE_EXT:
|
||||
l1 = __fpu_getreg64((reg & ~1) + 2);
|
||||
s = __fpu_qtof(fp, l0 >> 32, l0 & 0xffffffff, l1 >> 32,
|
||||
l1 & 0xffffffff);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef _KERNEL_MODE
|
||||
panic("fpu_explode");
|
||||
#else
|
||||
debugger("fpu_explode");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (s == (uint32_t)FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
|
||||
/*
|
||||
* Input is a signalling NaN. All operations that return
|
||||
* an input NaN operand put it through a ``NaN conversion'',
|
||||
* which basically just means ``turn on the quiet bit''.
|
||||
* We do this here so that all NaNs internally look quiet
|
||||
* (we can tell signalling ones by their class).
|
||||
*/
|
||||
fp->fp_mant[0] |= FP_QUIETBIT;
|
||||
fe->fe_cx = FSR_NV; /* assert invalid operand */
|
||||
s = FPC_SNAN;
|
||||
}
|
||||
fp->fp_class = s;
|
||||
DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' :
|
||||
((type == FTYPE_INT) ? 'i' :
|
||||
((type == FTYPE_SNG) ? 's' :
|
||||
((type == FTYPE_DBL) ? 'd' :
|
||||
((type == FTYPE_EXT) ? 'q' : '?')))),
|
||||
reg));
|
||||
DUMPFPN(FPE_REG, fp);
|
||||
DPRINTF(FPE_REG, ("\n"));
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 1995 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Christos Zoulas.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $NetBSD: fpu_extern.h,v 1.4 2000/08/03 18:32:08 eeh Exp $
|
||||
* $FreeBSD: head/lib/libc/sparc64/fpu/fpu_extern.h 326193 2017-11-25 17:12:48Z pfg $
|
||||
*/
|
||||
|
||||
#ifndef _SPARC64_FPU_FPU_EXTERN_H_
|
||||
#define _SPARC64_FPU_FPU_EXTERN_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct utrapframe;
|
||||
struct fpemu;
|
||||
struct fpn;
|
||||
|
||||
/* fpu.c */
|
||||
int __fpu_exception(struct utrapframe *tf);
|
||||
|
||||
/* fpu_add.c */
|
||||
struct fpn *__fpu_add(struct fpemu *);
|
||||
|
||||
/* fpu_compare.c */
|
||||
void __fpu_compare(struct fpemu *, int, int);
|
||||
|
||||
/* fpu_div.c */
|
||||
struct fpn *__fpu_div(struct fpemu *);
|
||||
|
||||
/* fpu_explode.c */
|
||||
int __fpu_itof(struct fpn *, uint32_t);
|
||||
int __fpu_xtof(struct fpn *, uint64_t);
|
||||
int __fpu_stof(struct fpn *, uint32_t);
|
||||
int __fpu_dtof(struct fpn *, uint32_t, uint32_t);
|
||||
int __fpu_qtof(struct fpn *, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
void __fpu_explode(struct fpemu *, struct fpn *, int, int);
|
||||
|
||||
/* fpu_implode.c */
|
||||
uint32_t __fpu_ftoi(struct fpemu *, struct fpn *);
|
||||
uint32_t __fpu_ftox(struct fpemu *, struct fpn *, uint32_t *);
|
||||
uint32_t __fpu_ftos(struct fpemu *, struct fpn *);
|
||||
uint32_t __fpu_ftod(struct fpemu *, struct fpn *, uint32_t *);
|
||||
uint32_t __fpu_ftoq(struct fpemu *, struct fpn *, uint32_t *);
|
||||
void __fpu_implode(struct fpemu *, struct fpn *, int, uint32_t *);
|
||||
|
||||
/* fpu_mul.c */
|
||||
struct fpn *__fpu_mul(struct fpemu *);
|
||||
|
||||
/* fpu_sqrt.c */
|
||||
struct fpn *__fpu_sqrt(struct fpemu *);
|
||||
|
||||
/* fpu_subr.c */
|
||||
/*
|
||||
* Shift a number right some number of bits, taking care of round/sticky.
|
||||
* Note that the result is probably not a well-formed number (it will lack
|
||||
* the normal 1-bit mant[0]&FP_1).
|
||||
*/
|
||||
int __fpu_shr(register struct fpn *, register int);
|
||||
void __fpu_norm(register struct fpn *);
|
||||
/* Build a new Quiet NaN (sign=0, frac=all 1's). */
|
||||
struct fpn *__fpu_newnan(register struct fpemu *);
|
||||
|
||||
#endif /* !_SPARC64_FPU_FPU_EXTERN_H_ */
|
||||
@@ -0,0 +1,549 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_implode.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_implode.c,v 1.8 2001/08/26 05:44:46 eeh Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* FPU subroutines: `implode' internal format numbers into the machine's
|
||||
* `packed binary' format.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef FPU_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "fsr.h"
|
||||
#include "ieee.h"
|
||||
#include "instr.h"
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
static int fpround(struct fpemu *, struct fpn *);
|
||||
static int toinf(struct fpemu *, int);
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
extern void panic(const char*, ...);
|
||||
#else
|
||||
#include <OS.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Round a number (algorithm from Motorola MC68882 manual, modified for
|
||||
* our internal format). Set inexact exception if rounding is required.
|
||||
* Return true iff we rounded up.
|
||||
*
|
||||
* After rounding, we discard the guard and round bits by shifting right
|
||||
* 2 bits (a la fpu_shr(), but we do not bother with fp->fp_sticky).
|
||||
* This saves effort later.
|
||||
*
|
||||
* Note that we may leave the value 2.0 in fp->fp_mant; it is the caller's
|
||||
* responsibility to fix this if necessary.
|
||||
*/
|
||||
static int
|
||||
fpround(struct fpemu *fe, struct fpn *fp)
|
||||
{
|
||||
uint32_t m0, m1, m2, m3;
|
||||
int gr, s;
|
||||
|
||||
m0 = fp->fp_mant[0];
|
||||
m1 = fp->fp_mant[1];
|
||||
m2 = fp->fp_mant[2];
|
||||
m3 = fp->fp_mant[3];
|
||||
gr = m3 & 3;
|
||||
s = fp->fp_sticky;
|
||||
|
||||
/* mant >>= FP_NG */
|
||||
m3 = (m3 >> FP_NG) | (m2 << (32 - FP_NG));
|
||||
m2 = (m2 >> FP_NG) | (m1 << (32 - FP_NG));
|
||||
m1 = (m1 >> FP_NG) | (m0 << (32 - FP_NG));
|
||||
m0 >>= FP_NG;
|
||||
|
||||
if ((gr | s) == 0) /* result is exact: no rounding needed */
|
||||
goto rounddown;
|
||||
|
||||
fe->fe_cx |= FSR_NX; /* inexact */
|
||||
|
||||
/* Go to rounddown to round down; break to round up. */
|
||||
switch (FSR_GET_RD(fe->fe_fsr)) {
|
||||
case FSR_RD_N:
|
||||
default:
|
||||
/*
|
||||
* Round only if guard is set (gr & 2). If guard is set,
|
||||
* but round & sticky both clear, then we want to round
|
||||
* but have a tie, so round to even, i.e., add 1 iff odd.
|
||||
*/
|
||||
if ((gr & 2) == 0)
|
||||
goto rounddown;
|
||||
if ((gr & 1) || fp->fp_sticky || (m3 & 1))
|
||||
break;
|
||||
goto rounddown;
|
||||
|
||||
case FSR_RD_Z:
|
||||
/* Round towards zero, i.e., down. */
|
||||
goto rounddown;
|
||||
|
||||
case FSR_RD_NINF:
|
||||
/* Round towards -Inf: up if negative, down if positive. */
|
||||
if (fp->fp_sign)
|
||||
break;
|
||||
goto rounddown;
|
||||
|
||||
case FSR_RD_PINF:
|
||||
/* Round towards +Inf: up if positive, down otherwise. */
|
||||
if (!fp->fp_sign)
|
||||
break;
|
||||
goto rounddown;
|
||||
}
|
||||
|
||||
/* Bump low bit of mantissa, with carry. */
|
||||
FPU_ADDS(m3, m3, 1);
|
||||
FPU_ADDCS(m2, m2, 0);
|
||||
FPU_ADDCS(m1, m1, 0);
|
||||
FPU_ADDC(m0, m0, 0);
|
||||
fp->fp_mant[0] = m0;
|
||||
fp->fp_mant[1] = m1;
|
||||
fp->fp_mant[2] = m2;
|
||||
fp->fp_mant[3] = m3;
|
||||
return (1);
|
||||
|
||||
rounddown:
|
||||
fp->fp_mant[0] = m0;
|
||||
fp->fp_mant[1] = m1;
|
||||
fp->fp_mant[2] = m2;
|
||||
fp->fp_mant[3] = m3;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For overflow: return true if overflow is to go to +/-Inf, according
|
||||
* to the sign of the overflowing result. If false, overflow is to go
|
||||
* to the largest magnitude value instead.
|
||||
*/
|
||||
static int
|
||||
toinf(struct fpemu *fe, int sign)
|
||||
{
|
||||
int inf;
|
||||
|
||||
/* look at rounding direction */
|
||||
switch (FSR_GET_RD(fe->fe_fsr)) {
|
||||
default:
|
||||
case FSR_RD_N: /* the nearest value is always Inf */
|
||||
inf = 1;
|
||||
break;
|
||||
|
||||
case FSR_RD_Z: /* toward 0 => never towards Inf */
|
||||
inf = 0;
|
||||
break;
|
||||
|
||||
case FSR_RD_PINF: /* toward +Inf iff positive */
|
||||
inf = sign == 0;
|
||||
break;
|
||||
|
||||
case FSR_RD_NINF: /* toward -Inf iff negative */
|
||||
inf = sign;
|
||||
break;
|
||||
}
|
||||
return (inf);
|
||||
}
|
||||
|
||||
/*
|
||||
* fpn -> int (int value returned as return value).
|
||||
*
|
||||
* N.B.: this conversion always rounds towards zero (this is a peculiarity
|
||||
* of the SPARC instruction set).
|
||||
*/
|
||||
uint32_t
|
||||
__fpu_ftoi(fe, fp)
|
||||
struct fpemu *fe;
|
||||
struct fpn *fp;
|
||||
{
|
||||
uint32_t i;
|
||||
int sign, exp;
|
||||
|
||||
sign = fp->fp_sign;
|
||||
switch (fp->fp_class) {
|
||||
case FPC_ZERO:
|
||||
return (0);
|
||||
|
||||
case FPC_NUM:
|
||||
/*
|
||||
* If exp >= 2^32, overflow. Otherwise shift value right
|
||||
* into last mantissa word (this will not exceed 0xffffffff),
|
||||
* shifting any guard and round bits out into the sticky
|
||||
* bit. Then ``round'' towards zero, i.e., just set an
|
||||
* inexact exception if sticky is set (see round()).
|
||||
* If the result is > 0x80000000, or is positive and equals
|
||||
* 0x80000000, overflow; otherwise the last fraction word
|
||||
* is the result.
|
||||
*/
|
||||
if ((exp = fp->fp_exp) >= 32)
|
||||
break;
|
||||
/* NB: the following includes exp < 0 cases */
|
||||
if (__fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
|
||||
fe->fe_cx |= FSR_NX;
|
||||
i = fp->fp_mant[3];
|
||||
if (i >= ((uint32_t)0x80000000 + sign))
|
||||
break;
|
||||
return (sign ? -i : i);
|
||||
|
||||
default: /* Inf, qNaN, sNaN */
|
||||
break;
|
||||
}
|
||||
/* overflow: replace any inexact exception with invalid */
|
||||
fe->fe_cx = (fe->fe_cx & ~FSR_NX) | FSR_NV;
|
||||
return (0x7fffffff + sign);
|
||||
}
|
||||
|
||||
/*
|
||||
* fpn -> extended int (high bits of int value returned as return value).
|
||||
*
|
||||
* N.B.: this conversion always rounds towards zero (this is a peculiarity
|
||||
* of the SPARC instruction set).
|
||||
*/
|
||||
uint32_t
|
||||
__fpu_ftox(fe, fp, res)
|
||||
struct fpemu *fe;
|
||||
struct fpn *fp;
|
||||
uint32_t *res;
|
||||
{
|
||||
uint64_t i;
|
||||
int sign, exp;
|
||||
|
||||
sign = fp->fp_sign;
|
||||
switch (fp->fp_class) {
|
||||
case FPC_ZERO:
|
||||
i = 0;
|
||||
goto done;
|
||||
|
||||
case FPC_NUM:
|
||||
/*
|
||||
* If exp >= 2^64, overflow. Otherwise shift value
|
||||
* right into last mantissa word (this will not exceed
|
||||
* 0xffffffffffffffff), shifting any guard and round
|
||||
* bits out into the sticky bit. Then ``round'' towards
|
||||
* zero, i.e., just set an inexact exception if sticky
|
||||
* is set (see round()).
|
||||
* If the result is > 0x8000000000000000, or is positive
|
||||
* and equals 0x8000000000000000, overflow; otherwise
|
||||
* the last fraction word is the result.
|
||||
*/
|
||||
if ((exp = fp->fp_exp) >= 64)
|
||||
break;
|
||||
/* NB: the following includes exp < 0 cases */
|
||||
if (__fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
|
||||
fe->fe_cx |= FSR_NX;
|
||||
i = ((uint64_t)fp->fp_mant[2]<<32)|fp->fp_mant[3];
|
||||
if (i >= ((uint64_t)0x8000000000000000LL + sign))
|
||||
break;
|
||||
if (sign)
|
||||
i = -i;
|
||||
goto done;
|
||||
|
||||
default: /* Inf, qNaN, sNaN */
|
||||
break;
|
||||
}
|
||||
/* overflow: replace any inexact exception with invalid */
|
||||
fe->fe_cx = (fe->fe_cx & ~FSR_NX) | FSR_NV;
|
||||
i = 0x7fffffffffffffffLL + sign;
|
||||
done:
|
||||
res[1] = i & 0xffffffff;
|
||||
return (i >> 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* fpn -> single (32 bit single returned as return value).
|
||||
* We assume <= 29 bits in a single-precision fraction (1.f part).
|
||||
*/
|
||||
uint32_t
|
||||
__fpu_ftos(fe, fp)
|
||||
struct fpemu *fe;
|
||||
struct fpn *fp;
|
||||
{
|
||||
uint32_t sign = fp->fp_sign << 31;
|
||||
int exp;
|
||||
|
||||
#define SNG_EXP(e) ((e) << SNG_FRACBITS) /* makes e an exponent */
|
||||
#define SNG_MASK (SNG_EXP(1) - 1) /* mask for fraction */
|
||||
|
||||
/* Take care of non-numbers first. */
|
||||
if (ISNAN(fp)) {
|
||||
/*
|
||||
* Preserve upper bits of NaN, per SPARC V8 appendix N.
|
||||
* Note that fp->fp_mant[0] has the quiet bit set,
|
||||
* even if it is classified as a signalling NaN.
|
||||
*/
|
||||
(void) __fpu_shr(fp, FP_NMANT - 1 - SNG_FRACBITS);
|
||||
exp = SNG_EXP_INFNAN;
|
||||
goto done;
|
||||
}
|
||||
if (ISINF(fp))
|
||||
return (sign | SNG_EXP(SNG_EXP_INFNAN));
|
||||
if (ISZERO(fp))
|
||||
return (sign);
|
||||
|
||||
/*
|
||||
* Normals (including subnormals). Drop all the fraction bits
|
||||
* (including the explicit ``implied'' 1 bit) down into the
|
||||
* single-precision range. If the number is subnormal, move
|
||||
* the ``implied'' 1 into the explicit range as well, and shift
|
||||
* right to introduce leading zeroes. Rounding then acts
|
||||
* differently for normals and subnormals: the largest subnormal
|
||||
* may round to the smallest normal (1.0 x 2^minexp), or may
|
||||
* remain subnormal. A number that is subnormal before rounding
|
||||
* will signal an underflow if the result is inexact or if underflow
|
||||
* traps are enabled.
|
||||
*
|
||||
* Rounding a normal, on the other hand, always produces another
|
||||
* normal (although either way the result might be too big for
|
||||
* single precision, and cause an overflow). If rounding a
|
||||
* normal produces 2.0 in the fraction, we need not adjust that
|
||||
* fraction at all, since both 1.0 and 2.0 are zero under the
|
||||
* fraction mask.
|
||||
*
|
||||
* Note that the guard and round bits vanish from the number after
|
||||
* rounding.
|
||||
*/
|
||||
if ((exp = fp->fp_exp + SNG_EXP_BIAS) <= 0) { /* subnormal */
|
||||
/* -NG for g,r; -SNG_FRACBITS-exp for fraction */
|
||||
(void) __fpu_shr(fp, FP_NMANT - FP_NG - SNG_FRACBITS - exp);
|
||||
if (fpround(fe, fp) && fp->fp_mant[3] == SNG_EXP(1)) {
|
||||
fe->fe_cx |= FSR_UF;
|
||||
return (sign | SNG_EXP(1) | 0);
|
||||
}
|
||||
if ((fe->fe_cx & FSR_NX) ||
|
||||
(fe->fe_fsr & (FSR_UF << FSR_TEM_SHIFT)))
|
||||
fe->fe_cx |= FSR_UF;
|
||||
return (sign | SNG_EXP(0) | fp->fp_mant[3]);
|
||||
}
|
||||
/* -FP_NG for g,r; -1 for implied 1; -SNG_FRACBITS for fraction */
|
||||
(void) __fpu_shr(fp, FP_NMANT - FP_NG - 1 - SNG_FRACBITS);
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((fp->fp_mant[3] & SNG_EXP(1 << FP_NG)) == 0)
|
||||
__utrap_panic("fpu_ftos");
|
||||
#endif
|
||||
if (fpround(fe, fp) && fp->fp_mant[3] == SNG_EXP(2))
|
||||
exp++;
|
||||
if (exp >= SNG_EXP_INFNAN) {
|
||||
/* overflow to inf or to max single */
|
||||
fe->fe_cx |= FSR_OF | FSR_NX;
|
||||
if (toinf(fe, sign))
|
||||
return (sign | SNG_EXP(SNG_EXP_INFNAN));
|
||||
return (sign | SNG_EXP(SNG_EXP_INFNAN - 1) | SNG_MASK);
|
||||
}
|
||||
done:
|
||||
/* phew, made it */
|
||||
return (sign | SNG_EXP(exp) | (fp->fp_mant[3] & SNG_MASK));
|
||||
}
|
||||
|
||||
/*
|
||||
* fpn -> double (32 bit high-order result returned; 32-bit low order result
|
||||
* left in res[1]). Assumes <= 61 bits in double precision fraction.
|
||||
*
|
||||
* This code mimics fpu_ftos; see it for comments.
|
||||
*/
|
||||
uint32_t
|
||||
__fpu_ftod(fe, fp, res)
|
||||
struct fpemu *fe;
|
||||
struct fpn *fp;
|
||||
uint32_t *res;
|
||||
{
|
||||
uint32_t sign = fp->fp_sign << 31;
|
||||
int exp;
|
||||
|
||||
#define DBL_EXP(e) ((e) << (DBL_FRACBITS & 31))
|
||||
#define DBL_MASK (DBL_EXP(1) - 1)
|
||||
|
||||
if (ISNAN(fp)) {
|
||||
(void) __fpu_shr(fp, FP_NMANT - 1 - DBL_FRACBITS);
|
||||
exp = DBL_EXP_INFNAN;
|
||||
goto done;
|
||||
}
|
||||
if (ISINF(fp)) {
|
||||
sign |= DBL_EXP(DBL_EXP_INFNAN);
|
||||
goto zero;
|
||||
}
|
||||
if (ISZERO(fp)) {
|
||||
zero: res[1] = 0;
|
||||
return (sign);
|
||||
}
|
||||
|
||||
if ((exp = fp->fp_exp + DBL_EXP_BIAS) <= 0) {
|
||||
(void) __fpu_shr(fp, FP_NMANT - FP_NG - DBL_FRACBITS - exp);
|
||||
if (fpround(fe, fp) && fp->fp_mant[2] == DBL_EXP(1)) {
|
||||
fe->fe_cx |= FSR_UF;
|
||||
res[1] = 0;
|
||||
return (sign | DBL_EXP(1) | 0);
|
||||
}
|
||||
if ((fe->fe_cx & FSR_NX) ||
|
||||
(fe->fe_fsr & (FSR_UF << FSR_TEM_SHIFT)))
|
||||
fe->fe_cx |= FSR_UF;
|
||||
exp = 0;
|
||||
goto done;
|
||||
}
|
||||
(void) __fpu_shr(fp, FP_NMANT - FP_NG - 1 - DBL_FRACBITS);
|
||||
if (fpround(fe, fp) && fp->fp_mant[2] == DBL_EXP(2))
|
||||
exp++;
|
||||
if (exp >= DBL_EXP_INFNAN) {
|
||||
fe->fe_cx |= FSR_OF | FSR_NX;
|
||||
if (toinf(fe, sign)) {
|
||||
res[1] = 0;
|
||||
return (sign | DBL_EXP(DBL_EXP_INFNAN) | 0);
|
||||
}
|
||||
res[1] = ~0;
|
||||
return (sign | DBL_EXP(DBL_EXP_INFNAN - 1) | DBL_MASK);
|
||||
}
|
||||
done:
|
||||
res[1] = fp->fp_mant[3];
|
||||
return (sign | DBL_EXP(exp) | (fp->fp_mant[2] & DBL_MASK));
|
||||
}
|
||||
|
||||
/*
|
||||
* fpn -> extended (32 bit high-order result returned; low-order fraction
|
||||
* words left in res[1]..res[3]). Like ftod, which is like ftos ... but
|
||||
* our internal format *is* extended precision, plus 2 bits for guard/round,
|
||||
* so we can avoid a small bit of work.
|
||||
*/
|
||||
uint32_t
|
||||
__fpu_ftoq(fe, fp, res)
|
||||
struct fpemu *fe;
|
||||
struct fpn *fp;
|
||||
uint32_t *res;
|
||||
{
|
||||
uint32_t sign = fp->fp_sign << 31;
|
||||
int exp;
|
||||
|
||||
#define EXT_EXP(e) ((e) << (EXT_FRACBITS & 31))
|
||||
#define EXT_MASK (EXT_EXP(1) - 1)
|
||||
|
||||
if (ISNAN(fp)) {
|
||||
(void) __fpu_shr(fp, 2); /* since we are not rounding */
|
||||
exp = EXT_EXP_INFNAN;
|
||||
goto done;
|
||||
}
|
||||
if (ISINF(fp)) {
|
||||
sign |= EXT_EXP(EXT_EXP_INFNAN);
|
||||
goto zero;
|
||||
}
|
||||
if (ISZERO(fp)) {
|
||||
zero: res[1] = res[2] = res[3] = 0;
|
||||
return (sign);
|
||||
}
|
||||
|
||||
if ((exp = fp->fp_exp + EXT_EXP_BIAS) <= 0) {
|
||||
(void) __fpu_shr(fp, FP_NMANT - FP_NG - EXT_FRACBITS - exp);
|
||||
if (fpround(fe, fp) && fp->fp_mant[0] == EXT_EXP(1)) {
|
||||
fe->fe_cx |= FSR_UF;
|
||||
res[1] = res[2] = res[3] = 0;
|
||||
return (sign | EXT_EXP(1) | 0);
|
||||
}
|
||||
if ((fe->fe_cx & FSR_NX) ||
|
||||
(fe->fe_fsr & (FSR_UF << FSR_TEM_SHIFT)))
|
||||
fe->fe_cx |= FSR_UF;
|
||||
exp = 0;
|
||||
goto done;
|
||||
}
|
||||
/* Since internal == extended, no need to shift here. */
|
||||
if (fpround(fe, fp) && fp->fp_mant[0] == EXT_EXP(2))
|
||||
exp++;
|
||||
if (exp >= EXT_EXP_INFNAN) {
|
||||
fe->fe_cx |= FSR_OF | FSR_NX;
|
||||
if (toinf(fe, sign)) {
|
||||
res[1] = res[2] = res[3] = 0;
|
||||
return (sign | EXT_EXP(EXT_EXP_INFNAN) | 0);
|
||||
}
|
||||
res[1] = res[2] = res[3] = ~0;
|
||||
return (sign | EXT_EXP(EXT_EXP_INFNAN - 1) | EXT_MASK);
|
||||
}
|
||||
done:
|
||||
res[1] = fp->fp_mant[1];
|
||||
res[2] = fp->fp_mant[2];
|
||||
res[3] = fp->fp_mant[3];
|
||||
return (sign | EXT_EXP(exp) | (fp->fp_mant[0] & EXT_MASK));
|
||||
}
|
||||
|
||||
/*
|
||||
* Implode an fpn, writing the result into the given space.
|
||||
*/
|
||||
void
|
||||
__fpu_implode(fe, fp, type, space)
|
||||
struct fpemu *fe;
|
||||
struct fpn *fp;
|
||||
int type;
|
||||
uint32_t *space;
|
||||
{
|
||||
|
||||
switch (type) {
|
||||
case FTYPE_LNG:
|
||||
space[0] = __fpu_ftox(fe, fp, space);
|
||||
break;
|
||||
|
||||
case FTYPE_INT:
|
||||
space[0] = __fpu_ftoi(fe, fp);
|
||||
break;
|
||||
|
||||
case FTYPE_SNG:
|
||||
space[0] = __fpu_ftos(fe, fp);
|
||||
break;
|
||||
|
||||
case FTYPE_DBL:
|
||||
space[0] = __fpu_ftod(fe, fp, space);
|
||||
break;
|
||||
|
||||
case FTYPE_EXT:
|
||||
/* funky rounding precision options ?? */
|
||||
space[0] = __fpu_ftoq(fe, fp, space);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef _KERNEL_MODE
|
||||
panic("fpu_implode");
|
||||
#else
|
||||
debugger("fpu_implode");
|
||||
#endif
|
||||
}
|
||||
DPRINTF(FPE_REG, ("fpu_implode: %x %x %x %x\n",
|
||||
space[0], space[1], space[2], space[3]));
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_mul.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_mul.c,v 1.2 1994/11/20 20:52:44 deraadt Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* Perform an FPU multiply (return x * y).
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
/*
|
||||
* The multiplication algorithm for normal numbers is as follows:
|
||||
*
|
||||
* The fraction of the product is built in the usual stepwise fashion.
|
||||
* Each step consists of shifting the accumulator right one bit
|
||||
* (maintaining any guard bits) and, if the next bit in y is set,
|
||||
* adding the multiplicand (x) to the accumulator. Then, in any case,
|
||||
* we advance one bit leftward in y. Algorithmically:
|
||||
*
|
||||
* A = 0;
|
||||
* for (bit = 0; bit < FP_NMANT; bit++) {
|
||||
* sticky |= A & 1, A >>= 1;
|
||||
* if (Y & (1 << bit))
|
||||
* A += X;
|
||||
* }
|
||||
*
|
||||
* (X and Y here represent the mantissas of x and y respectively.)
|
||||
* The resultant accumulator (A) is the product's mantissa. It may
|
||||
* be as large as 11.11111... in binary and hence may need to be
|
||||
* shifted right, but at most one bit.
|
||||
*
|
||||
* Since we do not have efficient multiword arithmetic, we code the
|
||||
* accumulator as four separate words, just like any other mantissa.
|
||||
* We use local `register' variables in the hope that this is faster
|
||||
* than memory. We keep x->fp_mant in locals for the same reason.
|
||||
*
|
||||
* In the algorithm above, the bits in y are inspected one at a time.
|
||||
* We will pick them up 32 at a time and then deal with those 32, one
|
||||
* at a time. Note, however, that we know several things about y:
|
||||
*
|
||||
* - the guard and round bits at the bottom are sure to be zero;
|
||||
*
|
||||
* - often many low bits are zero (y is often from a single or double
|
||||
* precision source);
|
||||
*
|
||||
* - bit FP_NMANT-1 is set, and FP_1*2 fits in a word.
|
||||
*
|
||||
* We can also test for 32-zero-bits swiftly. In this case, the center
|
||||
* part of the loop---setting sticky, shifting A, and not adding---will
|
||||
* run 32 times without adding X to A. We can do a 32-bit shift faster
|
||||
* by simply moving words. Since zeros are common, we optimize this case.
|
||||
* Furthermore, since A is initially zero, we can omit the shift as well
|
||||
* until we reach a nonzero word.
|
||||
*/
|
||||
struct fpn *
|
||||
__fpu_mul(fe)
|
||||
struct fpemu *fe;
|
||||
{
|
||||
struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
|
||||
u_int a3, a2, a1, a0, x3, x2, x1, x0, bit, m;
|
||||
int sticky;
|
||||
FPU_DECL_CARRY
|
||||
|
||||
/*
|
||||
* Put the `heavier' operand on the right (see fpu_emu.h).
|
||||
* Then we will have one of the following cases, taken in the
|
||||
* following order:
|
||||
*
|
||||
* - y = NaN. Implied: if only one is a signalling NaN, y is.
|
||||
* The result is y.
|
||||
* - y = Inf. Implied: x != NaN (is 0, number, or Inf: the NaN
|
||||
* case was taken care of earlier).
|
||||
* If x = 0, the result is NaN. Otherwise the result
|
||||
* is y, with its sign reversed if x is negative.
|
||||
* - x = 0. Implied: y is 0 or number.
|
||||
* The result is 0 (with XORed sign as usual).
|
||||
* - other. Implied: both x and y are numbers.
|
||||
* The result is x * y (XOR sign, multiply bits, add exponents).
|
||||
*/
|
||||
ORDER(x, y);
|
||||
if (ISNAN(y))
|
||||
return (y);
|
||||
if (ISINF(y)) {
|
||||
if (ISZERO(x))
|
||||
return (__fpu_newnan(fe));
|
||||
y->fp_sign ^= x->fp_sign;
|
||||
return (y);
|
||||
}
|
||||
if (ISZERO(x)) {
|
||||
x->fp_sign ^= y->fp_sign;
|
||||
return (x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup. In the code below, the mask `m' will hold the current
|
||||
* mantissa byte from y. The variable `bit' denotes the bit
|
||||
* within m. We also define some macros to deal with everything.
|
||||
*/
|
||||
x3 = x->fp_mant[3];
|
||||
x2 = x->fp_mant[2];
|
||||
x1 = x->fp_mant[1];
|
||||
x0 = x->fp_mant[0];
|
||||
sticky = a3 = a2 = a1 = a0 = 0;
|
||||
|
||||
#define ADD /* A += X */ \
|
||||
FPU_ADDS(a3, a3, x3); \
|
||||
FPU_ADDCS(a2, a2, x2); \
|
||||
FPU_ADDCS(a1, a1, x1); \
|
||||
FPU_ADDC(a0, a0, x0)
|
||||
|
||||
#define SHR1 /* A >>= 1, with sticky */ \
|
||||
sticky |= a3 & 1, a3 = (a3 >> 1) | (a2 << 31), \
|
||||
a2 = (a2 >> 1) | (a1 << 31), a1 = (a1 >> 1) | (a0 << 31), a0 >>= 1
|
||||
|
||||
#define SHR32 /* A >>= 32, with sticky */ \
|
||||
sticky |= a3, a3 = a2, a2 = a1, a1 = a0, a0 = 0
|
||||
|
||||
#define STEP /* each 1-bit step of the multiplication */ \
|
||||
SHR1; if (bit & m) { ADD; }; bit <<= 1
|
||||
|
||||
/*
|
||||
* We are ready to begin. The multiply loop runs once for each
|
||||
* of the four 32-bit words. Some words, however, are special.
|
||||
* As noted above, the low order bits of Y are often zero. Even
|
||||
* if not, the first loop can certainly skip the guard bits.
|
||||
* The last word of y has its highest 1-bit in position FP_NMANT-1,
|
||||
* so we stop the loop when we move past that bit.
|
||||
*/
|
||||
if ((m = y->fp_mant[3]) == 0) {
|
||||
/* SHR32; */ /* unneeded since A==0 */
|
||||
} else {
|
||||
bit = 1 << FP_NG;
|
||||
do {
|
||||
STEP;
|
||||
} while (bit != 0);
|
||||
}
|
||||
if ((m = y->fp_mant[2]) == 0) {
|
||||
SHR32;
|
||||
} else {
|
||||
bit = 1;
|
||||
do {
|
||||
STEP;
|
||||
} while (bit != 0);
|
||||
}
|
||||
if ((m = y->fp_mant[1]) == 0) {
|
||||
SHR32;
|
||||
} else {
|
||||
bit = 1;
|
||||
do {
|
||||
STEP;
|
||||
} while (bit != 0);
|
||||
}
|
||||
m = y->fp_mant[0]; /* definitely != 0 */
|
||||
bit = 1;
|
||||
do {
|
||||
STEP;
|
||||
} while (bit <= m);
|
||||
|
||||
/*
|
||||
* Done with mantissa calculation. Get exponent and handle
|
||||
* 11.111...1 case, then put result in place. We reuse x since
|
||||
* it already has the right class (FP_NUM).
|
||||
*/
|
||||
m = x->fp_exp + y->fp_exp;
|
||||
if (a0 >= FP_2) {
|
||||
SHR1;
|
||||
m++;
|
||||
}
|
||||
x->fp_sign ^= y->fp_sign;
|
||||
x->fp_exp = m;
|
||||
x->fp_sticky = sticky;
|
||||
x->fp_mant[3] = a3;
|
||||
x->fp_mant[2] = a2;
|
||||
x->fp_mant[1] = a1;
|
||||
x->fp_mant[0] = a0;
|
||||
return (x);
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*-
|
||||
* Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Define arrays of leaf functions to load/store fp registers to memory. See
|
||||
* fpu_reg.h for the definitions to use this from C code. The function sizes
|
||||
* defines there must be kept in sync with this file!
|
||||
*/
|
||||
|
||||
.macro ld32 reg
|
||||
retl
|
||||
ld [%o0], %f\reg
|
||||
.endm
|
||||
|
||||
.macro st32 reg
|
||||
retl
|
||||
st %f\reg, [%o0]
|
||||
.endm
|
||||
|
||||
.macro ld64 reg
|
||||
retl
|
||||
ldd [%o0], %f\reg
|
||||
.endm
|
||||
|
||||
.macro st64 reg
|
||||
retl
|
||||
std %f\reg, [%o0]
|
||||
.endm
|
||||
|
||||
/* The actual function arrays. */
|
||||
.globl __fpu_ld32
|
||||
__fpu_ld32:
|
||||
ld32 0
|
||||
ld32 1
|
||||
ld32 2
|
||||
ld32 3
|
||||
ld32 4
|
||||
ld32 5
|
||||
ld32 6
|
||||
ld32 7
|
||||
ld32 8
|
||||
ld32 9
|
||||
ld32 10
|
||||
ld32 11
|
||||
ld32 12
|
||||
ld32 13
|
||||
ld32 14
|
||||
ld32 15
|
||||
ld32 16
|
||||
ld32 17
|
||||
ld32 18
|
||||
ld32 19
|
||||
ld32 20
|
||||
ld32 21
|
||||
ld32 22
|
||||
ld32 23
|
||||
ld32 24
|
||||
ld32 25
|
||||
ld32 26
|
||||
ld32 27
|
||||
ld32 28
|
||||
ld32 29
|
||||
ld32 30
|
||||
ld32 31
|
||||
|
||||
.globl __fpu_st32
|
||||
__fpu_st32:
|
||||
st32 0
|
||||
st32 1
|
||||
st32 2
|
||||
st32 3
|
||||
st32 4
|
||||
st32 5
|
||||
st32 6
|
||||
st32 7
|
||||
st32 8
|
||||
st32 9
|
||||
st32 10
|
||||
st32 11
|
||||
st32 12
|
||||
st32 13
|
||||
st32 14
|
||||
st32 15
|
||||
st32 16
|
||||
st32 17
|
||||
st32 18
|
||||
st32 19
|
||||
st32 20
|
||||
st32 21
|
||||
st32 22
|
||||
st32 23
|
||||
st32 24
|
||||
st32 25
|
||||
st32 26
|
||||
st32 27
|
||||
st32 28
|
||||
st32 29
|
||||
st32 30
|
||||
st32 31
|
||||
|
||||
.globl __fpu_ld64
|
||||
__fpu_ld64:
|
||||
ld64 0
|
||||
ld64 2
|
||||
ld64 4
|
||||
ld64 6
|
||||
ld64 8
|
||||
ld64 10
|
||||
ld64 12
|
||||
ld64 14
|
||||
ld64 16
|
||||
ld64 18
|
||||
ld64 20
|
||||
ld64 22
|
||||
ld64 24
|
||||
ld64 26
|
||||
ld64 28
|
||||
ld64 30
|
||||
ld64 32
|
||||
ld64 34
|
||||
ld64 36
|
||||
ld64 38
|
||||
ld64 40
|
||||
ld64 42
|
||||
ld64 44
|
||||
ld64 46
|
||||
ld64 48
|
||||
ld64 50
|
||||
ld64 52
|
||||
ld64 54
|
||||
ld64 56
|
||||
ld64 58
|
||||
ld64 60
|
||||
ld64 62
|
||||
|
||||
.globl __fpu_st64
|
||||
__fpu_st64:
|
||||
st64 0
|
||||
st64 2
|
||||
st64 4
|
||||
st64 6
|
||||
st64 8
|
||||
st64 10
|
||||
st64 12
|
||||
st64 14
|
||||
st64 16
|
||||
st64 18
|
||||
st64 20
|
||||
st64 22
|
||||
st64 24
|
||||
st64 26
|
||||
st64 28
|
||||
st64 30
|
||||
st64 32
|
||||
st64 34
|
||||
st64 36
|
||||
st64 38
|
||||
st64 40
|
||||
st64 42
|
||||
st64 44
|
||||
st64 46
|
||||
st64 48
|
||||
st64 50
|
||||
st64 52
|
||||
st64 54
|
||||
st64 56
|
||||
st64 58
|
||||
st64 60
|
||||
st64 62
|
||||
@@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2002 by Thomas Moestl <[email protected]>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libc/sparc64/fpu/fpu_reg.h 327232 2017-12-27 03:23:41Z eadler $
|
||||
*/
|
||||
|
||||
#ifndef _LIBC_SPARC64_FPU_FPU_REG_H_
|
||||
#define _LIBC_SPARC64_FPU_FPU_REG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* These are not really of type char[]. They are arrays of functions defined
|
||||
* in fpu_reg.S; each array member loads/stores a certain fpu register of the
|
||||
* given size.
|
||||
*/
|
||||
extern char __fpu_ld32[];
|
||||
extern char __fpu_st32[];
|
||||
extern char __fpu_ld64[];
|
||||
extern char __fpu_st64[];
|
||||
|
||||
/* Size of the functions in the arrays. */
|
||||
#define FPU_LD32_SZ 8
|
||||
#define FPU_ST32_SZ 8
|
||||
#define FPU_LD64_SZ 8
|
||||
#define FPU_ST64_SZ 8
|
||||
|
||||
/* Typedefs for convenient casts in the functions below. */
|
||||
typedef void (fp_ldst32_fn)(uint32_t *);
|
||||
typedef void (fp_ldst64_fn)(uint64_t *);
|
||||
|
||||
/*
|
||||
* These are the functions that are actually used in the fpu emulation code to
|
||||
* access the fp registers. They are usually not used more than once, so
|
||||
* caching needs not be done here.
|
||||
*/
|
||||
static __inline uint32_t
|
||||
__fpu_getreg(int r)
|
||||
{
|
||||
uint32_t rv;
|
||||
|
||||
((fp_ldst32_fn *)&__fpu_st32[r * FPU_ST32_SZ])(&rv);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static __inline uint64_t
|
||||
__fpu_getreg64(int r)
|
||||
{
|
||||
uint64_t rv;
|
||||
|
||||
((fp_ldst64_fn *)&__fpu_st64[(r >> 1) * FPU_ST64_SZ])(&rv);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
__fpu_setreg(int r, uint32_t v)
|
||||
{
|
||||
|
||||
((fp_ldst32_fn *)&__fpu_ld32[r * FPU_LD32_SZ])(&v);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
__fpu_setreg64(int r, uint64_t v)
|
||||
{
|
||||
|
||||
((fp_ldst64_fn *)&__fpu_ld64[(r >> 1) * FPU_LD64_SZ])(&v);
|
||||
}
|
||||
|
||||
#endif /* _LIBC_SPARC64_FPU_FPU_REG_H_ */
|
||||
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_sqrt.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_sqrt.c,v 1.2 1994/11/20 20:52:46 deraadt Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* Perform an FPU square root (return sqrt(x)).
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
/*
|
||||
* Our task is to calculate the square root of a floating point number x0.
|
||||
* This number x normally has the form:
|
||||
*
|
||||
* exp
|
||||
* x = mant * 2 (where 1 <= mant < 2 and exp is an integer)
|
||||
*
|
||||
* This can be left as it stands, or the mantissa can be doubled and the
|
||||
* exponent decremented:
|
||||
*
|
||||
* exp-1
|
||||
* x = (2 * mant) * 2 (where 2 <= 2 * mant < 4)
|
||||
*
|
||||
* If the exponent `exp' is even, the square root of the number is best
|
||||
* handled using the first form, and is by definition equal to:
|
||||
*
|
||||
* exp/2
|
||||
* sqrt(x) = sqrt(mant) * 2
|
||||
*
|
||||
* If exp is odd, on the other hand, it is convenient to use the second
|
||||
* form, giving:
|
||||
*
|
||||
* (exp-1)/2
|
||||
* sqrt(x) = sqrt(2 * mant) * 2
|
||||
*
|
||||
* In the first case, we have
|
||||
*
|
||||
* 1 <= mant < 2
|
||||
*
|
||||
* and therefore
|
||||
*
|
||||
* sqrt(1) <= sqrt(mant) < sqrt(2)
|
||||
*
|
||||
* while in the second case we have
|
||||
*
|
||||
* 2 <= 2*mant < 4
|
||||
*
|
||||
* and therefore
|
||||
*
|
||||
* sqrt(2) <= sqrt(2*mant) < sqrt(4)
|
||||
*
|
||||
* so that in any case, we are sure that
|
||||
*
|
||||
* sqrt(1) <= sqrt(n * mant) < sqrt(4), n = 1 or 2
|
||||
*
|
||||
* or
|
||||
*
|
||||
* 1 <= sqrt(n * mant) < 2, n = 1 or 2.
|
||||
*
|
||||
* This root is therefore a properly formed mantissa for a floating
|
||||
* point number. The exponent of sqrt(x) is either exp/2 or (exp-1)/2
|
||||
* as above. This leaves us with the problem of finding the square root
|
||||
* of a fixed-point number in the range [1..4).
|
||||
*
|
||||
* Though it may not be instantly obvious, the following square root
|
||||
* algorithm works for any integer x of an even number of bits, provided
|
||||
* that no overflows occur:
|
||||
*
|
||||
* let q = 0
|
||||
* for k = NBITS-1 to 0 step -1 do -- for each digit in the answer...
|
||||
* x *= 2 -- multiply by radix, for next digit
|
||||
* if x >= 2q + 2^k then -- if adding 2^k does not
|
||||
* x -= 2q + 2^k -- exceed the correct root,
|
||||
* q += 2^k -- add 2^k and adjust x
|
||||
* fi
|
||||
* done
|
||||
* sqrt = q / 2^(NBITS/2) -- (and any remainder is in x)
|
||||
*
|
||||
* If NBITS is odd (so that k is initially even), we can just add another
|
||||
* zero bit at the top of x. Doing so means that q is not going to acquire
|
||||
* a 1 bit in the first trip around the loop (since x0 < 2^NBITS). If the
|
||||
* final value in x is not needed, or can be off by a factor of 2, this is
|
||||
* equivalant to moving the `x *= 2' step to the bottom of the loop:
|
||||
*
|
||||
* for k = NBITS-1 to 0 step -1 do if ... fi; x *= 2; done
|
||||
*
|
||||
* and the result q will then be sqrt(x0) * 2^floor(NBITS / 2).
|
||||
* (Since the algorithm is destructive on x, we will call x's initial
|
||||
* value, for which q is some power of two times its square root, x0.)
|
||||
*
|
||||
* If we insert a loop invariant y = 2q, we can then rewrite this using
|
||||
* C notation as:
|
||||
*
|
||||
* q = y = 0; x = x0;
|
||||
* for (k = NBITS; --k >= 0;) {
|
||||
* #if (NBITS is even)
|
||||
* x *= 2;
|
||||
* #endif
|
||||
* t = y + (1 << k);
|
||||
* if (x >= t) {
|
||||
* x -= t;
|
||||
* q += 1 << k;
|
||||
* y += 1 << (k + 1);
|
||||
* }
|
||||
* #if (NBITS is odd)
|
||||
* x *= 2;
|
||||
* #endif
|
||||
* }
|
||||
*
|
||||
* If x0 is fixed point, rather than an integer, we can simply alter the
|
||||
* scale factor between q and sqrt(x0). As it happens, we can easily arrange
|
||||
* for the scale factor to be 2**0 or 1, so that sqrt(x0) == q.
|
||||
*
|
||||
* In our case, however, x0 (and therefore x, y, q, and t) are multiword
|
||||
* integers, which adds some complication. But note that q is built one
|
||||
* bit at a time, from the top down, and is not used itself in the loop
|
||||
* (we use 2q as held in y instead). This means we can build our answer
|
||||
* in an integer, one word at a time, which saves a bit of work. Also,
|
||||
* since 1 << k is always a `new' bit in q, 1 << k and 1 << (k+1) are
|
||||
* `new' bits in y and we can set them with an `or' operation rather than
|
||||
* a full-blown multiword add.
|
||||
*
|
||||
* We are almost done, except for one snag. We must prove that none of our
|
||||
* intermediate calculations can overflow. We know that x0 is in [1..4)
|
||||
* and therefore the square root in q will be in [1..2), but what about x,
|
||||
* y, and t?
|
||||
*
|
||||
* We know that y = 2q at the beginning of each loop. (The relation only
|
||||
* fails temporarily while y and q are being updated.) Since q < 2, y < 4.
|
||||
* The sum in t can, in our case, be as much as y+(1<<1) = y+2 < 6, and.
|
||||
* Furthermore, we can prove with a bit of work that x never exceeds y by
|
||||
* more than 2, so that even after doubling, 0 <= x < 8. (This is left as
|
||||
* an exercise to the reader, mostly because I have become tired of working
|
||||
* on this comment.)
|
||||
*
|
||||
* If our floating point mantissas (which are of the form 1.frac) occupy
|
||||
* B+1 bits, our largest intermediary needs at most B+3 bits, or two extra.
|
||||
* In fact, we want even one more bit (for a carry, to avoid compares), or
|
||||
* three extra. There is a comment in fpu_emu.h reminding maintainers of
|
||||
* this, so we have some justification in assuming it.
|
||||
*/
|
||||
struct fpn *
|
||||
__fpu_sqrt(fe)
|
||||
struct fpemu *fe;
|
||||
{
|
||||
struct fpn *x = &fe->fe_f1;
|
||||
u_int bit, q, tt;
|
||||
u_int x0, x1, x2, x3;
|
||||
u_int y0, y1, y2, y3;
|
||||
u_int d0, d1, d2, d3;
|
||||
int e;
|
||||
|
||||
/*
|
||||
* Take care of special cases first. In order:
|
||||
*
|
||||
* sqrt(NaN) = NaN
|
||||
* sqrt(+0) = +0
|
||||
* sqrt(-0) = -0
|
||||
* sqrt(x < 0) = NaN (including sqrt(-Inf))
|
||||
* sqrt(+Inf) = +Inf
|
||||
*
|
||||
* Then all that remains are numbers with mantissas in [1..2).
|
||||
*/
|
||||
if (ISNAN(x) || ISZERO(x))
|
||||
return (x);
|
||||
if (x->fp_sign)
|
||||
return (__fpu_newnan(fe));
|
||||
if (ISINF(x))
|
||||
return (x);
|
||||
|
||||
/*
|
||||
* Calculate result exponent. As noted above, this may involve
|
||||
* doubling the mantissa. We will also need to double x each
|
||||
* time around the loop, so we define a macro for this here, and
|
||||
* we break out the multiword mantissa.
|
||||
*/
|
||||
#ifdef FPU_SHL1_BY_ADD
|
||||
#define DOUBLE_X { \
|
||||
FPU_ADDS(x3, x3, x3); FPU_ADDCS(x2, x2, x2); \
|
||||
FPU_ADDCS(x1, x1, x1); FPU_ADDC(x0, x0, x0); \
|
||||
}
|
||||
#else
|
||||
#define DOUBLE_X { \
|
||||
x0 = (x0 << 1) | (x1 >> 31); x1 = (x1 << 1) | (x2 >> 31); \
|
||||
x2 = (x2 << 1) | (x3 >> 31); x3 <<= 1; \
|
||||
}
|
||||
#endif
|
||||
#if (FP_NMANT & 1) != 0
|
||||
# define ODD_DOUBLE DOUBLE_X
|
||||
# define EVEN_DOUBLE /* nothing */
|
||||
#else
|
||||
# define ODD_DOUBLE /* nothing */
|
||||
# define EVEN_DOUBLE DOUBLE_X
|
||||
#endif
|
||||
x0 = x->fp_mant[0];
|
||||
x1 = x->fp_mant[1];
|
||||
x2 = x->fp_mant[2];
|
||||
x3 = x->fp_mant[3];
|
||||
e = x->fp_exp;
|
||||
if (e & 1) /* exponent is odd; use sqrt(2mant) */
|
||||
DOUBLE_X;
|
||||
/* THE FOLLOWING ASSUMES THAT RIGHT SHIFT DOES SIGN EXTENSION */
|
||||
x->fp_exp = e >> 1; /* calculates (e&1 ? (e-1)/2 : e/2 */
|
||||
|
||||
/*
|
||||
* Now calculate the mantissa root. Since x is now in [1..4),
|
||||
* we know that the first trip around the loop will definitely
|
||||
* set the top bit in q, so we can do that manually and start
|
||||
* the loop at the next bit down instead. We must be sure to
|
||||
* double x correctly while doing the `known q=1.0'.
|
||||
*
|
||||
* We do this one mantissa-word at a time, as noted above, to
|
||||
* save work. To avoid `(1U << 31) << 1', we also do the top bit
|
||||
* outside of each per-word loop.
|
||||
*
|
||||
* The calculation `t = y + bit' breaks down into `t0 = y0, ...,
|
||||
* t3 = y3, t? |= bit' for the appropriate word. Since the bit
|
||||
* is always a `new' one, this means that three of the `t?'s are
|
||||
* just the corresponding `y?'; we use `#define's here for this.
|
||||
* The variable `tt' holds the actual `t?' variable.
|
||||
*/
|
||||
|
||||
/* calculate q0 */
|
||||
#define t0 tt
|
||||
bit = FP_1;
|
||||
EVEN_DOUBLE;
|
||||
/* if (x >= (t0 = y0 | bit)) { */ /* always true */
|
||||
q = bit;
|
||||
x0 -= bit;
|
||||
y0 = bit << 1;
|
||||
/* } */
|
||||
ODD_DOUBLE;
|
||||
while ((bit >>= 1) != 0) { /* for remaining bits in q0 */
|
||||
EVEN_DOUBLE;
|
||||
t0 = y0 | bit; /* t = y + bit */
|
||||
if (x0 >= t0) { /* if x >= t then */
|
||||
x0 -= t0; /* x -= t */
|
||||
q |= bit; /* q += bit */
|
||||
y0 |= bit << 1; /* y += bit << 1 */
|
||||
}
|
||||
ODD_DOUBLE;
|
||||
}
|
||||
x->fp_mant[0] = q;
|
||||
#undef t0
|
||||
|
||||
/* calculate q1. note (y0&1)==0. */
|
||||
#define t0 y0
|
||||
#define t1 tt
|
||||
q = 0;
|
||||
y1 = 0;
|
||||
bit = 1 << 31;
|
||||
EVEN_DOUBLE;
|
||||
t1 = bit;
|
||||
FPU_SUBS(d1, x1, t1);
|
||||
FPU_SUBC(d0, x0, t0); /* d = x - t */
|
||||
if ((int)d0 >= 0) { /* if d >= 0 (i.e., x >= t) then */
|
||||
x0 = d0, x1 = d1; /* x -= t */
|
||||
q = bit; /* q += bit */
|
||||
y0 |= 1; /* y += bit << 1 */
|
||||
}
|
||||
ODD_DOUBLE;
|
||||
while ((bit >>= 1) != 0) { /* for remaining bits in q1 */
|
||||
EVEN_DOUBLE; /* as before */
|
||||
t1 = y1 | bit;
|
||||
FPU_SUBS(d1, x1, t1);
|
||||
FPU_SUBC(d0, x0, t0);
|
||||
if ((int)d0 >= 0) {
|
||||
x0 = d0, x1 = d1;
|
||||
q |= bit;
|
||||
y1 |= bit << 1;
|
||||
}
|
||||
ODD_DOUBLE;
|
||||
}
|
||||
x->fp_mant[1] = q;
|
||||
#undef t1
|
||||
|
||||
/* calculate q2. note (y1&1)==0; y0 (aka t0) is fixed. */
|
||||
#define t1 y1
|
||||
#define t2 tt
|
||||
q = 0;
|
||||
y2 = 0;
|
||||
bit = 1 << 31;
|
||||
EVEN_DOUBLE;
|
||||
t2 = bit;
|
||||
FPU_SUBS(d2, x2, t2);
|
||||
FPU_SUBCS(d1, x1, t1);
|
||||
FPU_SUBC(d0, x0, t0);
|
||||
if ((int)d0 >= 0) {
|
||||
x0 = d0, x1 = d1, x2 = d2;
|
||||
q = bit;
|
||||
y1 |= 1; /* now t1, y1 are set in concrete */
|
||||
}
|
||||
ODD_DOUBLE;
|
||||
while ((bit >>= 1) != 0) {
|
||||
EVEN_DOUBLE;
|
||||
t2 = y2 | bit;
|
||||
FPU_SUBS(d2, x2, t2);
|
||||
FPU_SUBCS(d1, x1, t1);
|
||||
FPU_SUBC(d0, x0, t0);
|
||||
if ((int)d0 >= 0) {
|
||||
x0 = d0, x1 = d1, x2 = d2;
|
||||
q |= bit;
|
||||
y2 |= bit << 1;
|
||||
}
|
||||
ODD_DOUBLE;
|
||||
}
|
||||
x->fp_mant[2] = q;
|
||||
#undef t2
|
||||
|
||||
/* calculate q3. y0, t0, y1, t1 all fixed; y2, t2, almost done. */
|
||||
#define t2 y2
|
||||
#define t3 tt
|
||||
q = 0;
|
||||
y3 = 0;
|
||||
bit = 1 << 31;
|
||||
EVEN_DOUBLE;
|
||||
t3 = bit;
|
||||
FPU_SUBS(d3, x3, t3);
|
||||
FPU_SUBCS(d2, x2, t2);
|
||||
FPU_SUBCS(d1, x1, t1);
|
||||
FPU_SUBC(d0, x0, t0);
|
||||
if ((int)d0 >= 0) {
|
||||
x0 = d0, x1 = d1, x2 = d2; x3 = d3;
|
||||
q = bit;
|
||||
y2 |= 1;
|
||||
}
|
||||
ODD_DOUBLE;
|
||||
while ((bit >>= 1) != 0) {
|
||||
EVEN_DOUBLE;
|
||||
t3 = y3 | bit;
|
||||
FPU_SUBS(d3, x3, t3);
|
||||
FPU_SUBCS(d2, x2, t2);
|
||||
FPU_SUBCS(d1, x1, t1);
|
||||
FPU_SUBC(d0, x0, t0);
|
||||
if ((int)d0 >= 0) {
|
||||
x0 = d0, x1 = d1, x2 = d2; x3 = d3;
|
||||
q |= bit;
|
||||
y3 |= bit << 1;
|
||||
}
|
||||
ODD_DOUBLE;
|
||||
}
|
||||
x->fp_mant[3] = q;
|
||||
|
||||
/*
|
||||
* The result, which includes guard and round bits, is exact iff
|
||||
* x is now zero; any nonzero bits in x represent sticky bits.
|
||||
*/
|
||||
x->fp_sticky = x0 | x1 | x2 | x3;
|
||||
return (x);
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fpu_subr.c 8.1 (Berkeley) 6/11/93
|
||||
* $NetBSD: fpu_subr.c,v 1.3 1996/03/14 19:42:01 christos Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* FPU subroutines.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "fsr.h"
|
||||
#include "instr.h"
|
||||
|
||||
#include "fpu_arith.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
/*
|
||||
* Shift the given number right rsh bits. Any bits that `fall off' will get
|
||||
* shoved into the sticky field; we return the resulting sticky. Note that
|
||||
* shifting NaNs is legal (this will never shift all bits out); a NaN's
|
||||
* sticky field is ignored anyway.
|
||||
*/
|
||||
int
|
||||
__fpu_shr(struct fpn *fp, int rsh)
|
||||
{
|
||||
uint32_t m0, m1, m2, m3, s;
|
||||
int lsh;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (rsh <= 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp)))
|
||||
__utrap_panic("fpu_rightshift 1");
|
||||
#endif
|
||||
|
||||
m0 = fp->fp_mant[0];
|
||||
m1 = fp->fp_mant[1];
|
||||
m2 = fp->fp_mant[2];
|
||||
m3 = fp->fp_mant[3];
|
||||
|
||||
/* If shifting all the bits out, take a shortcut. */
|
||||
if (rsh >= FP_NMANT) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((m0 | m1 | m2 | m3) == 0)
|
||||
__utrap_panic("fpu_rightshift 2");
|
||||
#endif
|
||||
fp->fp_mant[0] = 0;
|
||||
fp->fp_mant[1] = 0;
|
||||
fp->fp_mant[2] = 0;
|
||||
fp->fp_mant[3] = 0;
|
||||
#ifdef notdef
|
||||
if ((m0 | m1 | m2 | m3) == 0)
|
||||
fp->fp_class = FPC_ZERO;
|
||||
else
|
||||
#endif
|
||||
fp->fp_sticky = 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Squish out full words. */
|
||||
s = fp->fp_sticky;
|
||||
if (rsh >= 32 * 3) {
|
||||
s |= m3 | m2 | m1;
|
||||
m3 = m0, m2 = 0, m1 = 0, m0 = 0;
|
||||
} else if (rsh >= 32 * 2) {
|
||||
s |= m3 | m2;
|
||||
m3 = m1, m2 = m0, m1 = 0, m0 = 0;
|
||||
} else if (rsh >= 32) {
|
||||
s |= m3;
|
||||
m3 = m2, m2 = m1, m1 = m0, m0 = 0;
|
||||
}
|
||||
|
||||
/* Handle any remaining partial word. */
|
||||
if ((rsh &= 31) != 0) {
|
||||
lsh = 32 - rsh;
|
||||
s |= m3 << lsh;
|
||||
m3 = (m3 >> rsh) | (m2 << lsh);
|
||||
m2 = (m2 >> rsh) | (m1 << lsh);
|
||||
m1 = (m1 >> rsh) | (m0 << lsh);
|
||||
m0 >>= rsh;
|
||||
}
|
||||
fp->fp_mant[0] = m0;
|
||||
fp->fp_mant[1] = m1;
|
||||
fp->fp_mant[2] = m2;
|
||||
fp->fp_mant[3] = m3;
|
||||
fp->fp_sticky = s;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Force a number to be normal, i.e., make its fraction have all zero
|
||||
* bits before FP_1, then FP_1, then all 1 bits. This is used for denorms
|
||||
* and (sometimes) for intermediate results.
|
||||
*
|
||||
* Internally, this may use a `supernormal' -- a number whose fp_mant
|
||||
* is greater than or equal to 2.0 -- so as a side effect you can hand it
|
||||
* a supernormal and it will fix it (provided fp->fp_mant[3] == 0).
|
||||
*/
|
||||
void
|
||||
__fpu_norm(struct fpn *fp)
|
||||
{
|
||||
uint32_t m0, m1, m2, m3, top, sup, nrm;
|
||||
int lsh, rsh, exp;
|
||||
|
||||
exp = fp->fp_exp;
|
||||
m0 = fp->fp_mant[0];
|
||||
m1 = fp->fp_mant[1];
|
||||
m2 = fp->fp_mant[2];
|
||||
m3 = fp->fp_mant[3];
|
||||
|
||||
/* Handle severe subnormals with 32-bit moves. */
|
||||
if (m0 == 0) {
|
||||
if (m1)
|
||||
m0 = m1, m1 = m2, m2 = m3, m3 = 0, exp -= 32;
|
||||
else if (m2)
|
||||
m0 = m2, m1 = m3, m2 = 0, m3 = 0, exp -= 2 * 32;
|
||||
else if (m3)
|
||||
m0 = m3, m1 = 0, m2 = 0, m3 = 0, exp -= 3 * 32;
|
||||
else {
|
||||
fp->fp_class = FPC_ZERO;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now fix any supernormal or remaining subnormal. */
|
||||
nrm = FP_1;
|
||||
sup = nrm << 1;
|
||||
if (m0 >= sup) {
|
||||
/*
|
||||
* We have a supernormal number. We need to shift it right.
|
||||
* We may assume m3==0.
|
||||
*/
|
||||
for (rsh = 1, top = m0 >> 1; top >= sup; rsh++) /* XXX slow */
|
||||
top >>= 1;
|
||||
exp += rsh;
|
||||
lsh = 32 - rsh;
|
||||
m3 = m2 << lsh;
|
||||
m2 = (m2 >> rsh) | (m1 << lsh);
|
||||
m1 = (m1 >> rsh) | (m0 << lsh);
|
||||
m0 = top;
|
||||
} else if (m0 < nrm) {
|
||||
/*
|
||||
* We have a regular denorm (a subnormal number), and need
|
||||
* to shift it left.
|
||||
*/
|
||||
for (lsh = 1, top = m0 << 1; top < nrm; lsh++) /* XXX slow */
|
||||
top <<= 1;
|
||||
exp -= lsh;
|
||||
rsh = 32 - lsh;
|
||||
m0 = top | (m1 >> rsh);
|
||||
m1 = (m1 << lsh) | (m2 >> rsh);
|
||||
m2 = (m2 << lsh) | (m3 >> rsh);
|
||||
m3 <<= lsh;
|
||||
}
|
||||
|
||||
fp->fp_exp = exp;
|
||||
fp->fp_mant[0] = m0;
|
||||
fp->fp_mant[1] = m1;
|
||||
fp->fp_mant[2] = m2;
|
||||
fp->fp_mant[3] = m3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Concoct a `fresh' Quiet NaN per Appendix N.
|
||||
* As a side effect, we set NV (invalid) for the current exceptions.
|
||||
*/
|
||||
struct fpn *
|
||||
__fpu_newnan(struct fpemu *fe)
|
||||
{
|
||||
struct fpn *fp;
|
||||
|
||||
fe->fe_cx = FSR_NV;
|
||||
fp = &fe->fe_f3;
|
||||
fp->fp_class = FPC_QNAN;
|
||||
fp->fp_sign = 0;
|
||||
fp->fp_mant[0] = FP_1 - 1;
|
||||
fp->fp_mant[1] = fp->fp_mant[2] = fp->fp_mant[3] = ~0;
|
||||
return (fp);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright 2001 by Thomas Moestl <[email protected]>. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/sys/sparc64/include/fsr.h 326262 2017-11-27 15:10:39Z pfg $
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_FSR_H_
|
||||
#define _MACHINE_FSR_H_
|
||||
|
||||
#define FPRS_DL (1 << 0)
|
||||
#define FPRS_DU (1 << 1)
|
||||
#define FPRS_FEF (1 << 2)
|
||||
|
||||
#define VIS_BLOCKSIZE 64
|
||||
|
||||
#ifndef LOCORE
|
||||
|
||||
#define FSR_EXC_BITS 5
|
||||
#define FSR_EXC_MASK ((1UL << FSR_EXC_BITS) - 1)
|
||||
#define FSR_CEXC_SHIFT 0
|
||||
#define FSR_CEXC_MASK (FSR_EXC_MASK << FSR_CEXC_SHIFT)
|
||||
#define FSR_CEXC(b) ((unsigned long)(b) << FSR_CEXC_SHIFT)
|
||||
#define FSR_GET_CEXC(x) (((x) & FSR_CEXC_MASK) >> FSR_CEXC_SHIFT)
|
||||
#define FSR_AEXC_SHIFT 5
|
||||
#define FSR_AEXC_MASK (FSR_EXC_MASK << FSR_AEXC_SHIFT)
|
||||
#define FSR_AEXC(b) ((unsigned long)(b) << FSR_AEXC_SHIFT)
|
||||
#define FSR_GET_AEXC(x) (((x) & FSR_AEXC_MASK) >> FSR_AEXC_SHIFT)
|
||||
#define FSR_QNE (1UL << 13)
|
||||
#define FSR_NS (1UL << 22)
|
||||
#define FSR_TEM_SHIFT 23
|
||||
#define FSR_TEM_MASK (FSR_EXC_MASK << FSR_TEM_SHIFT)
|
||||
#define FSR_TEM(b) ((unsigned long)(b) << FSR_TEM_SHIFT)
|
||||
#define FSR_GET_TEM(x) (((x) & FSR_TEM_MASK) >> FSR_TEM_SHIFT)
|
||||
#define FSR_FCC0_SHIFT 10
|
||||
#define FSR_FCC0_BITS 2
|
||||
#define FSR_FCC0_MASK (((1UL << FSR_FCC0_BITS) - 1) << FSR_FCC0_SHIFT)
|
||||
#define FSR_FCC0(x) ((unsigned long)(x) << FSR_FCC0_SHIFT)
|
||||
#define FSR_GET_FCC0(x) (((x) & FSR_FCC0_MASK) >> FSR_FCC0_SHIFT)
|
||||
#define FSR_FTT_SHIFT 14
|
||||
#define FSR_FTT_BITS 3
|
||||
#define FSR_FTT_MASK (((1UL << FSR_FTT_BITS) - 1) << FSR_FTT_SHIFT)
|
||||
#define FSR_FTT(x) ((unsigned long)(x) << FSR_FTT_SHIFT)
|
||||
#define FSR_GET_FTT(x) (((x) & FSR_FTT_MASK) >> FSR_FTT_SHIFT)
|
||||
#define FSR_VER_SHIFT 17
|
||||
#define FSR_GET_VER(x) (((x) >> FSR_VER_SHIFT) & 7)
|
||||
#define FSR_RD_SHIFT 30
|
||||
#define FSR_RD_BITS 2
|
||||
#define FSR_RD_MASK (((1UL << FSR_RD_BITS) - 1) << FSR_RD_SHIFT)
|
||||
#define FSR_RD(x) ((unsigned long)(x) << FSR_RD_SHIFT)
|
||||
#define FSR_GET_RD(x) (((x) & FSR_RD_MASK) >> FSR_RD_SHIFT)
|
||||
#define FSR_FCC1_SHIFT 32
|
||||
#define FSR_FCC1_BITS 2
|
||||
#define FSR_FCC1_MASK (((1UL << FSR_FCC1_BITS) - 1) << FSR_FCC1_SHIFT)
|
||||
#define FSR_FCC1(x) ((unsigned long)(x) << FSR_FCC1_SHIFT)
|
||||
#define FSR_GET_FCC1(x) (((x) & FSR_FCC1_MASK) >> FSR_FCC1_SHIFT)
|
||||
#define FSR_FCC2_SHIFT 34
|
||||
#define FSR_FCC2_BITS 2
|
||||
#define FSR_FCC2_MASK (((1UL << FSR_FCC2_BITS) - 1) << FSR_FCC2_SHIFT)
|
||||
#define FSR_FCC2(x) ((unsigned long)(x) << FSR_FCC2_SHIFT)
|
||||
#define FSR_GET_FCC2(x) (((x) & FSR_FCC2_MASK) >> FSR_FCC2_SHIFT)
|
||||
#define FSR_FCC3_SHIFT 36
|
||||
#define FSR_FCC3_BITS 2
|
||||
#define FSR_FCC3_MASK (((1UL << FSR_FCC3_BITS) - 1) << FSR_FCC3_SHIFT)
|
||||
#define FSR_FCC3(x) ((unsigned long)(x) << FSR_FCC3_SHIFT)
|
||||
#define FSR_GET_FCC3(x) (((x) & FSR_FCC3_MASK) >> FSR_FCC3_SHIFT)
|
||||
|
||||
/* CEXC/AEXC/TEM exception values */
|
||||
#define FSR_NX (1 << 0)
|
||||
#define FSR_DZ (1 << 1)
|
||||
#define FSR_UF (1 << 2)
|
||||
#define FSR_OF (1 << 3)
|
||||
#define FSR_NV (1 << 4)
|
||||
/* FTT values. */
|
||||
#define FSR_FTT_NONE 0
|
||||
#define FSR_FTT_IEEE 1
|
||||
#define FSR_FTT_UNFIN 2
|
||||
#define FSR_FTT_UNIMP 3
|
||||
#define FSR_FTT_SEQERR 4
|
||||
#define FSR_FTT_HWERR 5
|
||||
#define FSR_FTT_INVREG 6
|
||||
/* RD values */
|
||||
#define FSR_RD_N 0 /* nearest */
|
||||
#define FSR_RD_Z 1 /* zero */
|
||||
#define FSR_RD_PINF 2 /* +infinity */
|
||||
#define FSR_RD_NINF 3 /* -infinity */
|
||||
/* condition codes */
|
||||
#define FSR_CC_EQ 0 /* a = b */
|
||||
#define FSR_CC_LT 1 /* a < b */
|
||||
#define FSR_CC_GT 2 /* a > b */
|
||||
#define FSR_CC_UO 3 /* unordered */
|
||||
|
||||
#endif /* !LOCORE */
|
||||
|
||||
#endif /* !_MACHINE_FSR_H_ */
|
||||
@@ -0,0 +1,139 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ieee.h 8.1 (Berkeley) 6/11/93
|
||||
* from: NetBSD: ieee.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp
|
||||
* $FreeBSD: head/sys/sparc64/include/ieee.h 139825 2005-01-07 02:29:27Z imp $
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_IEEE_H_
|
||||
#define _MACHINE_IEEE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* ieee.h defines the machine-dependent layout of the machine's IEEE
|
||||
* floating point. It does *not* define (yet?) any of the rounding
|
||||
* mode bits, exceptions, and so forth.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define the number of bits in each fraction and exponent.
|
||||
*
|
||||
* k k+1
|
||||
* Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
|
||||
*
|
||||
* (-exp_bias+1)
|
||||
* as fractions that look like 0.fffff x 2 . This means that
|
||||
*
|
||||
* -126
|
||||
* the number 0.10000 x 2 , for instance, is the same as the normalized
|
||||
*
|
||||
* -127 -128
|
||||
* float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
|
||||
*
|
||||
* -129
|
||||
* in the fraction; to represent 2 , we need two, and so on. This
|
||||
*
|
||||
* (-exp_bias-fracbits+1)
|
||||
* implies that the smallest denormalized number is 2
|
||||
*
|
||||
* for whichever format we are talking about: for single precision, for
|
||||
*
|
||||
* -126 -149
|
||||
* instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
|
||||
*
|
||||
* -149 == -127 - 23 + 1.
|
||||
*/
|
||||
#define SNG_EXPBITS 8
|
||||
#define SNG_FRACBITS 23
|
||||
|
||||
#define DBL_EXPBITS 11
|
||||
#define DBL_FRACBITS 52
|
||||
|
||||
#ifdef notyet
|
||||
#define E80_EXPBITS 15
|
||||
#define E80_FRACBITS 64
|
||||
#endif
|
||||
|
||||
#define EXT_EXPBITS 15
|
||||
#define EXT_FRACBITS 112
|
||||
|
||||
struct ieee_single {
|
||||
uint32_t sng_sign:1;
|
||||
uint32_t sng_exp:8;
|
||||
uint32_t sng_frac:23;
|
||||
};
|
||||
|
||||
struct ieee_double {
|
||||
uint32_t dbl_sign:1;
|
||||
uint32_t dbl_exp:11;
|
||||
uint32_t dbl_frach:20;
|
||||
uint32_t dbl_fracl;
|
||||
};
|
||||
|
||||
struct ieee_ext {
|
||||
uint32_t ext_sign:1;
|
||||
uint32_t ext_exp:15;
|
||||
uint32_t ext_frach:16;
|
||||
uint32_t ext_frachm;
|
||||
uint32_t ext_fraclm;
|
||||
uint32_t ext_fracl;
|
||||
};
|
||||
|
||||
/*
|
||||
* Floats whose exponent is in [1..INFNAN) (of whatever type) are
|
||||
* `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
|
||||
* Floats whose exponent is zero are either zero (iff all fraction
|
||||
* bits are zero) or subnormal values.
|
||||
*
|
||||
* A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
|
||||
* high fraction; if the bit is set, it is a `quiet NaN'.
|
||||
*/
|
||||
#define SNG_EXP_INFNAN 255
|
||||
#define DBL_EXP_INFNAN 2047
|
||||
#define EXT_EXP_INFNAN 32767
|
||||
|
||||
#if 0
|
||||
#define SNG_QUIETNAN (1 << 22)
|
||||
#define DBL_QUIETNAN (1 << 19)
|
||||
#define EXT_QUIETNAN (1 << 15)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exponent biases.
|
||||
*/
|
||||
#define SNG_EXP_BIAS 127
|
||||
#define DBL_EXP_BIAS 1023
|
||||
#define EXT_EXP_BIAS 16383
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,620 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-4-Clause
|
||||
*
|
||||
* Copyright (c) 1994 David S. Miller, [email protected]
|
||||
* Copyright (c) 1995 Paul Kranenburg
|
||||
* Copyright (c) 2001 Thomas Moestl <[email protected]>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by David Miller.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* from: NetBSD: db_disasm.c,v 1.9 2000/08/16 11:29:42 pk Exp
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_INSTR_H_
|
||||
#define _MACHINE_INSTR_H_
|
||||
|
||||
/*
|
||||
* Definitions for all instruction formats
|
||||
*/
|
||||
#define IF_OP_SHIFT 30
|
||||
#define IF_OP_BITS 2
|
||||
#define IF_IMM_SHIFT 0 /* Immediate/Displacement */
|
||||
|
||||
/*
|
||||
* Definitions for format 2
|
||||
*/
|
||||
#define IF_F2_RD_SHIFT 25
|
||||
#define IF_F2_RD_BITS 5
|
||||
#define IF_F2_A_SHIFT 29
|
||||
#define IF_F2_A_BITS 1
|
||||
#define IF_F2_COND_SHIFT 25
|
||||
#define IF_F2_COND_BITS 4
|
||||
#define IF_F2_RCOND_SHIFT 25
|
||||
#define IF_F2_RCOND_BITS 3
|
||||
#define IF_F2_OP2_SHIFT 22
|
||||
#define IF_F2_OP2_BITS 3
|
||||
#define IF_F2_CC1_SHIFT 21
|
||||
#define IF_F2_CC1_BITS 1
|
||||
#define IF_F2_CC0_SHIFT 20
|
||||
#define IF_F2_CC0_BITS 1
|
||||
#define IF_F2_CC_SHIFT 20 /* CC0 and CC1 combined. */
|
||||
#define IF_F2_CC_BITS 2
|
||||
#define IF_F2_D16HI_SHIFT 20
|
||||
#define IF_F2_D16HI_BITS 2
|
||||
#define IF_F2_P_SHIFT 19
|
||||
#define IF_F2_P_BITS 1
|
||||
#define IF_F2_RS1_SHIFT 14
|
||||
#define IF_F2_RS1_BITS 5
|
||||
|
||||
/*
|
||||
* Definitions for format 3
|
||||
*/
|
||||
#define IF_F3_OP3_SHIFT 19
|
||||
#define IF_F3_OP3_BITS 6
|
||||
#define IF_F3_RD_SHIFT IF_F2_RD_SHIFT
|
||||
#define IF_F3_RD_BITS IF_F2_RD_BITS
|
||||
#define IF_F3_FCN_SHIFT 25
|
||||
#define IF_F3_FCN_BITS 5
|
||||
#define IF_F3_CC1_SHIFT 26
|
||||
#define IF_F3_CC1_BITS 1
|
||||
#define IF_F3_CC0_SHIFT 25
|
||||
#define IF_F3_CC0_BITS 1
|
||||
#define IF_F3_CC_SHIFT 25 /* CC0 and CC1 combined. */
|
||||
#define IF_F3_CC_BITS 2
|
||||
#define IF_F3_RS1_SHIFT IF_F2_RS1_SHIFT
|
||||
#define IF_F3_RS1_BITS IF_F2_RS1_BITS
|
||||
#define IF_F3_I_SHIFT 13
|
||||
#define IF_F3_I_BITS 1
|
||||
#define IF_F3_X_SHIFT 12
|
||||
#define IF_F3_X_BITS 1
|
||||
#define IF_F3_RCOND_SHIFT 10
|
||||
#define IF_F3_RCOND_BITS 3
|
||||
#define IF_F3_IMM_ASI_SHIFT 5
|
||||
#define IF_F3_IMM_ASI_BITS 8
|
||||
#define IF_F3_OPF_SHIFT 5
|
||||
#define IF_F3_OPF_BITS 9
|
||||
#define IF_F3_CMASK_SHIFT 4
|
||||
#define IF_F3_CMASK_BITS 3
|
||||
#define IF_F3_RS2_SHIFT 0
|
||||
#define IF_F3_RS2_BITS 5
|
||||
#define IF_F3_SHCNT32_SHIFT 0
|
||||
#define IF_F3_SHCNT32_BITS 5
|
||||
#define IF_F3_SHCNT64_SHIFT 0
|
||||
#define IF_F3_SHCNT64_BITS 6
|
||||
|
||||
/*
|
||||
* Definitions for format 4
|
||||
*/
|
||||
#define IF_F4_OP3_SHIFT IF_F3_OP3_SHIFT
|
||||
#define IF_F4_OP3_BITS IF_F3_OP3_BITS
|
||||
#define IF_F4_RD_SHIFT IF_F2_RD_SHIFT
|
||||
#define IF_F4_RD_BITS IF_F2_RD_BITS
|
||||
#define IF_F4_RS1_SHIFT IF_F2_RS1_SHIFT
|
||||
#define IF_F4_RS1_BITS IF_F2_RS1_BITS
|
||||
#define IF_F4_TCOND_SHIFT IF_F2_COND_SHIFT /* cond for Tcc */
|
||||
#define IF_F4_TCOND_BITS IF_F2_COND_BITS
|
||||
#define IF_F4_CC2_SHIFT 18
|
||||
#define IF_F4_CC2_BITS 1
|
||||
#define IF_F4_COND_SHIFT 14
|
||||
#define IF_F4_COND_BITS 4
|
||||
#define IF_F4_I_SHIFT IF_F3_I_SHIFT
|
||||
#define IF_F4_I_BITS IF_F3_I_BITS
|
||||
#define IF_F4_OPF_CC_SHIFT 11
|
||||
#define IF_F4_OPF_CC_BITS 3
|
||||
#define IF_F4_CC1_SHIFT 12
|
||||
#define IF_F4_CC1_BITS 1
|
||||
#define IF_F4_CC0_SHIFT 11
|
||||
#define IF_F4_CC0_BITS 1
|
||||
#define IF_F4_RCOND_SHIFT IF_F3_RCOND_SHIFT
|
||||
#define IF_F4_RCOND_BITS IF_F3_RCOND_BITS
|
||||
#define IF_F4_OPF_LOW_SHIFT 5
|
||||
#define IF_F4_RS2_SHIFT IF_F3_RS2_SHIFT
|
||||
#define IF_F4_RS2_BITS IF_F3_RS2_BITS
|
||||
#define IF_F4_SW_TRAP_SHIFT 0
|
||||
#define IF_F4_SW_TRAP_BITS 7
|
||||
|
||||
/*
|
||||
* Macros to decode instructions
|
||||
*/
|
||||
/* Extract a field */
|
||||
#define IF_MASK(s, w) (((1 << (w)) - 1) << (s))
|
||||
#define IF_EXTRACT(x, s, w) (((x) & IF_MASK((s), (w))) >> (s))
|
||||
#define IF_DECODE(x, f) \
|
||||
IF_EXTRACT((x), IF_ ## f ## _SHIFT, IF_ ## f ## _BITS)
|
||||
|
||||
/* Sign-extend a field of width W */
|
||||
#define IF_SEXT(x, w) \
|
||||
(((x) & (1L << ((w) - 1))) != 0 ? \
|
||||
(-1L - ((x) ^ ((1L << (w)) - 1))) : (x))
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* The following C variant is from db_disassemble.c, and surely faster, but it
|
||||
* relies on behaviour that is undefined by the C standard (>> in conjunction
|
||||
* with signed negative arguments).
|
||||
*/
|
||||
#define IF_SEXT(v, w) ((((long long)(v)) << (64 - w)) >> (64 - w))
|
||||
/* Assembler version of the above */
|
||||
#define IF_SEXT(v, w) \
|
||||
{ u_long t; ( __asm __volatile("sllx %1, %2, %0; srax %0, %2, %0" :
|
||||
"=r" (t) : "r" (v) : "i" (64 - w)); t)}
|
||||
#endif
|
||||
|
||||
/* All instruction formats */
|
||||
#define IF_OP(i) IF_DECODE(i, OP)
|
||||
|
||||
/* Instruction format 2 */
|
||||
#define IF_F2_RD(i) IF_DECODE((i), F2_RD)
|
||||
#define IF_F2_A(i) IF_DECODE((i), F2_A)
|
||||
#define IF_F2_COND(i) IF_DECODE((i), F2_COND)
|
||||
#define IF_F2_RCOND(i) IF_DECODE((i), F2_RCOND)
|
||||
#define IF_F2_OP2(i) IF_DECODE((i), F2_OP2)
|
||||
#define IF_F2_CC1(i) IF_DECODE((i), F2_CC1)
|
||||
#define IF_F2_CC0(i) IF_DECODE((i), F2_CC0)
|
||||
#define IF_F2_CC(i) IF_DECODE((i), F2_CC)
|
||||
#define IF_F2_D16HI(i) IF_DECODE((i), F2_D16HI)
|
||||
#define IF_F2_P(i) IF_DECODE((i), F2_P)
|
||||
#define IF_F2_RS1(i) IF_DECODE((i), F2_RS1)
|
||||
|
||||
/* Instruction format 3 */
|
||||
#define IF_F3_OP3(i) IF_DECODE((i), F3_OP3)
|
||||
#define IF_F3_RD(i) IF_F2_RD((i))
|
||||
#define IF_F3_FCN(i) IF_DECODE((i), F3_FCN)
|
||||
#define IF_F3_CC1(i) IF_DECODE((i), F3_CC1)
|
||||
#define IF_F3_CC0(i) IF_DECODE((i), F3_CC0)
|
||||
#define IF_F3_CC(i) IF_DECODE((i), F3_CC)
|
||||
#define IF_F3_RS1(i) IF_F2_RS1((i))
|
||||
#define IF_F3_I(i) IF_DECODE((i), F3_I)
|
||||
#define IF_F3_X(i) IF_DECODE((i), F3_X)
|
||||
#define IF_F3_RCOND(i) IF_DECODE((i), F3_RCOND)
|
||||
#define IF_F3_IMM_ASI(i) IF_DECODE((i), F3_IMM_ASI)
|
||||
#define IF_F3_OPF(i) IF_DECODE((i), F3_OPF)
|
||||
#define IF_F3_CMASK(i) IF_DECODE((i), F3_CMASK)
|
||||
#define IF_F3_RS2(i) IF_DECODE((i), F3_RS2)
|
||||
#define IF_F3_SHCNT32(i) IF_DECODE((i), F3_SHCNT32)
|
||||
#define IF_F3_SHCNT64(i) IF_DECODE((i), F3_SHCNT64)
|
||||
|
||||
/* Instruction format 4 */
|
||||
#define IF_F4_OP3(i) IF_F3_OP3((i))
|
||||
#define IF_F4_RD(i) IF_F3_RD((i))
|
||||
#define IF_F4_TCOND(i) IF_DECODE((i), F4_TCOND)
|
||||
#define IF_F4_RS1(i) IF_F3_RS1((i))
|
||||
#define IF_F4_CC2(i) IF_DECODE((i), F4_CC2)
|
||||
#define IF_F4_COND(i) IF_DECODE((i), F4_COND)
|
||||
#define IF_F4_I(i) IF_F3_I((i))
|
||||
#define IF_F4_OPF_CC(i) IF_DECODE((i), F4_OPF_CC)
|
||||
#define IF_F4_RCOND(i) IF_F3_RCOND((i))
|
||||
#define IF_F4_OPF_LOW(i, w) IF_EXTRACT((i), IF_F4_OPF_LOW_SHIFT, (w))
|
||||
#define IF_F4_RS2(i) IF_F3_RS2((i))
|
||||
#define IF_F4_SW_TRAP(i) IF_DECODE((i), F4_SW_TRAP)
|
||||
|
||||
/* Extract an immediate from an instruction, with an without sign extension */
|
||||
#define IF_IMM(i, w) IF_EXTRACT((i), IF_IMM_SHIFT, (w))
|
||||
#define IF_SIMM(i, w) ({ u_long b = (w), x = IF_IMM((i), b); IF_SEXT((x), b); })
|
||||
|
||||
/*
|
||||
* Macros to encode instructions
|
||||
*/
|
||||
#define IF_INSERT(x, s, w) (((x) & ((1 << (w)) - 1)) << (s))
|
||||
#define IF_ENCODE(x, f) \
|
||||
IF_INSERT((x), IF_ ## f ## _SHIFT, IF_ ## f ## _BITS)
|
||||
|
||||
/* All instruction formats */
|
||||
#define EIF_OP(x) IF_ENCODE((x), OP)
|
||||
|
||||
/* Instruction format 2 */
|
||||
#define EIF_F2_RD(x) IF_ENCODE((x), F2_RD)
|
||||
#define EIF_F2_A(x) IF_ENCODE((x), F2_A)
|
||||
#define EIF_F2_COND(x) IF_ENCODE((x), F2_COND)
|
||||
#define EIF_F2_RCOND(x) IF_ENCODE((x), F2_RCOND)
|
||||
#define EIF_F2_OP2(x) IF_ENCODE((x), F2_OP2)
|
||||
#define EIF_F2_CC1(x) IF_ENCODE((x), F2_CC1)
|
||||
#define EIF_F2_CC0(x) IF_ENCODE((x), F2_CC0)
|
||||
#define EIF_F2_D16HI(x) IF_ENCODE((x), F2_D16HI)
|
||||
#define EIF_F2_P(x) IF_ENCODE((x), F2_P)
|
||||
#define EIF_F2_RS1(x) IF_ENCODE((x), F2_RS1)
|
||||
|
||||
/* Instruction format 3 */
|
||||
#define EIF_F3_OP3(x) IF_ENCODE((x), F3_OP3)
|
||||
#define EIF_F3_RD(x) EIF_F2_RD((x))
|
||||
#define EIF_F3_FCN(x) IF_ENCODE((x), F3_FCN)
|
||||
#define EIF_F3_CC1(x) IF_ENCODE((x), F3_CC1)
|
||||
#define EIF_F3_CC0(x) IF_ENCODE((x), F3_CC0)
|
||||
#define EIF_F3_RS1(x) EIF_F2_RS1((x))
|
||||
#define EIF_F3_I(x) IF_ENCODE((x), F3_I)
|
||||
#define EIF_F3_X(x) IF_ENCODE((x), F3_X)
|
||||
#define EIF_F3_RCOND(x) IF_ENCODE((x), F3_RCOND)
|
||||
#define EIF_F3_IMM_ASI(x) IF_ENCODE((x), F3_IMM_ASI)
|
||||
#define EIF_F3_OPF(x) IF_ENCODE((x), F3_OPF)
|
||||
#define EIF_F3_CMASK(x) IF_ENCODE((x), F3_CMASK)
|
||||
#define EIF_F3_RS2(x) IF_ENCODE((x), F3_RS2)
|
||||
#define EIF_F3_SHCNT32(x) IF_ENCODE((x), F3_SHCNT32)
|
||||
#define EIF_F3_SHCNT64(x) IF_ENCODE((x), F3_SHCNT64)
|
||||
|
||||
/* Instruction format 4 */
|
||||
#define EIF_F4_OP3(x) EIF_F3_OP3((x))
|
||||
#define EIF_F4_RD(x) EIF_F2_RD((x))
|
||||
#define EIF_F4_TCOND(x) IF_ENCODE((x), F4_TCOND)
|
||||
#define EIF_F4_RS1(x) EIF_F2_RS1((x))
|
||||
#define EIF_F4_CC2(x) IF_ENCODE((x), F4_CC2)
|
||||
#define EIF_F4_COND(x) IF_ENCODE((x), F4_COND)
|
||||
#define EIF_F4_I(x) EIF_F3_I((x))
|
||||
#define EIF_F4_OPF_CC(x) IF_ENCODE((x), F4_OPF_CC)
|
||||
#define EIF_F4_RCOND(x) EIF_F3_RCOND((x))
|
||||
#define EIF_F4_OPF_LOW(i, w) IF_INSERT((x), IF_F4_OPF_CC_SHIFT, (w))
|
||||
#define EIF_F4_RS2(x) EIF_F3_RS2((x))
|
||||
#define EIF_F4_SW_TRAP(x) IF_ENCODE((x), F4_SW_TRAP)
|
||||
|
||||
/* Immediates */
|
||||
#define EIF_IMM(x, w) IF_INSERT((x), IF_IMM_SHIFT, (w))
|
||||
#define EIF_SIMM(x, w) IF_EIMM((x), (w))
|
||||
|
||||
/*
|
||||
* OP field values (specifying the instruction format)
|
||||
*/
|
||||
#define IOP_FORM2 0x00 /* Format 2: sethi, branches */
|
||||
#define IOP_CALL 0x01 /* Format 1: call */
|
||||
#define IOP_MISC 0x02 /* Format 3 or 4: arith & misc */
|
||||
#define IOP_LDST 0x03 /* Format 4: loads and stores */
|
||||
|
||||
/*
|
||||
* OP2/OP3 values (specifying the actual instruction)
|
||||
*/
|
||||
/* OP2 values for format 2 (OP = 0) */
|
||||
#define INS0_ILLTRAP 0x00
|
||||
#define INS0_BPcc 0x01
|
||||
#define INS0_Bicc 0x02
|
||||
#define INS0_BPr 0x03
|
||||
#define INS0_SETHI 0x04 /* with rd = 0 and imm22 = 0, nop */
|
||||
#define INS0_FBPfcc 0x05
|
||||
#define INS0_FBfcc 0x06
|
||||
/* undefined 0x07 */
|
||||
|
||||
/* OP3 values for Format 3 and 4 (OP = 2) */
|
||||
#define INS2_ADD 0x00
|
||||
#define INS2_AND 0x01
|
||||
#define INS2_OR 0x02
|
||||
#define INS2_XOR 0x03
|
||||
#define INS2_SUB 0x04
|
||||
#define INS2_ANDN 0x05
|
||||
#define INS2_ORN 0x06
|
||||
#define INS2_XNOR 0x07
|
||||
#define INS2_ADDC 0x08
|
||||
#define INS2_MULX 0x09
|
||||
#define INS2_UMUL 0x0a
|
||||
#define INS2_SMUL 0x0b
|
||||
#define INS2_SUBC 0x0c
|
||||
#define INS2_UDIVX 0x0d
|
||||
#define INS2_UDIV 0x0e
|
||||
#define INS2_SDIV 0x0f
|
||||
#define INS2_ADDcc 0x10
|
||||
#define INS2_ANDcc 0x11
|
||||
#define INS2_ORcc 0x12
|
||||
#define INS2_XORcc 0x13
|
||||
#define INS2_SUBcc 0x14
|
||||
#define INS2_ANDNcc 0x15
|
||||
#define INS2_ORNcc 0x16
|
||||
#define INS2_XNORcc 0x17
|
||||
#define INS2_ADDCcc 0x18
|
||||
/* undefined 0x19 */
|
||||
#define INS2_UMULcc 0x1a
|
||||
#define INS2_SMULcc 0x1b
|
||||
#define INS2_SUBCcc 0x1c
|
||||
/* undefined 0x1d */
|
||||
#define INS2_UDIVcc 0x1e
|
||||
#define INS2_SDIVcc 0x1f
|
||||
#define INS2_TADDcc 0x20
|
||||
#define INS2_TSUBcc 0x21
|
||||
#define INS2_TADDccTV 0x22
|
||||
#define INS2_TSUBccTV 0x23
|
||||
#define INS2_MULScc 0x24
|
||||
#define INS2_SSL 0x25 /* SLLX when IF_X(i) == 1 */
|
||||
#define INS2_SRL 0x26 /* SRLX when IF_X(i) == 1 */
|
||||
#define INS2_SRA 0x27 /* SRAX when IF_X(i) == 1 */
|
||||
#define INS2_RD 0x28 /* and MEMBAR, STBAR */
|
||||
/* undefined 0x29 */
|
||||
#define INS2_RDPR 0x2a
|
||||
#define INS2_FLUSHW 0x2b
|
||||
#define INS2_MOVcc 0x2c
|
||||
#define INS2_SDIVX 0x2d
|
||||
#define INS2_POPC 0x2e /* undefined if IF_RS1(i) != 0 */
|
||||
#define INS2_MOVr 0x2f
|
||||
#define INS2_WR 0x30 /* and SIR */
|
||||
#define INS2_SV_RSTR 0x31 /* saved, restored */
|
||||
#define INS2_WRPR 0x32
|
||||
/* undefined 0x33 */
|
||||
#define INS2_FPop1 0x34 /* further encoded in opf field */
|
||||
#define INS2_FPop2 0x35 /* further encoded in opf field */
|
||||
#define INS2_IMPLDEP1 0x36
|
||||
#define INS2_IMPLDEP2 0x37
|
||||
#define INS2_JMPL 0x38
|
||||
#define INS2_RETURN 0x39
|
||||
#define INS2_Tcc 0x3a
|
||||
#define INS2_FLUSH 0x3b
|
||||
#define INS2_SAVE 0x3c
|
||||
#define INS2_RESTORE 0x3d
|
||||
#define INS2_DONE_RETR 0x3e /* done, retry */
|
||||
/* undefined 0x3f */
|
||||
|
||||
/* OP3 values for format 3 (OP = 3) */
|
||||
#define INS3_LDUW 0x00
|
||||
#define INS3_LDUB 0x01
|
||||
#define INS3_LDUH 0x02
|
||||
#define INS3_LDD 0x03
|
||||
#define INS3_STW 0x04
|
||||
#define INS3_STB 0x05
|
||||
#define INS3_STH 0x06
|
||||
#define INS3_STD 0x07
|
||||
#define INS3_LDSW 0x08
|
||||
#define INS3_LDSB 0x09
|
||||
#define INS3_LDSH 0x0a
|
||||
#define INS3_LDX 0x0b
|
||||
/* undefined 0x0c */
|
||||
#define INS3_LDSTUB 0x0d
|
||||
#define INS3_STX 0x0e
|
||||
#define INS3_SWAP 0x0f
|
||||
#define INS3_LDUWA 0x10
|
||||
#define INS3_LDUBA 0x11
|
||||
#define INS3_LDUHA 0x12
|
||||
#define INS3_LDDA 0x13
|
||||
#define INS3_STWA 0x14
|
||||
#define INS3_STBA 0x15
|
||||
#define INS3_STHA 0x16
|
||||
#define INS3_STDA 0x17
|
||||
#define INS3_LDSWA 0x18
|
||||
#define INS3_LDSBA 0x19
|
||||
#define INS3_LDSHA 0x1a
|
||||
#define INS3_LDXA 0x1b
|
||||
/* undefined 0x1c */
|
||||
#define INS3_LDSTUBA 0x1d
|
||||
#define INS3_STXA 0x1e
|
||||
#define INS3_SWAPA 0x1f
|
||||
#define INS3_LDF 0x20
|
||||
#define INS3_LDFSR 0x21 /* and LDXFSR */
|
||||
#define INS3_LDQF 0x22
|
||||
#define INS3_LDDF 0x23
|
||||
#define INS3_STF 0x24
|
||||
#define INS3_STFSR 0x25 /* and STXFSR */
|
||||
#define INS3_STQF 0x26
|
||||
#define INS3_STDF 0x27
|
||||
/* undefined 0x28 - 0x2c */
|
||||
#define INS3_PREFETCH 0x2d
|
||||
/* undefined 0x2e - 0x2f */
|
||||
#define INS3_LDFA 0x30
|
||||
/* undefined 0x31 */
|
||||
#define INS3_LDQFA 0x32
|
||||
#define INS3_LDDFA 0x33
|
||||
#define INS3_STFA 0x34
|
||||
/* undefined 0x35 */
|
||||
#define INS3_STQFA 0x36
|
||||
#define INS3_STDFA 0x37
|
||||
/* undefined 0x38 - 0x3b */
|
||||
#define INS3_CASA 0x39
|
||||
#define INS3_PREFETCHA 0x3a
|
||||
#define INS3_CASXA 0x3b
|
||||
|
||||
/*
|
||||
* OPF values (floating point instructions, IMPLDEP)
|
||||
*/
|
||||
/*
|
||||
* These values are or'ed to the FPop values to get the instructions.
|
||||
* They describe the operand type(s).
|
||||
*/
|
||||
#define INSFP_i 0x000 /* 32-bit int */
|
||||
#define INSFP_s 0x001 /* 32-bit single */
|
||||
#define INSFP_d 0x002 /* 64-bit double */
|
||||
#define INSFP_q 0x003 /* 128-bit quad */
|
||||
/* FPop1. The comments give the types for which this instruction is defined. */
|
||||
#define INSFP1_FMOV 0x000 /* s, d, q */
|
||||
#define INSFP1_FNEG 0x004 /* s, d, q */
|
||||
#define INSFP1_FABS 0x008 /* s, d, q */
|
||||
#define INSFP1_FSQRT 0x028 /* s, d, q */
|
||||
#define INSFP1_FADD 0x040 /* s, d, q */
|
||||
#define INSFP1_FSUB 0x044 /* s, d, q */
|
||||
#define INSFP1_FMUL 0x048 /* s, d, q */
|
||||
#define INSFP1_FDIV 0x04c /* s, d, q */
|
||||
#define INSFP1_FsMULd 0x068 /* s */
|
||||
#define INSFP1_FdMULq 0x06c /* d */
|
||||
#define INSFP1_FTOx 0x080 /* s, d, q */
|
||||
#define INSFP1_FxTOs 0x084 /* special: i only */
|
||||
#define INSFP1_FxTOd 0x088 /* special: i only */
|
||||
#define INSFP1_FxTOq 0x08c /* special: i only */
|
||||
#define INSFP1_FTOs 0x0c4 /* i, d, q */
|
||||
#define INSFP1_FTOd 0x0c8 /* i, s, q */
|
||||
#define INSFP1_FTOq 0x0cc /* i, s, d */
|
||||
#define INSFP1_FTOi 0x0d0 /* i, s, d */
|
||||
|
||||
/* FPop2 */
|
||||
#define INSFP2_FMOV_CCMUL 0x40
|
||||
#define INSFP2_FMOV_CCOFFS 0x00
|
||||
/* Use the IFCC_* constants for cc. Operand types: s, d, q */
|
||||
#define INSFP2_FMOV_CC(cc) ((cc) * INSFP2_FMOV_CCMUL + INSFP2_FMOV_CCOFFS)
|
||||
#define INSFP2_FMOV_RCMUL 0x20
|
||||
#define INSFP2_FMOV_RCOFFS 0x04
|
||||
/* Use the IRCOND_* constants for rc. Operand types: s, d, q */
|
||||
#define INSFP2_FMOV_RC(rc) ((rc) * INSFP2_FMOV_RCMUL + INSFP2_FMOV_RCOFFS)
|
||||
#define INSFP2_FCMP 0x050 /* s, d, q */
|
||||
#define INSFP2_FCMPE 0x054 /* s, d, q */
|
||||
|
||||
/* Decode 5-bit register field into 6-bit number (for doubles and quads). */
|
||||
#define INSFPdq_RN(rn) (((rn) & ~1) | (((rn) & 1) << 5))
|
||||
|
||||
/* IMPLDEP1 for Sun UltraSparc */
|
||||
#define IIDP1_EDGE8 0x00
|
||||
#define IIDP1_EDGE8N 0x01 /* US-III */
|
||||
#define IIDP1_EDGE8L 0x02
|
||||
#define IIDP1_EDGE8LN 0x03 /* US-III */
|
||||
#define IIDP1_EDGE16 0x04
|
||||
#define IIDP1_EDGE16N 0x05 /* US-III */
|
||||
#define IIDP1_EDGE16L 0x06
|
||||
#define IIDP1_EDGE16LN 0x07 /* US-III */
|
||||
#define IIDP1_EDGE32 0x08
|
||||
#define IIDP1_EDGE32N 0x09 /* US-III */
|
||||
#define IIDP1_EDGE32L 0x0a
|
||||
#define IIDP1_EDGE32LN 0x0b /* US-III */
|
||||
#define IIDP1_ARRAY8 0x10
|
||||
#define IIDP1_ARRAY16 0x12
|
||||
#define IIDP1_ARRAY32 0x14
|
||||
#define IIDP1_ALIGNADDRESS 0x18
|
||||
#define IIDP1_BMASK 0x19 /* US-III */
|
||||
#define IIDP1_ALIGNADDRESS_L 0x1a
|
||||
#define IIDP1_FCMPLE16 0x20
|
||||
#define IIDP1_FCMPNE16 0x22
|
||||
#define IIDP1_FCMPLE32 0x24
|
||||
#define IIDP1_FCMPNE32 0x26
|
||||
#define IIDP1_FCMPGT16 0x28
|
||||
#define IIDP1_FCMPEQ16 0x2a
|
||||
#define IIDP1_FCMPGT32 0x2c
|
||||
#define IIDP1_FCMPEQ32 0x2e
|
||||
#define IIDP1_FMUL8x16 0x31
|
||||
#define IIDP1_FMUL8x16AU 0x33
|
||||
#define IIDP1_FMUL8X16AL 0x35
|
||||
#define IIDP1_FMUL8SUx16 0x36
|
||||
#define IIDP1_FMUL8ULx16 0x37
|
||||
#define IIDP1_FMULD8SUx16 0x38
|
||||
#define IIDP1_FMULD8ULx16 0x39
|
||||
#define IIDP1_FPACK32 0x3a
|
||||
#define IIDP1_FPACK16 0x3b
|
||||
#define IIDP1_FPACKFIX 0x3d
|
||||
#define IIDP1_PDIST 0x3e
|
||||
#define IIDP1_FALIGNDATA 0x48
|
||||
#define IIDP1_FPMERGE 0x4b
|
||||
#define IIDP1_BSHUFFLE 0x4c /* US-III */
|
||||
#define IIDP1_FEXPAND 0x4d
|
||||
#define IIDP1_FPADD16 0x50
|
||||
#define IIDP1_FPADD16S 0x51
|
||||
#define IIDP1_FPADD32 0x52
|
||||
#define IIDP1_FPADD32S 0x53
|
||||
#define IIDP1_SUB16 0x54
|
||||
#define IIDP1_SUB16S 0x55
|
||||
#define IIDP1_SUB32 0x56
|
||||
#define IIDP1_SUB32S 0x57
|
||||
#define IIDP1_FZERO 0x60
|
||||
#define IIDP1_FZEROS 0x61
|
||||
#define IIDP1_FNOR 0x62
|
||||
#define IIDP1_FNORS 0x63
|
||||
#define IIDP1_FANDNOT2 0x64
|
||||
#define IIDP1_FANDNOT2S 0x65
|
||||
#define IIDP1_NOT2 0x66
|
||||
#define IIDP1_NOT2S 0x67
|
||||
#define IIDP1_FANDNOT1 0x68
|
||||
#define IIDP1_FANDNOT1S 0x69
|
||||
#define IIDP1_FNOT1 0x6a
|
||||
#define IIDP1_FNOT1S 0x6b
|
||||
#define IIDP1_FXOR 0x6c
|
||||
#define IIDP1_FXORS 0x6d
|
||||
#define IIDP1_FNAND 0x6e
|
||||
#define IIDP1_FNANDS 0x6f
|
||||
#define IIDP1_FAND 0x70
|
||||
#define IIDP1_FANDS 0x71
|
||||
#define IIDP1_FXNOR 0x72
|
||||
#define IIDP1_FXNORS 0x73
|
||||
#define IIDP1_FSRC1 0x74
|
||||
#define IIDP1_FSRC1S 0x75
|
||||
#define IIDP1_FORNOT2 0x76
|
||||
#define IIDP1_FORNOT2S 0x77
|
||||
#define IIDP1_FSRC2 0x78
|
||||
#define IIDP1_FSRC2S 0x79
|
||||
#define IIDP1_FORNOT1 0x7a
|
||||
#define IIDP1_FORNOT1S 0x7b
|
||||
#define IIDP1_FOR 0x7c
|
||||
#define IIDP1_FORS 0x7d
|
||||
#define IIDP1_FONE 0x7e
|
||||
#define IIDP1_FONES 0x7f
|
||||
#define IIDP1_SHUTDOWN 0x80
|
||||
#define IIDP1_SIAM 0x81 /* US-III */
|
||||
|
||||
/*
|
||||
* Instruction modifiers
|
||||
*/
|
||||
/* cond values for integer ccr's */
|
||||
#define IICOND_N 0x00
|
||||
#define IICOND_E 0x01
|
||||
#define IICOND_LE 0x02
|
||||
#define IICOND_L 0x03
|
||||
#define IICOND_LEU 0x04
|
||||
#define IICOND_CS 0x05
|
||||
#define IICOND_NEG 0x06
|
||||
#define IICOND_VS 0x07
|
||||
#define IICOND_A 0x08
|
||||
#define IICOND_NE 0x09
|
||||
#define IICOND_G 0x0a
|
||||
#define IICOND_GE 0x0b
|
||||
#define IICOND_GU 0x0c
|
||||
#define IICOND_CC 0x0d
|
||||
#define IICOND_POS 0x0e
|
||||
#define IICOND_VC 0x0f
|
||||
|
||||
/* cond values for fp ccr's */
|
||||
#define IFCOND_N 0x00
|
||||
#define IFCOND_NE 0x01
|
||||
#define IFCOND_LG 0x02
|
||||
#define IFCOND_UL 0x03
|
||||
#define IFCOND_L 0x04
|
||||
#define IFCOND_UG 0x05
|
||||
#define IFCOND_G 0x06
|
||||
#define IFCOND_U 0x07
|
||||
#define IFCOND_A 0x08
|
||||
#define IFCOND_E 0x09
|
||||
#define IFCOND_UE 0x0a
|
||||
#define IFCOND_GE 0x0b
|
||||
#define IFCOND_UGE 0x0c
|
||||
#define IFCOND_LE 0x0d
|
||||
#define IFCOND_ULE 0x0e
|
||||
#define IFCOND_O 0x0f
|
||||
|
||||
/* rcond values for BPr, MOVr, FMOVr */
|
||||
#define IRCOND_Z 0x01
|
||||
#define IRCOND_LEZ 0x02
|
||||
#define IRCOND_LZ 0x03
|
||||
#define IRCOND_NZ 0x05
|
||||
#define IRCOND_GZ 0x06
|
||||
#define IRCOND_GEZ 0x07
|
||||
|
||||
/* cc values for MOVcc and FMOVcc */
|
||||
#define IFCC_ICC 0x04
|
||||
#define IFCC_XCC 0x06
|
||||
/* if true, the lower 2 bits are the fcc number */
|
||||
#define IFCC_FCC(c) ((c) & 3)
|
||||
#define IFCC_GET_FCC(c) ((c) & 3)
|
||||
#define IFCC_ISFCC(c) (((c) & 4) == 0)
|
||||
|
||||
/* cc values for BPc and Tcc */
|
||||
#define IBCC_ICC 0x00
|
||||
#define IBCC_XCC 0x02
|
||||
|
||||
/*
|
||||
* Integer registers
|
||||
*/
|
||||
#define IREG_G0 0x00
|
||||
#define IREG_O0 0x08
|
||||
#define IREG_L0 0x10
|
||||
#define IREQ_I0 0x18
|
||||
|
||||
#endif /* !_MACHINE_INSTR_H_ */
|
||||
@@ -0,0 +1,164 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2002 Jake Burkholder.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "fsr.h"
|
||||
#include "fpu_emu.h"
|
||||
#include "fpu_extern.h"
|
||||
|
||||
#define _QP_OP(op) \
|
||||
void _Qp_ ## op(u_int *c, u_int *a, u_int *b); \
|
||||
void \
|
||||
_Qp_ ## op(u_int *c, u_int *a, u_int *b) \
|
||||
{ \
|
||||
struct fpemu fe; \
|
||||
struct fpn *r; \
|
||||
__asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
|
||||
fe.fe_cx = 0; \
|
||||
fe.fe_f1.fp_sign = a[0] >> 31; \
|
||||
fe.fe_f1.fp_sticky = 0; \
|
||||
fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \
|
||||
fe.fe_f2.fp_sign = b[0] >> 31; \
|
||||
fe.fe_f2.fp_sticky = 0; \
|
||||
fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \
|
||||
r = __fpu_ ## op(&fe); \
|
||||
c[0] = __fpu_ftoq(&fe, r, c); \
|
||||
fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
|
||||
__asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
|
||||
}
|
||||
|
||||
#define _QP_TTOQ(qname, fname, ntype, signpos, atype, ...) \
|
||||
void _Qp_ ## qname ## toq(u_int *c, ntype n); \
|
||||
void \
|
||||
_Qp_ ## qname ## toq(u_int *c, ntype n) \
|
||||
{ \
|
||||
struct fpemu fe; \
|
||||
union { atype a[2]; ntype n; } u = { .n = n }; \
|
||||
__asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
|
||||
fe.fe_cx = 0; \
|
||||
fe.fe_f1.fp_sign = (signpos >= 0) ? u.a[0] >> signpos : 0; \
|
||||
fe.fe_f1.fp_sticky = 0; \
|
||||
fe.fe_f1.fp_class = __fpu_ ## fname ## tof(&fe.fe_f1, __VA_ARGS__); \
|
||||
c[0] = __fpu_ftoq(&fe, &fe.fe_f1, c); \
|
||||
fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
|
||||
__asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
|
||||
}
|
||||
|
||||
#define _QP_QTOT(qname, fname, type, ...) \
|
||||
type _Qp_qto ## qname(u_int *c); \
|
||||
type \
|
||||
_Qp_qto ## qname(u_int *c) \
|
||||
{ \
|
||||
struct fpemu fe; \
|
||||
union { u_int a; type n; } u; \
|
||||
__asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
|
||||
fe.fe_cx = 0; \
|
||||
fe.fe_f1.fp_sign = c[0] >> 31; \
|
||||
fe.fe_f1.fp_sticky = 0; \
|
||||
fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, c[0], c[1], c[2], c[3]); \
|
||||
u.a = __fpu_fto ## fname(&fe, &fe.fe_f1, ## __VA_ARGS__); \
|
||||
fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
|
||||
__asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
|
||||
return (u.n); \
|
||||
}
|
||||
|
||||
#define FCC_EQ(fcc) ((fcc) == FSR_CC_EQ)
|
||||
#define FCC_GE(fcc) ((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_GT)
|
||||
#define FCC_GT(fcc) ((fcc) == FSR_CC_GT)
|
||||
#define FCC_LE(fcc) ((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_LT)
|
||||
#define FCC_LT(fcc) ((fcc) == FSR_CC_LT)
|
||||
#define FCC_NE(fcc) ((fcc) != FSR_CC_EQ)
|
||||
#define FCC_ID(fcc) (fcc)
|
||||
|
||||
#define _QP_CMP(name, cmpe, test) \
|
||||
int _Qp_ ## name(u_int *a, u_int *b) ; \
|
||||
int \
|
||||
_Qp_ ## name(u_int *a, u_int *b) \
|
||||
{ \
|
||||
struct fpemu fe; \
|
||||
__asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
|
||||
fe.fe_cx = 0; \
|
||||
fe.fe_f1.fp_sign = a[0] >> 31; \
|
||||
fe.fe_f1.fp_sticky = 0; \
|
||||
fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \
|
||||
fe.fe_f2.fp_sign = b[0] >> 31; \
|
||||
fe.fe_f2.fp_sticky = 0; \
|
||||
fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \
|
||||
__fpu_compare(&fe, cmpe, 0); \
|
||||
fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
|
||||
__asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
|
||||
return (test(FSR_GET_FCC0(fe.fe_fsr))); \
|
||||
}
|
||||
|
||||
void _Qp_sqrt(u_int *c, u_int *a);
|
||||
void
|
||||
_Qp_sqrt(u_int *c, u_int *a)
|
||||
{
|
||||
struct fpemu fe;
|
||||
struct fpn *r;
|
||||
__asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :);
|
||||
fe.fe_cx = 0;
|
||||
fe.fe_f1.fp_sign = a[0] >> 31;
|
||||
fe.fe_f1.fp_sticky = 0;
|
||||
fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]);
|
||||
r = __fpu_sqrt(&fe);
|
||||
c[0] = __fpu_ftoq(&fe, r, c);
|
||||
fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT;
|
||||
__asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr));
|
||||
}
|
||||
|
||||
_QP_OP(add)
|
||||
_QP_OP(div)
|
||||
_QP_OP(mul)
|
||||
_QP_OP(sub)
|
||||
|
||||
_QP_TTOQ(d, d, double, 31, u_int, u.a[0], u.a[1])
|
||||
_QP_TTOQ(i, i, int, 31, u_int, u.a[0])
|
||||
_QP_TTOQ(s, s, float, 31, u_int, u.a[0])
|
||||
_QP_TTOQ(x, x, long, 63, u_long, u.a[0])
|
||||
_QP_TTOQ(ui, i, u_int, -1, u_int, u.a[0])
|
||||
_QP_TTOQ(ux, x, u_long, -1, u_long, u.a[0])
|
||||
|
||||
_QP_QTOT(d, d, double, &u.a)
|
||||
_QP_QTOT(i, i, int)
|
||||
_QP_QTOT(s, s, float)
|
||||
_QP_QTOT(x, x, long, &u.a)
|
||||
_QP_QTOT(ui, i, u_int)
|
||||
_QP_QTOT(ux, x, u_long, &u.a)
|
||||
|
||||
_QP_CMP(feq, 0, FCC_EQ)
|
||||
_QP_CMP(fge, 1, FCC_GE)
|
||||
_QP_CMP(fgt, 1, FCC_GT)
|
||||
_QP_CMP(fle, 1, FCC_LE)
|
||||
_QP_CMP(flt, 1, FCC_LT)
|
||||
_QP_CMP(fne, 0, FCC_NE)
|
||||
_QP_CMP(cmp, 0, FCC_ID)
|
||||
_QP_CMP(cmpe, 1, FCC_ID)
|
||||
Reference in New Issue
Block a user