diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-03-25 19:08:57 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-03-25 19:08:57 +0000 |
commit | 6c1e632ba5b6c594fb8792d8739d841d7b320ca3 (patch) | |
tree | c9bbd86f58228e8f631c33cea3637112244cfd6d | |
parent | 2a5c5d0d6c30acc8f4c48a4f4c6300ad2397e8bd (diff) |
Remove the m68k FPU emulator; it was only used by the mac68k port which has been
lying in the Attic for quite awhile; none of the remaining m68k-based ports
support FPU-less systems; assuming my HP332 cpu board is in working condition,
give me memory boards for it to have at least 8MB and a chassis, and I'll
consider bringing this code back. But then, the 332 has an FPU socket, and
I'd rather write a new glue to use the MI softloat code (bug-free) than try
and fix the bugs in this.
-rw-r--r-- | sys/arch/m68k/fpe/README | 155 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/files.fpe | 22 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_add.c | 205 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_arith.h | 171 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_arith_proto.h | 74 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_calcea.c | 767 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_div.c | 263 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_emulate.c | 1166 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_emulate.h | 319 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_explode.c | 280 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_fmovecr.c | 119 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_fscale.c | 333 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_fstore.c | 132 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_getexp.c | 77 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_implode.c | 488 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_int.c | 124 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_log.c | 602 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_mul.c | 212 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_rem.c | 232 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_sqrt.c | 360 | ||||
-rw-r--r-- | sys/arch/m68k/fpe/fpu_subr.c | 209 |
21 files changed, 0 insertions, 6310 deletions
diff --git a/sys/arch/m68k/fpe/README b/sys/arch/m68k/fpe/README deleted file mode 100644 index ba738da39e4..00000000000 --- a/sys/arch/m68k/fpe/README +++ /dev/null @@ -1,155 +0,0 @@ -# $OpenBSD: README,v 1.4 2007/11/25 16:40:04 jmc Exp $ -* $NetBSD: README,v 1.4 1995/11/05 04:23:00 briggs Exp $ -* NetBSD/m68k FPE (floating point emulation) README file -* Created Oct/??/95 by kenn@remus.rutgers.edu (Ken Nakata) -* Last updated Nov/04/95 by kenn - -1. INSTALLATION AND COMPILATION - -To compile a kernel with FPE built-in, do the following: - -1) Add a line "options FPU_EMULATE" to your config file. If you are -going to use the resulted kernel on a machine with an FPU for -debugging purpose, add "options DEBUG_WITH_FPU" as well. - -2) Follow the usual procedure to build a new kernel. - -NOTE: If you add "options DEBUG_WITH_FPU", FPE will accept cpID=6 as -emulated FPU. You will need a modified gas that generates cpID=6 for -floating point instructions, instead of normal cpID=1. Apply the -following patch to the gas source: - -*** /usr/src/gnu/usr.bin/gas/config/tc-m68k.c Mon Nov 21 16:30:41 1994 ---- gas/config/tc-m68k.c Fri Sep 29 07:59:06 1995 -*************** -*** 1275,1281 **** - /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */ - memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0])); - the_ins.operands[0].mode=MSCR; -! the_ins.operands[0].reg=COPNUM; /* COP #1 */ - opsfound++; - } - ---- 1275,1281 ---- - /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */ - memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0])); - the_ins.operands[0].mode=MSCR; -! the_ins.operands[0].reg=COP5; /* COP #6 */ - opsfound++; - } - - -Also, with the DEBUG_WITH_FPU option, you will be able to run only ONE -process that uses FPE at once to get correct results. - - -2. MISSING PARTS - -For missing instructions, refer to the Section 3. Other than that, -there is one thing that is missing from this version of FPE: packed -BCD support. - -I have no plan to support it since it's rarely used. However, all we -need to support it is explosion/implosion functions between the -internal FP representation and the m68k PBCD format, so you are more -than welcome to write such functions if you wish to. - - -3. IMPLEMENTED INSTRUCTIONS - -This is the list of implemented and unimplemented FPU instructions. -All 040's directly supported type 0 instructions are already -implemented except FSGLDIV and FSGLMUL. - -Type field = bit 8-6 of opcode word - -* Implemented Instructions - -Type=0: FMOVE (mem->FPr), FINT, FINTRZ, FSQRT, FABS, FNEG, FGETEXP, - FGETMAN, FDIV, FADD, FMUL, FSGLDIV(*), FSCALE, FSGLMUL(*), FSUB, - FCMP, FTST, FMOVE (FPr->mem), FMOVEM (FPr), FMOVEM (FPcr), - FMOVECR, FLOGNP1, FLOGN, FLOG10, FLOG2, FMOD, FREM - -Type=1: FDBcc, FScc, FTRAPcc, - -Type=2: FBcc (word, incl. FNOP) - -Type=3: FBcc (long) - -Type=4: none - -Type=5: none - - *: currently FSGLMUL and FSGLDIV are just aliases of - FMUL and FDIV, respectively - -* Unimplemented Instructions - -Type=0: FSINH, FETOXM1, FTANH, FATAN, FASIN, FATANH, FSIN, FTAN, - FETOX, FTWOTOX, FTENTOX, FCOSH, FACOS, FCOS, FSINCOS - -Type=1: none - -Type=2: none - -Type=3: none - -Type=4: FSAVE - -Type=5: FRESTORE - - -4. HOW TO ADD A NEW INSTRUCTION SUPPORT - -Since we need not support FSAVE and FRESTORE operations, all -instructions we have to implement are type 0, all of which are -arithmetic operations. It is particularly easy to add a new -arithmetic instruction to the existing ones (not that it is easy to -write a "stable" function to perform floating point operation. That's -entirely another matter). In "fpu_emulate.c", there's a function -fpu_emul_arith() which calls emulation functions for all arithmetic -operations. In it, there's a large switch() { case ... } which -dispatches each instruction emulator. An emulation function of any -type 0 arithmetic instruction follows this prototype: - - struct fpn *fpu_op(struct fpemu *fe); - -Where fe is a pointer to a struct fpemu in which frame, fpframe, and -fetched operands are accessible. That's right, you don't have to -fetch the operands by yourself in your emulation function. For -instance, the parts calling FSQRT, FSUB, FADD and FTST look like: - - switch(word1 & 0x3F) { -[...] - case 0x04: /* fsqrt */ - res = fpu_sqrt(fe); - break; -[...] - case 0x28: /* fsub */ - fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */ - case 0x22: /* fadd */ - res = fpu_add(fe); - break; -[...] - case 0x3A: /* ftst */ - res = &fe->fe_f2; - no_store = 1; - break; -[...] - default: - sig = SIGILL; - } /* switch */ - -Here, fe->fe_f1 and fe->fe_f2 are fetched operands. You can use -fe->fe_f3 for storing the result, or you can return a pointer to -either operand if you want to. At any rate, you have to follow -the following rules: - - 1) A dyadic instruction takes two operands fe->fe_f1 and fe->fe_f2. - 2) A monadic instruction takes one operand fe->fe_f2 (NOT fe_f1). - 3) Must return a pointer to struct fpn where the result is stored, - and assign the pointer to the variable "res". - 4) If exceptions are detected, set corresponding bits in fe->fe_fpsr. - The rest is taken care of in fpu_emul_arith(). - 5) Condition code does not need to be calculated. It's taken care of in - fpu_emul_arith(). diff --git a/sys/arch/m68k/fpe/files.fpe b/sys/arch/m68k/fpe/files.fpe deleted file mode 100644 index a10c479e163..00000000000 --- a/sys/arch/m68k/fpe/files.fpe +++ /dev/null @@ -1,22 +0,0 @@ -# $OpenBSD: files.fpe,v 1.3 2006/01/16 22:08:26 miod Exp $ -# $NetBSD: files.fpe,v 1.2 1995/11/03 04:51:51 briggs Exp $ - -# files for m68k floating point emulator. -# Included by ports that need it. - -file arch/m68k/fpe/fpu_add.c fpu_emulate -file arch/m68k/fpe/fpu_calcea.c fpu_emulate -file arch/m68k/fpe/fpu_div.c fpu_emulate -file arch/m68k/fpe/fpu_emulate.c fpu_emulate -file arch/m68k/fpe/fpu_explode.c fpu_emulate -file arch/m68k/fpe/fpu_fmovecr.c fpu_emulate -file arch/m68k/fpe/fpu_fscale.c fpu_emulate -file arch/m68k/fpe/fpu_fstore.c fpu_emulate -file arch/m68k/fpe/fpu_getexp.c fpu_emulate -file arch/m68k/fpe/fpu_implode.c fpu_emulate -file arch/m68k/fpe/fpu_int.c fpu_emulate -file arch/m68k/fpe/fpu_log.c fpu_emulate -file arch/m68k/fpe/fpu_mul.c fpu_emulate -file arch/m68k/fpe/fpu_rem.c fpu_emulate -file arch/m68k/fpe/fpu_sqrt.c fpu_emulate -file arch/m68k/fpe/fpu_subr.c fpu_emulate diff --git a/sys/arch/m68k/fpe/fpu_add.c b/sys/arch/m68k/fpe/fpu_add.c deleted file mode 100644 index ac53572b3ef..00000000000 --- a/sys/arch/m68k/fpe/fpu_add.c +++ /dev/null @@ -1,205 +0,0 @@ -/* $OpenBSD: fpu_add.c,v 1.4 2006/01/16 22:08:26 miod Exp $ */ -/* $NetBSD: fpu_add.c,v 1.5 2003/08/07 16:28:10 agc Exp $ */ - -/* - * 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 - */ - -/* - * Perform an FPU add (return x + y). - * - * To subtract, negate y and call add. - */ - -#include <sys/types.h> -#include <sys/systm.h> - -#include <machine/reg.h> - -#include "fpu_arith.h" -#include "fpu_emulate.h" - -struct fpn * -fpu_add(fe) - struct fpemu *fe; -{ - struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2, *r; - u_int r0, r1, r2; - 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 = (fe->fe_fpcr & FPCR_ROUND); - if (ISZERO(y)) { - if (rd != FPCR_MINF) /* 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[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(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) == 0) { - /* case ii */ - r->fp_class = FPC_ZERO; - r->fp_sign = (rd == FPCR_MINF); - 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) - panic("fpu_add"); -#endif - r->fp_sign = y->fp_sign; - FPU_SUBS(r2, 0, r2); - FPU_SUBCS(r1, 0, r1); - FPU_SUBC(r0, 0, r0); - } - r->fp_mant[2] = r2; - r->fp_mant[1] = r1; - r->fp_mant[0] = r0; - if (r0 < FP_1) - fpu_norm(r); - } - return (r); -} diff --git a/sys/arch/m68k/fpe/fpu_arith.h b/sys/arch/m68k/fpe/fpu_arith.h deleted file mode 100644 index bceb7f25f38..00000000000 --- a/sys/arch/m68k/fpe/fpu_arith.h +++ /dev/null @@ -1,171 +0,0 @@ -/* $OpenBSD: fpu_arith.h,v 1.5 2011/09/17 08:38:07 miod Exp $ */ -/* $NetBSD: fpu_arith.h,v 1.3 2003/08/07 16:28:10 agc Exp $ */ - -/* - * 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_arith.h 8.1 (Berkeley) 6/11/93 - */ - -/* - * 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. - */ - -#ifndef FPE_USE_ASM - -/* set up for extended-precision arithmetic */ -#define FPU_DECL_CARRY quad_t fpu_carry, fpu_tmp; - -/* - * 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) \ - (r) = (x) + (y) + (!!fpu_carry) -#define FPU_ADDS(r, x, y) \ - { \ - fpu_tmp = (quad_t)(x) + (quad_t)(y); \ - (r) = (u_int)fpu_tmp; \ - fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ - } -#define FPU_ADDCS(r, x, y) \ - { \ - fpu_tmp = (quad_t)(x) + (quad_t)(y) + (!!fpu_carry); \ - (r) = (u_int)fpu_tmp; \ - fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ - } -#define FPU_SUBC(r, x, y) \ - (r) = (x) - (y) - (!!fpu_carry) -#define FPU_SUBS(r, x, y) \ - { \ - fpu_tmp = (quad_t)(x) - (quad_t)(y); \ - (r) = (u_int)fpu_tmp; \ - fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ - } -#define FPU_SUBCS(r, x, y) \ - { \ - fpu_tmp = (quad_t)(x) - (quad_t)(y) - (!!fpu_carry); \ - (r) = (u_int)fpu_tmp; \ - fpu_carry = ((fpu_tmp & 0xffffffff00000000LL) != 0); \ - } - -#define FPU_GET_CARRY(r) (r) = (!!fpu_carry) -#define FPU_SET_CARRY(v) fpu_carry = ((v) != 0) - -#else - -/* set up for extended-precision arithmetic */ -#define FPU_DECL_CARRY int fpu_tmp; - -/* - * 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("movel %1,%0" : "=d"(fpu_tmp) : "g"(x)); \ - asm volatile("addxl %1,%0" : "=d"(fpu_tmp) : "d"(y)); \ - asm volatile("movel %1,%0" : "=g"(r) : "r"(fpu_tmp)); \ - } -#define FPU_ADDS(r, x, y) \ - { \ - asm volatile("movel %1,%0" : "=d"(fpu_tmp) : "g"(x)); \ - asm volatile("addl %1,%0" : "=d"(fpu_tmp) : "g"(y)); \ - asm volatile("movel %1,%0" : "=g"(r) : "r"(fpu_tmp)); \ - } -#define FPU_ADDCS(r, x, y) FPU_ADDC(r, x, y) - -#define FPU_SUBC(r, x, y) \ - { \ - asm volatile("movel %1,%0" : "=d"(fpu_tmp) : "g"(x)); \ - asm volatile("subxl %1,%0" : "=d"(fpu_tmp) : "d"(y)); \ - asm volatile("movel %1,%0" : "=g"(r) : "r"(fpu_tmp)); \ - } -#define FPU_SUBS(r, x, y) \ - { \ - asm volatile("movel %1,%0" : "=d"(fpu_tmp) : "g"(x)); \ - asm volatile("subl %1,%0" : "=d"(fpu_tmp) : "g"(y)); \ - asm volatile("movel %1,%0" : "=g"(r) : "r"(fpu_tmp)); \ - } -#define FPU_SUBCS(r, x, y) FPU_SUBC(r, x, y) - -#define FPU_GET_CARRY(r) \ - { \ - asm volatile("moveq #0,%0" : "=d"(r)); \ - asm volatile("addxl %0,%0" : "+d"(r)); \ - } -#define FPU_SET_CARRY(v) \ - { \ - asm volatile("moveq #0,%0" : "=d"(fpu_tmp)); \ - asm volatile("subl %1,%0" : "=d"(fpu_tmp) : "g"(v)); \ - } - -#endif /* FPE_USE_ASM */ diff --git a/sys/arch/m68k/fpe/fpu_arith_proto.h b/sys/arch/m68k/fpe/fpu_arith_proto.h deleted file mode 100644 index 8976c8c55e4..00000000000 --- a/sys/arch/m68k/fpe/fpu_arith_proto.h +++ /dev/null @@ -1,74 +0,0 @@ -/* $OpenBSD: fpu_arith_proto.h,v 1.4 2006/01/16 22:08:26 miod Exp $ */ -/* $NetBSD: fpu_arith_proto.h,v 1.1 1995/11/03 04:47:00 briggs Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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. Neither the name of the author 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 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. - * - * @(#)fpu_arith_proto.c 10/24/95 - */ - -#ifndef _FPU_ARITH_PROTO_H_ -#define _FPU_ARITH_PROTO_H_ - -/* - * Arithmetic functions - called from fpu_emul_arith(). - * Each of these may modify its inputs (f1,f2) and/or the temporary. - * Each returns a pointer to the result and/or sets exceptions. - */ - -/* fpu_add.c */ -struct fpn *fpu_add(struct fpemu *fe); - -/* fpu_div.c */ -struct fpn *fpu_div(struct fpemu *fe); - -/* fpu_getexp.c */ -struct fpn *fpu_getexp(struct fpemu *fe); -struct fpn *fpu_getman(struct fpemu *fe); - -/* fpu_int.c */ -struct fpn *fpu_intrz(struct fpemu *fe); -struct fpn *fpu_int(struct fpemu *fe); - -/* fpu_log.c */ -struct fpn *fpu_log10(struct fpemu *fe); -struct fpn *fpu_log2(struct fpemu *fe); -struct fpn *fpu_logn(struct fpemu *fe); -struct fpn *fpu_lognp1(struct fpemu *fe); - -/* fpu_mulc */ -struct fpn *fpu_mul(struct fpemu *fe); - -/* fpu_rem.c */ -struct fpn *fpu_rem(struct fpemu *fe); -struct fpn *fpu_mod(struct fpemu *fe); - -/* fpu_sqrt.c */ -struct fpn *fpu_sqrt(struct fpemu *fe); - -#endif /* _FPU_ARITH_PROTO_H_ */ diff --git a/sys/arch/m68k/fpe/fpu_calcea.c b/sys/arch/m68k/fpe/fpu_calcea.c deleted file mode 100644 index 8d76a849158..00000000000 --- a/sys/arch/m68k/fpe/fpu_calcea.c +++ /dev/null @@ -1,767 +0,0 @@ -/* $OpenBSD: fpu_calcea.c,v 1.11 2006/01/30 21:23:22 miod Exp $ */ -/* $NetBSD: fpu_calcea.c,v 1.16 2004/02/13 11:36:14 wiz Exp $ */ - -/* - * Copyright (c) 1995 Gordon W. Ross - * portion Copyright (c) 1995 Ken Nakata - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 4. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Gordon Ross - * - * 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. - */ - -#include <sys/param.h> -#include <sys/signal.h> -#include <sys/systm.h> -#include <machine/frame.h> - -#include "fpu_emulate.h" - -/* - * Prototypes of local functions - */ -int decode_ea6(struct frame *frame, struct instruction *insn, - struct insn_ea *ea, int modreg, int *typ); -int fetch_immed(struct frame *frame, struct instruction *insn, - int *dst); -int fetch_disp(struct frame *frame, struct instruction *insn, - int size, int *res); -int calc_ea(struct insn_ea *ea, char *ptr, char **eaddr); - -/* - * Helper routines for dealing with "effective address" values. - */ - -/* - * Decode an effective address into internal form. - * Returns zero on success, else signal number. - */ -int -fpu_decode_ea(struct frame *frame, struct instruction *insn, struct insn_ea *ea, - int modreg, int *typ) -{ - int sig; - -#ifdef DEBUG - if (insn->is_datasize < 0) { - panic("decode_ea: called with uninitialized datasize"); - } -#endif - - sig = 0; - - /* Set the most common value here. */ - ea->ea_regnum = 8 + (modreg & 7); - - if ((modreg & 060) == 0) { - /* register direct */ - ea->ea_regnum = modreg & 0xf; - ea->ea_flags = EA_DIRECT; -#ifdef DEBUG_FPE - printf("decode_ea: register direct reg=%d\n", ea->ea_regnum); -#endif - } else if ((modreg & 077) == 074) { - /* immediate */ - ea->ea_flags = EA_IMMED; - sig = fetch_immed(frame, insn, &ea->ea_immed[0]); -#ifdef DEBUG_FPE - printf("decode_ea: immediate size=%d\n", insn->is_datasize); -#endif - } - /* - * rest of the address modes need to be separately - * handled for the LC040 and the others. - */ -#if 0 /* XXX */ - else if (frame->f_format == 4 && frame->f_fmt4.f_fa) { - /* LC040 */ - ea->ea_flags = EA_FRAME_EA; - ea->ea_fea = frame->f_fmt4.f_fa; -#ifdef DEBUG_FPE - printf("decode_ea: 68LC040 - in-frame EA (%p) size %d\n", - (void *)ea->ea_fea, insn->is_datasize); -#endif - if ((modreg & 070) == 030) { - /* postincrement mode */ - ea->ea_flags |= EA_POSTINCR; - } else if ((modreg & 070) == 040) { - /* predecrement mode */ - ea->ea_flags |= EA_PREDECR; -#ifdef M68060 -#if defined(M68020) || defined(M68030) || defined(M68040) - if (cputype == CPU_68060) -#endif - if (insn->is_datasize == 12) - ea->ea_fea -= 8; -#endif - } - } -#endif /* XXX */ - else { - /* 020/030 */ - switch (modreg & 070) { - - case 020: /* (An) */ - ea->ea_flags = 0; -#ifdef DEBUG_FPE - printf("decode_ea: register indirect reg=%d\n", ea->ea_regnum); -#endif - break; - - case 030: /* (An)+ */ - ea->ea_flags = EA_POSTINCR; -#ifdef DEBUG_FPE - printf("decode_ea: reg indirect postincrement reg=%d\n", - ea->ea_regnum); -#endif - break; - - case 040: /* -(An) */ - ea->ea_flags = EA_PREDECR; -#ifdef DEBUG_FPE - printf("decode_ea: reg indirect predecrement reg=%d\n", - ea->ea_regnum); -#endif - break; - - case 050: /* (d16,An) */ - ea->ea_flags = EA_OFFSET; - sig = fetch_disp(frame, insn, 1, &ea->ea_offset); -#ifdef DEBUG_FPE - printf("decode_ea: reg indirect with displacement reg=%d\n", - ea->ea_regnum); -#endif - break; - - case 060: /* (d8,An,Xn) */ - ea->ea_flags = EA_INDEXED; - sig = decode_ea6(frame, insn, ea, modreg, typ); - break; - - case 070: /* misc. */ - ea->ea_regnum = (modreg & 7); - switch (modreg & 7) { - - case 0: /* (xxxx).W */ - ea->ea_flags = EA_ABS; - sig = fetch_disp(frame, insn, 1, &ea->ea_absaddr); -#ifdef DEBUG_FPE - printf("decode_ea: absolute address (word)\n"); -#endif - break; - - case 1: /* (xxxxxxxx).L */ - ea->ea_flags = EA_ABS; - sig = fetch_disp(frame, insn, 2, &ea->ea_absaddr); -#ifdef DEBUG_FPE - printf("decode_ea: absolute address (long)\n"); -#endif - break; - - case 2: /* (d16,PC) */ - ea->ea_flags = EA_PC_REL | EA_OFFSET; - sig = fetch_disp(frame, insn, 1, &ea->ea_absaddr); -#ifdef DEBUG_FPE - printf("decode_ea: pc relative word displacement\n"); -#endif - break; - - case 3: /* (d8,PC,Xn) */ - ea->ea_flags = EA_PC_REL | EA_INDEXED; - sig = decode_ea6(frame, insn, ea, modreg, typ); - break; - - case 4: /* #data */ - /* it should have been taken care of earlier */ - default: -#ifdef DEBUG_FPE - printf("decode_ea: invalid addr mode (7,%d)\n", modreg & 7); -#endif - *typ = ILL_ILLADR; - return SIGILL; - } /* switch for mode 7 */ - break; - } /* switch mode */ - } - ea->ea_moffs = 0; - - return sig; -} - -/* - * Decode Mode=6 address modes - */ -int -decode_ea6(struct frame *frame, struct instruction *insn, struct insn_ea *ea, - int modreg, int *typ) -{ - int idx; - int basedisp, outerdisp; - int bd_size, od_size; - int sig; - u_int16_t extword; - - if (copyin((void *)(insn->is_pc + insn->is_advance), &extword, - sizeof(extword)) != 0) { - return SIGSEGV; - } - insn->is_advance += 2; - - /* get register index */ - ea->ea_idxreg = (extword >> 12) & 0xf; - idx = frame->f_regs[ea->ea_idxreg]; - if ((extword & 0x0800) == 0) { - /* if word sized index, sign-extend */ - idx &= 0xffff; - if (idx & 0x8000) { - idx |= 0xffff0000; - } - } - /* scale register index */ - idx <<= ((extword >> 9) & 3); - - if ((extword & 0x100) == 0) { - /* brief extension word - sign-extend the displacement */ - basedisp = (extword & 0xff); - if (basedisp & 0x80) { - basedisp |= 0xffffff00; - } - - ea->ea_basedisp = idx + basedisp; - ea->ea_outerdisp = 0; -#if DEBUG_FPE - printf("decode_ea6: brief ext word idxreg=%d, basedisp=%08x\n", - ea->ea_idxreg, ea->ea_basedisp); -#endif - } else { - /* full extension word */ - if (extword & 0x80) { - ea->ea_flags |= EA_BASE_SUPPRSS; - } - bd_size = ((extword >> 4) & 3) - 1; - od_size = (extword & 3) - 1; - sig = fetch_disp(frame, insn, bd_size, &basedisp); - if (sig) { - return sig; - } - if (od_size >= 0) { - ea->ea_flags |= EA_MEM_INDIR; - } - sig = fetch_disp(frame, insn, od_size, &outerdisp); - if (sig) { - return sig; - } - - switch (extword & 0x44) { - case 0: /* preindexed */ - ea->ea_basedisp = basedisp + idx; - ea->ea_outerdisp = outerdisp; - break; - case 4: /* postindexed */ - ea->ea_basedisp = basedisp; - ea->ea_outerdisp = outerdisp + idx; - break; - case 0x40: /* no index */ - ea->ea_basedisp = basedisp; - ea->ea_outerdisp = outerdisp; - break; - default: -#ifdef DEBUG - printf("decode_ea6: invalid indirect mode: ext word %02x\n", - extword); -#endif - *typ = ILL_ILLADR; - return SIGILL; - break; - } -#if DEBUG_FPE - printf("decode_ea6: full ext idxreg=%d, basedisp=%x, outerdisp=%x\n", - ea->ea_idxreg, ea->ea_basedisp, ea->ea_outerdisp); -#endif - } -#if DEBUG_FPE - printf("decode_ea6: regnum=%d, flags=%x\n", - ea->ea_regnum, ea->ea_flags); -#endif - return 0; -} - -/* - * Load a value from an effective address. - * Returns zero on success, else signal number. - */ -int -fpu_load_ea(struct frame *frame, struct instruction *insn, struct insn_ea *ea, - char *dst, int *typ) -{ - int *reg; - char *src; - int len, step; - int sig; - -#ifdef DIAGNOSTIC - if (ea->ea_regnum & ~0xF) { - panic("load_ea: bad regnum"); - } -#endif - -#ifdef DEBUG_FPE - printf("load_ea: frame at %p\n", frame); -#endif - /* dst is always int or larger. */ - len = insn->is_datasize; - if (len < 4) { - dst += (4 - len); - } - step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len; - -#if 0 - if (ea->ea_flags & EA_FRAME_EA) { - /* Using LC040 frame EA */ -#ifdef DEBUG_FPE - if (ea->ea_flags & (EA_PREDECR|EA_POSTINCR)) { - printf("load_ea: frame ea %08x w/r%d\n", - ea->ea_fea, ea->ea_regnum); - } else { - printf("load_ea: frame ea %08x\n", ea->ea_fea); - } -#endif - src = (char *)ea->ea_fea; - if (copyin(src + ea->ea_moffs, dst, len) != 0) - return (SIGSEGV); - if (ea->ea_flags & EA_PREDECR) { - frame->f_regs[ea->ea_regnum] = ea->ea_fea; - ea->ea_fea -= step; - ea->ea_moffs = 0; - } else if (ea->ea_flags & EA_POSTINCR) { - ea->ea_fea += step; - frame->f_regs[ea->ea_regnum] = ea->ea_fea; - ea->ea_moffs = 0; - } else { - ea->ea_moffs += step; - } - /* That's it, folks */ - } else if (ea->ea_flags & EA_DIRECT) { - if (len > 4) { -#ifdef DEBUG - printf("load_ea: operand doesn't fit CPU reg\n"); -#endif - return SIGILL; - } - if (ea->ea_moffs > 0) { -#ifdef DEBUG - printf("load_ea: more than one move from CPU reg\n"); -#endif - return SIGILL; - } - src = (char *)&frame->f_regs[ea->ea_regnum]; - /* The source is an int. */ - if (len < 4) { - src += (4 - len); -#ifdef DEBUG_FPE - printf("load_ea: short/byte opr - addr adjusted\n"); -#endif - } -#ifdef DEBUG_FPE - printf("load_ea: src %p\n", src); -#endif - memcpy(dst, src, len); - } else -#endif /* 0 */ - if (ea->ea_flags & EA_IMMED) { -#ifdef DEBUG_FPE - printf("load_ea: immed %08x%08x%08x size %d\n", - ea->ea_immed[0], ea->ea_immed[1], ea->ea_immed[2], len); -#endif - src = (char *)&ea->ea_immed[0]; - if (len < 4) { - src += (4 - len); -#ifdef DEBUG_FPE - printf("load_ea: short/byte immed opr - addr adjusted\n"); -#endif - } - memcpy(dst, src, len); - } else if (ea->ea_flags & EA_ABS) { -#ifdef DEBUG_FPE - printf("load_ea: abs addr %08x\n", ea->ea_absaddr); -#endif - src = (char *)ea->ea_absaddr; - if (copyin(src, dst, len) != 0) - return (SIGSEGV); - } else /* register indirect */ { - if (ea->ea_flags & EA_PC_REL) { -#ifdef DEBUG_FPE - printf("load_ea: using PC\n"); -#endif - reg = NULL; - /* Grab the register contents. 4 is offset to the first - extension word from the opcode */ - src = (char *)insn->is_pc + 4; -#ifdef DEBUG_FPE - printf("load_ea: pc relative pc+4 = %p\n", src); -#endif - } else /* not PC relative */ { -#ifdef DEBUG_FPE - printf("load_ea: using register %c%d\n", - (ea->ea_regnum >= 8) ? 'a' : 'd', ea->ea_regnum & 7); -#endif - /* point to the register */ - reg = &frame->f_regs[ea->ea_regnum]; - - if (ea->ea_flags & EA_PREDECR) { -#ifdef DEBUG_FPE - printf("load_ea: predecr mode - reg decremented\n"); -#endif - *reg -= step; - ea->ea_moffs = 0; - } - - /* Grab the register contents. */ - src = (char *)*reg; -#ifdef DEBUG_FPE - printf("load_ea: reg indirect reg = %p\n", src); -#endif - } - - sig = calc_ea(ea, src, &src); - if (sig) - return sig; - - if (copyin(src + ea->ea_moffs, dst, len) != 0) - return (SIGSEGV); - - /* do post-increment */ - if (ea->ea_flags & EA_POSTINCR) { - if (ea->ea_flags & EA_PC_REL) { -#ifdef DEBUG - printf("load_ea: tried to postincrement PC\n"); -#endif - *typ = ILL_ILLADR; - return SIGILL; - } - *reg += step; - ea->ea_moffs = 0; -#ifdef DEBUG_FPE - printf("load_ea: postinc mode - reg incremented\n"); -#endif - } else { - ea->ea_moffs += len; - } - } - - return 0; -} - -/* - * Store a value at the effective address. - * Returns zero on success, else signal number. - */ -int -fpu_store_ea(frame, insn, ea, src) - struct frame *frame; - struct instruction *insn; - struct insn_ea *ea; - char *src; -{ - int *reg; - char *dst; - int len, step; - int sig; - -#ifdef DIAGNOSTIC - if (ea->ea_regnum & ~0xf) { - panic("store_ea: bad regnum"); - } -#endif - - if (ea->ea_flags & (EA_IMMED|EA_PC_REL)) { - /* not alterable address mode */ -#ifdef DEBUG - printf("store_ea: not alterable address mode\n"); -#endif - return SIGILL; - } - - /* src is always int or larger. */ - len = insn->is_datasize; - if (len < 4) { - src += (4 - len); - } - step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len; - - if (ea->ea_flags & EA_FRAME_EA) { - /* Using LC040 frame EA */ -#ifdef DEBUG_FPE - if (ea->ea_flags & (EA_PREDECR|EA_POSTINCR)) { - printf("store_ea: frame ea %08x w/r%d\n", - ea->ea_fea, ea->ea_regnum); - } else { - printf("store_ea: frame ea %08x\n", ea->ea_fea); - } -#endif - dst = (char *)ea->ea_fea; - copyout(src, dst + ea->ea_moffs, len); - if (ea->ea_flags & EA_PREDECR) { - frame->f_regs[ea->ea_regnum] = ea->ea_fea; - ea->ea_fea -= step; - ea->ea_moffs = 0; - } else if (ea->ea_flags & EA_POSTINCR) { - ea->ea_fea += step; - frame->f_regs[ea->ea_regnum] = ea->ea_fea; - ea->ea_moffs = 0; - } else { - ea->ea_moffs += step; - } - /* That's it, folks */ - } else if (ea->ea_flags & EA_ABS) { -#ifdef DEBUG_FPE - printf("store_ea: abs addr %08x\n", ea->ea_absaddr); -#endif - dst = (char *)ea->ea_absaddr; - copyout(src, dst + ea->ea_moffs, len); - ea->ea_moffs += len; - } else if (ea->ea_flags & EA_DIRECT) { - if (len > 4) { -#ifdef DEBUG - printf("store_ea: operand doesn't fit CPU reg\n"); -#endif - return SIGILL; - } - if (ea->ea_moffs > 0) { -#ifdef DEBUG - printf("store_ea: more than one move to CPU reg\n"); -#endif - return SIGILL; - } - dst = (char *)&frame->f_regs[ea->ea_regnum]; - /* The destination is an int. */ - if (len < 4) { - dst += (4 - len); -#ifdef DEBUG_FPE - printf("store_ea: short/byte opr - dst addr adjusted\n"); -#endif - } -#ifdef DEBUG_FPE - printf("store_ea: dst %p\n", dst); -#endif - memcpy(dst, src, len); - } else /* One of MANY indirect forms... */ { -#ifdef DEBUG_FPE - printf("store_ea: using register %c%d\n", - (ea->ea_regnum >= 8) ? 'a' : 'd', ea->ea_regnum & 7); -#endif - /* point to the register */ - reg = &(frame->f_regs[ea->ea_regnum]); - - /* do pre-decrement */ - if (ea->ea_flags & EA_PREDECR) { -#ifdef DEBUG_FPE - printf("store_ea: predecr mode - reg decremented\n"); -#endif - *reg -= step; - ea->ea_moffs = 0; - } - - /* calculate the effective address */ - sig = calc_ea(ea, (char *)*reg, &dst); - if (sig) - return sig; - -#ifdef DEBUG_FPE - printf("store_ea: dst addr=%p+%d\n", dst, ea->ea_moffs); -#endif - copyout(src, dst + ea->ea_moffs, len); - - /* do post-increment */ - if (ea->ea_flags & EA_POSTINCR) { - *reg += step; - ea->ea_moffs = 0; -#ifdef DEBUG_FPE - printf("store_ea: postinc mode - reg incremented\n"); -#endif - } else { - ea->ea_moffs += len; - } - } - - return 0; -} - -/* - * fetch_immed: fetch immediate operand - */ -int -fetch_immed(frame, insn, dst) - struct frame *frame; - struct instruction *insn; - int *dst; -{ - int data, ext_bytes; - u_int16_t tmp; - - ext_bytes = insn->is_datasize; - if (ext_bytes < 0) - return (0); - - if (ext_bytes <= 2) { - if (copyin((void *)(insn->is_pc + insn->is_advance), &tmp, - sizeof(tmp)) != 0) { - return SIGSEGV; - } - if (ext_bytes == 1) { - /* sign-extend byte to long */ - data = (char)tmp; - } else { - /* sign-extend word to long */ - data = (int)tmp; - } - insn->is_advance += 2; - dst[0] = data; - return (0); - } - - /* if (ext_bytes > 2) { */ - if (copyin((void *)(insn->is_pc + insn->is_advance), &dst[0], - sizeof(dst[0])) != 0) { - return SIGSEGV; - } - insn->is_advance += 4; - /* } */ - - if (ext_bytes > 4) { - if (copyin((void *)(insn->is_pc + insn->is_advance), &dst[1], - sizeof(dst[1])) != 0) { - return SIGSEGV; - } - insn->is_advance += 4; - } - - if (ext_bytes > 8) { - if (copyin((void *)(insn->is_pc + insn->is_advance), &dst[2], - sizeof(dst[2])) != 0) { - return SIGSEGV; - } - insn->is_advance += 4; - } - - return 0; -} - -/* - * fetch_disp: fetch displacement in full extension words - */ -int -fetch_disp(frame, insn, size, res) - struct frame *frame; - struct instruction *insn; - int size, *res; -{ - int disp; - u_int16_t word; - - switch (size) { - case 1: - if (copyin((void *)(insn->is_pc + insn->is_advance), &word, - sizeof(word)) != 0) { - return SIGSEGV; - } - /* sign-extend */ - disp = (int)word; - insn->is_advance += 2; - break; - case 2: - if (copyin((void *)(insn->is_pc + insn->is_advance), &disp, - sizeof(disp)) != 0) { - return SIGSEGV; - } - insn->is_advance += 4; - break; - default: - disp = 0; - break; - } - - *res = disp; - - return 0; -} - -/* - * Calculates an effective address for all address modes except for - * register direct, absolute, and immediate modes. However, it does - * not take care of predecrement/postincrement of register content. - * Returns a signal value (0 == no error). - */ -int -calc_ea(ea, ptr, eaddr) - struct insn_ea *ea; - char *ptr; /* base address (usually a register content) */ - char **eaddr; /* pointer to result pointer */ -{ - int word; - -#if DEBUG_FPE - printf("calc_ea: reg indirect (reg) = %p\n", ptr); -#endif - - if (ea->ea_flags & EA_OFFSET) { - /* apply the signed offset */ -#if DEBUG_FPE - printf("calc_ea: offset %d\n", ea->ea_offset); -#endif - ptr += ea->ea_offset; - } else if (ea->ea_flags & EA_INDEXED) { -#if DEBUG_FPE - printf("calc_ea: indexed mode\n"); -#endif - - if (ea->ea_flags & EA_BASE_SUPPRSS) { - /* base register is suppressed */ - ptr = (char *)ea->ea_basedisp; - } else { - ptr += ea->ea_basedisp; - } - - if (ea->ea_flags & EA_MEM_INDIR) { -#if DEBUG_FPE - printf("calc_ea: mem indir mode: basedisp=%08x, outerdisp=%08x\n", - ea->ea_basedisp, ea->ea_outerdisp); - printf("calc_ea: addr fetched from %p\n", ptr); -#endif - /* memory indirect modes */ - if (copyin(ptr, &word, sizeof(word)) != 0) { - return SIGSEGV; - } -#if DEBUG_FPE - printf("calc_ea: fetched ptr 0x%08x\n", word); -#endif - ptr = (char *)word + ea->ea_outerdisp; - } - } - - *eaddr = ptr; - - return 0; -} diff --git a/sys/arch/m68k/fpe/fpu_div.c b/sys/arch/m68k/fpe/fpu_div.c deleted file mode 100644 index f01ff07ed6d..00000000000 --- a/sys/arch/m68k/fpe/fpu_div.c +++ /dev/null @@ -1,263 +0,0 @@ -/* $OpenBSD: fpu_div.c,v 1.5 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_div.c,v 1.4 2003/08/07 16:28:11 agc Exp $ */ - -/* - * 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 - */ - -/* - * Perform an FPU divide (return x / y). - */ - -#include <sys/types.h> - -#include <machine/reg.h> - -#include <m68k/fpe/fpu_arith.h> -#include <m68k/fpe/fpu_emulate.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, d0, d1, d2, y0, y1, y2; - FPU_DECL_CARRY - - fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */ - - /* - * 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 - */ - 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)); - return (x); - } - - /* all results at this point use XOR of operand signs */ - x->fp_sign ^= y->fp_sign; - if (ISINF(y)) { - x->fp_class = FPC_ZERO; - return (x); - } - if (ISZERO(y)) { - fe->fe_fpsr |= FPSR_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(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(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 <<= 1 -#endif - -#define LOOP /* do ... while (bit >>= 1) */ \ - do { \ - SHL1; \ - SUBTRACT; \ - if (NONNEGATIVE) { \ - q |= bit; \ - r0 = d0, r1 = d1, r2 = d2; \ - } \ - } 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]; - y0 = y->fp_mant[0]; - y1 = y->fp_mant[1]; - y2 = y->fp_mant[2]; - - bit = FP_1; - SUBTRACT; - if (NONNEGATIVE) { - x->fp_exp -= y->fp_exp; - r0 = d0, r1 = d1, r2 = d2; - 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); - x->fp_sticky = r0 | r1 | r2; - - return (x); -} diff --git a/sys/arch/m68k/fpe/fpu_emulate.c b/sys/arch/m68k/fpe/fpu_emulate.c deleted file mode 100644 index daa89da2539..00000000000 --- a/sys/arch/m68k/fpe/fpu_emulate.c +++ /dev/null @@ -1,1166 +0,0 @@ -/* $OpenBSD: fpu_emulate.c,v 1.16 2010/07/20 20:47:17 miod Exp $ */ -/* $NetBSD: fpu_emulate.c,v 1.25 2003/09/22 14:18:34 cl Exp $ */ - -/* - * Copyright (c) 1995 Gordon W. Ross - * some portion Copyright (c) 1995 Ken Nakata - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 4. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Gordon Ross - * - * 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. - */ - -/* - * mc68881 emulator - * XXX - Just a start at it for now... - */ - -#include <sys/types.h> -#include <sys/signal.h> -#include <sys/systm.h> -#include <machine/frame.h> - -#if defined(DDB) && defined(DEBUG_FPE) -#include <machine/db_machdep.h> -#endif - -#include <m68k/fpe/fpu_emulate.h> - -int fpu_emul_fmovmcr(struct fpemu *fe, struct instruction *insn, int *); -int fpu_emul_fmovm(struct fpemu *fe, struct instruction *insn, int *); -int fpu_emul_arith(struct fpemu *fe, struct instruction *insn, int *); -int fpu_emul_type1(struct fpemu *fe, struct instruction *insn, int *); -int fpu_emul_brcc(struct fpemu *fe, struct instruction *insn); -int test_cc(struct fpemu *fe, int pred); -struct fpn *fpu_cmp(struct fpemu *fe); - -#if DEBUG_FPE -# define DUMP_INSN(insn) \ - printf("fpu_emulate: insn={adv=%d,siz=%d,op=%04x,w1=%04x}\n", \ - (insn)->is_advance, (insn)->is_datasize, \ - (insn)->is_opcode, (insn)->is_word1) -#else -# define DUMP_INSN(insn) -#endif - -/* - * Emulate a floating-point instruction. - * Return zero for success, else signal number. - * (Typically: zero, SIGFPE, SIGILL, SIGSEGV) - */ -int -fpu_emulate(struct frame *frame, struct fpframe *fpf, int *typ) -{ - static struct instruction insn; - static struct fpemu fe; - int optype, sig; - u_int16_t word; - - - /* initialize insn.is_datasize to tell it is *not* initialized */ - insn.is_datasize = -1; - - fe.fe_frame = frame; - fe.fe_fpframe = fpf; - fe.fe_fpsr = fpf->fpf_fpsr; - fe.fe_fpcr = fpf->fpf_fpcr; - -#if DEBUG_FPE - printf("ENTERING fpu_emulate: FPSR=%08x, FPCR=%08x\n", - fe.fe_fpsr, fe.fe_fpcr); -#endif - - /* always set this (to avoid a warning) */ - insn.is_pc = frame->f_pc; - insn.is_nextpc = 0; - if (frame->f_format == 4) { - /* - * A format 4 is generated by the 68{EC,LC}040. The PC is - * already set to the instruction following the faulting - * instruction. We need to calculate that, anyway. The - * fslw is the PC of the faulted instruction, which is what - * we expect to be in f_pc. - * - * XXX - This is a hack; it assumes we at least know the - * sizes of all instructions we run across. - * XXX TODO: This may not be true, so we might want to save the PC - * in order to restore it later. - */ - /* insn.is_nextpc = frame->f_pc; */ - insn.is_pc = frame->f_fmt4.f_fslw; - frame->f_pc = insn.is_pc; - } - - if (copyin((void *)insn.is_pc, &word, sizeof(word)) != 0) { -#ifdef DEBUG - printf("fpu_emulate: fault reading opcode\n"); -#endif - return (SIGSEGV); - } - - if ((word & 0xf000) != 0xf000) { -#ifdef DEBUG - printf("fpu_emulate: not coproc. insn.: opcode=0x%x\n", word); -#endif - return (SIGILL); - } - - if ((word & 0x0E00) != 0x0200) { -#ifdef DEBUG - printf("fpu_emulate: bad coproc. id: opcode=0x%x\n", word); -#endif - *typ = ILL_COPROC; - return (SIGILL); - } - - insn.is_opcode = word; - optype = (word & 0x01C0); - - if (copyin((void *)(insn.is_pc + 2), &word, sizeof(word)) != 0) { -#ifdef DEBUG - printf("fpu_emulate: fault reading word1\n"); -#endif - return (SIGSEGV); - } - insn.is_word1 = word; - /* all FPU instructions are at least 4-byte long */ - insn.is_advance = 4; - - DUMP_INSN(&insn); - - /* - * Which family (or type) of opcode is it? - * Tests ordered by likelihood (hopefully). - * Certainly, type 0 is the most common. - */ - if (optype == 0x0000) { - /* type=0: generic */ - if ((word & 0xc000) == 0xc000) { -#if DEBUG_FPE - printf("fpu_emulate: fmovm FPr\n"); -#endif - sig = fpu_emul_fmovm(&fe, &insn, typ); - } else if ((word & 0xc000) == 0x8000) { -#if DEBUG_FPE - printf("fpu_emulate: fmovm FPcr\n"); -#endif - sig = fpu_emul_fmovmcr(&fe, &insn, typ); - } else if ((word & 0xe000) == 0x6000) { - /* fstore = fmove FPn,mem */ -#if DEBUG_FPE - printf("fpu_emulate: fmove to mem\n"); -#endif - sig = fpu_emul_fstore(&fe, &insn, typ); - } else if ((word & 0xfc00) == 0x5c00) { - /* fmovecr */ -#if DEBUG_FPE - printf("fpu_emulate: fmovecr\n"); -#endif - sig = fpu_emul_fmovecr(&fe, &insn, typ); - } else if ((word & 0xa07f) == 0x26) { - /* fscale */ -#if DEBUG_FPE - printf("fpu_emulate: fscale\n"); -#endif - sig = fpu_emul_fscale(&fe, &insn, typ); - } else { -#if DEBUG_FPE - printf("fpu_emulate: other type0\n"); -#endif - /* all other type0 insns are arithmetic */ - sig = fpu_emul_arith(&fe, &insn, typ); - } - if (sig == 0) { -#if DEBUG_FPE - printf("fpu_emulate: type 0 returned 0\n"); -#endif - sig = fpu_upd_excp(&fe); - } - } else if (optype == 0x0080 || optype == 0x00C0) { - /* type=2 or 3: fbcc, short or long disp. */ -#if DEBUG_FPE - printf("fpu_emulate: fbcc %s\n", - (optype & 0x40) ? "long" : "short"); -#endif - sig = fpu_emul_brcc(&fe, &insn); - } else if (optype == 0x0040) { - /* type=1: fdbcc, fscc, ftrapcc */ -#if DEBUG_FPE - printf("fpu_emulate: type1\n"); -#endif - sig = fpu_emul_type1(&fe, &insn, typ); - } else { - /* type=4: fsave (privileged) */ - /* type=5: frestore (privileged) */ - /* type=6: reserved */ - /* type=7: reserved */ -#ifdef DEBUG - printf("fpu_emulate: bad opcode type: opcode=0x%x\n", insn.is_opcode); -#endif - *typ = ILL_PRVOPC; - sig = SIGILL; - } - - DUMP_INSN(&insn); - - /* - * XXX it is not clear to me, if we should progress the PC always, - * for SIGFPE || 0, or only for 0; however, without SIGFPE, we - * don't pass the signalling regression tests. -is - */ - if ((sig == 0) || (sig == SIGFPE)) - frame->f_pc += insn.is_advance; -#if defined(DDB) && defined(DEBUG_FPE) - else { - printf("fpu_emulate: sig=%d, opcode=%x, word1=%x\n", - sig, insn.is_opcode, insn.is_word1); - kdb_trap(-1, (db_regs_t *)frame); - } -#endif -#if 0 /* XXX something is wrong */ - if (frame->f_format == 4) { - /* XXX Restore PC -- 68{EC,LC}040 only */ - if (insn.is_nextpc) - frame->f_pc = insn.is_nextpc; - } -#endif - -#if DEBUG_FPE - printf("EXITING fpu_emulate: w/FPSR=%08x, FPCR=%08x\n", - fe.fe_fpsr, fe.fe_fpcr); -#endif - - if (*typ == 0) - switch (sig) { - case SIGSEGV: - *typ = SEGV_MAPERR; - break; - case SIGILL: - *typ = ILL_ILLOPC; - break; - case SIGFPE: - *typ = FPE_FLTINV; - break; - } - return (sig); -} - -/* update accrued exception bits and see if there's an FP exception */ -int -fpu_upd_excp(fe) - struct fpemu *fe; -{ - u_int fpsr; - u_int fpcr; - - fpsr = fe->fe_fpsr; - fpcr = fe->fe_fpcr; - /* update fpsr accrued exception bits; each insn doesn't have to - update this */ - if (fpsr & (FPSR_BSUN | FPSR_SNAN | FPSR_OPERR)) { - fpsr |= FPSR_AIOP; - } - if (fpsr & FPSR_OVFL) { - fpsr |= FPSR_AOVFL; - } - if ((fpsr & FPSR_UNFL) && (fpsr & FPSR_INEX2)) { - fpsr |= FPSR_AUNFL; - } - if (fpsr & FPSR_DZ) { - fpsr |= FPSR_ADZ; - } - if (fpsr & (FPSR_INEX1 | FPSR_INEX2 | FPSR_OVFL)) { - fpsr |= FPSR_AINEX; - } - - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; - - return (fpsr & fpcr & FPSR_EXCP) ? SIGFPE : 0; -} - -/* update fpsr according to fp (= result of an fp op) */ -u_int -fpu_upd_fpsr(fe, fp) - struct fpemu *fe; - struct fpn *fp; -{ - u_int fpsr; - -#if DEBUG_FPE - printf("fpu_upd_fpsr: previous fpsr=%08x\n", fe->fe_fpsr); -#endif - /* clear all condition code */ - fpsr = fe->fe_fpsr & ~FPSR_CCB; - -#if DEBUG_FPE - printf("fpu_upd_fpsr: result is a "); -#endif - if (fp->fp_sign) { -#if DEBUG_FPE - printf("negative "); -#endif - fpsr |= FPSR_NEG; -#if DEBUG_FPE - } else { - printf("positive "); -#endif - } - - switch (fp->fp_class) { - case FPC_SNAN: -#if DEBUG_FPE - printf("signaling NAN\n"); -#endif - fpsr |= (FPSR_NAN | FPSR_SNAN); - break; - case FPC_QNAN: -#if DEBUG_FPE - printf("quiet NAN\n"); -#endif - fpsr |= FPSR_NAN; - break; - case FPC_ZERO: -#if DEBUG_FPE - printf("Zero\n"); -#endif - fpsr |= FPSR_ZERO; - break; - case FPC_INF: -#if DEBUG_FPE - printf("Inf\n"); -#endif - fpsr |= FPSR_INF; - break; - default: -#if DEBUG_FPE - printf("Number\n"); -#endif - /* anything else is treated as if it is a number */ - break; - } - - fe->fe_fpsr = fe->fe_fpframe->fpf_fpsr = fpsr; - -#if DEBUG_FPE - printf("fpu_upd_fpsr: new fpsr=%08x\n", fe->fe_fpframe->fpf_fpsr); -#endif - - return fpsr; -} - -int -fpu_emul_fmovmcr(struct fpemu *fe, struct instruction *insn, int *typ) -{ - struct frame *frame = fe->fe_frame; - struct fpframe *fpf = fe->fe_fpframe; - int sig; - int reglist; - int fpu_to_mem; - - /* move to/from control registers */ - reglist = (insn->is_word1 & 0x1c00) >> 10; - /* Bit 13 selects direction (FPU to/from Mem) */ - fpu_to_mem = insn->is_word1 & 0x2000; - - insn->is_datasize = 4; - insn->is_advance = 4; - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ); - if (sig) { return sig; } - - if (reglist != 1 && reglist != 2 && reglist != 4 && - (insn->is_ea.ea_flags & EA_DIRECT)) { - /* attempted to copy more than one FPcr to CPU regs */ -#ifdef DEBUG - printf("fpu_emul_fmovmcr: tried to copy too many FPcr\n"); -#endif - return SIGILL; - } - - if (reglist & 4) { - /* fpcr */ - if ((insn->is_ea.ea_flags & EA_DIRECT) && - insn->is_ea.ea_regnum >= 8 /* address reg */) { - /* attempted to copy FPCR to An */ -#ifdef DEBUG - printf("fpu_emul_fmovmcr: tried to copy FPCR from/to A%d\n", - insn->is_ea.ea_regnum & 7); -#endif - return SIGILL; - } - if (fpu_to_mem) { - sig = fpu_store_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpcr); - } else { - sig = fpu_load_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpcr, typ); - } - } - if (sig) { return sig; } - - if (reglist & 2) { - /* fpsr */ - if ((insn->is_ea.ea_flags & EA_DIRECT) && - insn->is_ea.ea_regnum >= 8 /* address reg */) { - /* attempted to copy FPSR to An */ -#ifdef DEBUG - printf("fpu_emul_fmovmcr: tried to copy FPSR from/to A%d\n", - insn->is_ea.ea_regnum & 7); -#endif - return SIGILL; - } - if (fpu_to_mem) { - sig = fpu_store_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpsr); - } else { - sig = fpu_load_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpsr, typ); - } - } - if (sig) { return sig; } - - if (reglist & 1) { - /* fpiar - can be moved to/from An */ - if (fpu_to_mem) { - sig = fpu_store_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpiar); - } else { - sig = fpu_load_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpiar, typ); - } - } - return sig; -} - -/* - * type 0: fmovem - * Separated out of fpu_emul_type0 for efficiency. - * In this function, we know: - * (opcode & 0x01C0) == 0 - * (word1 & 0x8000) == 0x8000 - * - * No conversion or rounding is done by this instruction, - * and the FPSR is not affected. - */ -int -fpu_emul_fmovm(struct fpemu *fe, struct instruction *insn, int *typ) -{ - struct frame *frame = fe->fe_frame; - struct fpframe *fpf = fe->fe_fpframe; - int word1, sig; - int reglist, regmask, regnum; - int fpu_to_mem, order; - int w1_post_incr; - int *fpregs; - - insn->is_advance = 4; - insn->is_datasize = 12; - word1 = insn->is_word1; - - /* Bit 13 selects direction (FPU to/from Mem) */ - fpu_to_mem = word1 & 0x2000; - - /* - * Bits 12,11 select register list mode: - * 0,0: Static reg list, pre-decr. - * 0,1: Dynamic reg list, pre-decr. - * 1,0: Static reg list, post-incr. - * 1,1: Dynamic reg list, post-incr - */ - w1_post_incr = word1 & 0x1000; - if (word1 & 0x0800) { - /* dynamic reg list */ - reglist = frame->f_regs[(word1 & 0x70) >> 4]; - } else { - reglist = word1; - } - reglist &= 0xFF; - - /* Get effective address. (modreg=opcode&077) */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ); - if (sig) { return sig; } - - /* Get address of soft coprocessor regs. */ - fpregs = &fpf->fpf_regs[0]; - - if (insn->is_ea.ea_flags & EA_PREDECR) { - regnum = 7; - order = -1; - } else { - regnum = 0; - order = 1; - } - - regmask = 0x80; - while ((0 <= regnum) && (regnum < 8)) { - if (regmask & reglist) { - if (fpu_to_mem) { - sig = fpu_store_ea(frame, insn, &insn->is_ea, - (char *)&fpregs[regnum * 3]); -#if DEBUG_FPE - printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) saved\n", - regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1], - fpregs[regnum * 3 + 2]); -#endif - } else { /* mem to fpu */ - sig = fpu_load_ea(frame, insn, &insn->is_ea, - (char *)&fpregs[regnum * 3], typ); -#if DEBUG_FPE - printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) loaded\n", - regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1], - fpregs[regnum * 3 + 2]); -#endif - } - if (sig) { break; } - } - regnum += order; - regmask >>= 1; - } - - return sig; -} - -struct fpn * -fpu_cmp(fe) - struct fpemu *fe; -{ - struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2; - - /* take care of special cases */ - if (x->fp_class < 0 || y->fp_class < 0) { - /* if either of two is a SNAN, result is SNAN */ - x->fp_class = (y->fp_class < x->fp_class) ? y->fp_class : x->fp_class; - } else if (x->fp_class == FPC_INF) { - if (y->fp_class == FPC_INF) { - /* both infinities */ - if (x->fp_sign == y->fp_sign) { - x->fp_class = FPC_ZERO; /* return a signed zero */ - } else { - x->fp_class = FPC_NUM; /* return a faked number w/x's sign */ - x->fp_exp = 16383; - x->fp_mant[0] = FP_1; - } - } else { - /* y is a number */ - x->fp_class = FPC_NUM; /* return a forged number w/x's sign */ - x->fp_exp = 16383; - x->fp_mant[0] = FP_1; - } - } else if (y->fp_class == FPC_INF) { - /* x is a Num but y is an Inf */ - /* return a forged number w/y's sign inverted */ - x->fp_class = FPC_NUM; - x->fp_sign = !y->fp_sign; - x->fp_exp = 16383; - x->fp_mant[0] = FP_1; - } else { - /* x and y are both numbers or zeros, or pair of a number and a zero */ - y->fp_sign = !y->fp_sign; - x = fpu_add(fe); /* (x - y) */ - /* - * FCMP does not set Inf bit in CC, so return a forged number - * (value doesn't matter) if Inf is the result of fsub. - */ - if (x->fp_class == FPC_INF) { - x->fp_class = FPC_NUM; - x->fp_exp = 16383; - x->fp_mant[0] = FP_1; - } - } - return x; -} - -/* - * arithmetic operations - */ -int -fpu_emul_arith(struct fpemu *fe, struct instruction *insn, int *typ) -{ - struct frame *frame = fe->fe_frame; - u_int *fpregs = &(fe->fe_fpframe->fpf_regs[0]); - struct fpn *res; - int word1, sig = 0; - int regnum, format; - int discard_result = 0; - u_int buf[3]; -#if DEBUG_FPE - int flags; - char regname; -#endif - - fe->fe_fpsr &= ~FPSR_EXCP; - - DUMP_INSN(insn); - -#if DEBUG_FPE - printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n", - fe->fe_fpsr, fe->fe_fpcr); -#endif - - word1 = insn->is_word1; - format = (word1 >> 10) & 7; - regnum = (word1 >> 7) & 7; - - /* fetch a source operand : may not be used */ -#if DEBUG_FPE - printf("fpu_emul_arith: dst/src FP%d=%08x,%08x,%08x\n", - regnum, fpregs[regnum*3], fpregs[regnum*3+1], - fpregs[regnum*3+2]); -#endif - - fpu_explode(fe, &fe->fe_f1, FTYPE_EXT, &fpregs[regnum * 3]); - - DUMP_INSN(insn); - - /* get the other operand which is always the source */ - if ((word1 & 0x4000) == 0) { -#if DEBUG_FPE - printf("fpu_emul_arith: FP%d op FP%d => FP%d\n", - format, regnum, regnum); - printf("fpu_emul_arith: src opr FP%d=%08x,%08x,%08x\n", - format, fpregs[format*3], fpregs[format*3+1], - fpregs[format*3+2]); -#endif - fpu_explode(fe, &fe->fe_f2, FTYPE_EXT, &fpregs[format * 3]); - } else { - /* the operand is in memory */ - if (format == FTYPE_DBL) { - insn->is_datasize = 8; - } else if (format == FTYPE_SNG || format == FTYPE_LNG) { - insn->is_datasize = 4; - } else if (format == FTYPE_WRD) { - insn->is_datasize = 2; - } else if (format == FTYPE_BYT) { - insn->is_datasize = 1; - } else if (format == FTYPE_EXT) { - insn->is_datasize = 12; - } else { - /* invalid or unsupported operand format */ - *typ = ILL_ILLOPN; - sig = SIGILL; - return sig; - } - - /* Get effective address. (modreg=opcode&077) */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ); - if (sig) { -#if DEBUG_FPE - printf("fpu_emul_arith: error in fpu_decode_ea\n"); -#endif - return sig; - } - - DUMP_INSN(insn); - -#if DEBUG_FPE - printf("fpu_emul_arith: addr mode = "); - flags = insn->is_ea.ea_flags; - regname = (insn->is_ea.ea_regnum & 8) ? 'a' : 'd'; - - if (flags & EA_DIRECT) { - printf("%c%d\n", - regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_PC_REL) { - if (flags & EA_OFFSET) { - printf("pc@(%d)\n", insn->is_ea.ea_offset); - } else if (flags & EA_INDEXED) { - printf("pc@(...)\n"); - } - } else if (flags & EA_PREDECR) { - printf("%c%d@-\n", - regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_POSTINCR) { - printf("%c%d@+\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_OFFSET) { - printf("%c%d@(%d)\n", regname, insn->is_ea.ea_regnum & 7, - insn->is_ea.ea_offset); - } else if (flags & EA_INDEXED) { - printf("%c%d@(...)\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_ABS) { - printf("0x%08x\n", insn->is_ea.ea_absaddr); - } else if (flags & EA_IMMED) { - - printf("#0x%08x,%08x,%08x\n", insn->is_ea.ea_immed[0], - insn->is_ea.ea_immed[1], insn->is_ea.ea_immed[2]); - } else { - printf("%c%d@\n", regname, insn->is_ea.ea_regnum & 7); - } -#endif /* DEBUG_FPE */ - - fpu_load_ea(frame, insn, &insn->is_ea, (char *)buf, typ); - if (format == FTYPE_WRD) { - /* sign-extend */ - buf[0] &= 0xffff; - if (buf[0] & 0x8000) { - buf[0] |= 0xffff0000; - } - format = FTYPE_LNG; - } else if (format == FTYPE_BYT) { - /* sign-extend */ - buf[0] &= 0xff; - if (buf[0] & 0x80) { - buf[0] |= 0xffffff00; - } - format = FTYPE_LNG; - } -#if DEBUG_FPE - printf("fpu_emul_arith: src = %08x %08x %08x, siz = %d\n", - buf[0], buf[1], buf[2], insn->is_datasize); -#endif - fpu_explode(fe, &fe->fe_f2, format, buf); - } - - DUMP_INSN(insn); - - /* An arithmetic instruction emulate function has a prototype of - * struct fpn *fpu_op(struct fpemu *); - - * 1) If the instruction is monadic, then fpu_op() must use - * fe->fe_f2 as its operand, and return a pointer to the - * result. - - * 2) If the instruction is diadic, then fpu_op() must use - * fe->fe_f1 and fe->fe_f2 as its two operands, and return a - * pointer to the result. - - */ - res = 0; - switch (word1 & 0x3f) { - case 0x00: /* fmove */ - res = &fe->fe_f2; - break; - - case 0x01: /* fint */ - res = fpu_int(fe); - break; - - case 0x03: /* fintrz */ - res = fpu_intrz(fe); - break; - - case 0x04: /* fsqrt */ - res = fpu_sqrt(fe); - break; - - case 0x06: /* flognp1 */ - res = fpu_lognp1(fe); - break; - - case 0x14: /* flogn */ - res = fpu_logn(fe); - break; - - case 0x15: /* flog10 */ - res = fpu_log10(fe); - break; - - case 0x16: /* flog2 */ - res = fpu_log2(fe); - break; - - case 0x18: /* fabs */ - fe->fe_f2.fp_sign = 0; - res = &fe->fe_f2; - break; - - case 0x1A: /* fneg */ - fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; - res = &fe->fe_f2; - break; - - case 0x1E: /* fgetexp */ - res = fpu_getexp(fe); - break; - - case 0x1F: /* fgetman */ - res = fpu_getman(fe); - break; - - case 0x20: /* fdiv */ - case 0x24: /* fsgldiv: cheating - better than nothing */ - res = fpu_div(fe); - break; - - case 0x21: /* fmod */ - res = fpu_mod(fe); - break; - - case 0x28: /* fsub */ - fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */ - case 0x22: /* fadd */ - res = fpu_add(fe); - break; - - case 0x23: /* fmul */ - case 0x27: /* fsglmul: cheating - better than nothing */ - res = fpu_mul(fe); - break; - - case 0x25: /* frem */ - res = fpu_rem(fe); - break; - - case 0x26: - /* fscale is handled by a separate function */ - break; - - case 0x38: /* fcmp */ - res = fpu_cmp(fe); - discard_result = 1; - break; - - case 0x3A: /* ftst */ - res = &fe->fe_f2; - discard_result = 1; - break; - - case 0x02: /* fsinh */ - case 0x08: /* fetoxm1 */ - case 0x09: /* ftanh */ - case 0x0A: /* fatan */ - case 0x0C: /* fasin */ - case 0x0D: /* fatanh */ - case 0x0E: /* fsin */ - case 0x0F: /* ftan */ - case 0x10: /* fetox */ - case 0x11: /* ftwotox */ - case 0x12: /* ftentox */ - case 0x19: /* fcosh */ - case 0x1C: /* facos */ - case 0x1D: /* fcos */ - case 0x30: /* fsincos */ - case 0x31: /* fsincos */ - case 0x32: /* fsincos */ - case 0x33: /* fsincos */ - case 0x34: /* fsincos */ - case 0x35: /* fsincos */ - case 0x36: /* fsincos */ - case 0x37: /* fsincos */ - default: -#ifdef DEBUG - printf("fpu_emul_arith: bad opcode=0x%x, word1=0x%x\n", - insn->is_opcode, insn->is_word1); -#endif - sig = SIGILL; - } /* switch (word1 & 0x3f) */ - - if (!discard_result && sig == 0) { - fpu_implode(fe, res, FTYPE_EXT, &fpregs[regnum * 3]); -#if DEBUG_FPE - printf("fpu_emul_arith: %08x,%08x,%08x stored in FP%d\n", - fpregs[regnum*3], fpregs[regnum*3+1], - fpregs[regnum*3+2], regnum); - } else if (sig == 0) { - static char *class_name[] = { "SNAN", "QNAN", "ZERO", "NUM", "INF" }; - printf("fpu_emul_arith: result(%s,%c,%d,%08x,%08x,%08x) discarded\n", - class_name[res->fp_class + 2], - res->fp_sign ? '-' : '+', res->fp_exp, - res->fp_mant[0], res->fp_mant[1], - res->fp_mant[2]); - } else { - printf("fpu_emul_arith: received signal %d\n", sig); -#endif - } - - /* update fpsr according to the result of operation */ - fpu_upd_fpsr(fe, res); - -#if DEBUG_FPE - printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n", - fe->fe_fpsr, fe->fe_fpcr); -#endif - - DUMP_INSN(insn); - - return sig; -} - -/* test condition code according to the predicate in the opcode. - * returns -1 when the predicate evaluates to true, 0 when false. - * signal numbers are returned when an error is detected. - */ -int -test_cc(fe, pred) - struct fpemu *fe; - int pred; -{ - int result, sig_bsun, invert; - int fpsr; - - fpsr = fe->fe_fpsr; - invert = 0; - fpsr &= ~FPSR_EXCP; /* clear all exceptions */ -#if DEBUG_FPE - printf("test_cc: fpsr=0x%08x\n", fpsr); -#endif - pred &= 0x3f; /* lowest 6 bits */ - -#if DEBUG_FPE - printf("test_cc: "); -#endif - - if (pred >= 0x20) { - return SIGILL; - } else if (pred & 0x10) { - /* IEEE nonaware tests */ - sig_bsun = 1; - pred &= 0x0f; /* lower 4 bits */ - } else { - /* IEEE aware tests */ -#if DEBUG_FPE - printf("IEEE "); -#endif - sig_bsun = 0; - } - - if (pred & 0x08) { -#if DEBUG_FPE - printf("Not "); -#endif - /* predicate is "NOT ..." */ - pred ^= 0xf; /* invert */ - invert = -1; - } - switch (pred) { - case 0: /* (Signaling) False */ -#if DEBUG_FPE - printf("False"); -#endif - result = 0; - break; - case 1: /* (Signaling) Equal */ -#if DEBUG_FPE - printf("Equal"); -#endif - result = -((fpsr & FPSR_ZERO) == FPSR_ZERO); - break; - case 2: /* Greater Than */ -#if DEBUG_FPE - printf("GT"); -#endif - result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == 0); - break; - case 3: /* Greater or Equal */ -#if DEBUG_FPE - printf("GE"); -#endif - result = -((fpsr & FPSR_ZERO) || - (fpsr & (FPSR_NAN|FPSR_NEG)) == 0); - break; - case 4: /* Less Than */ -#if DEBUG_FPE - printf("LT"); -#endif - result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == FPSR_NEG); - break; - case 5: /* Less or Equal */ -#if DEBUG_FPE - printf("LE"); -#endif - result = -((fpsr & FPSR_ZERO) || - ((fpsr & (FPSR_NAN|FPSR_NEG)) == FPSR_NEG)); - break; - case 6: /* Greater or Less than */ -#if DEBUG_FPE - printf("GLT"); -#endif - result = -((fpsr & (FPSR_NAN|FPSR_ZERO)) == 0); - break; - case 7: /* Greater, Less or Equal */ -#if DEBUG_FPE - printf("GLE"); -#endif - result = -((fpsr & FPSR_NAN) == 0); - break; - default: - /* invalid predicate */ - return SIGILL; - } - result ^= invert; /* if the predicate is "NOT ...", then - invert the result */ -#if DEBUG_FPE - printf("=> %s (%d)\n", result ? "true" : "false", result); -#endif - /* if it's an IEEE unaware test and NAN is set, BSUN is set */ - if (sig_bsun && (fpsr & FPSR_NAN)) { - fpsr |= FPSR_BSUN; - } - - /* put fpsr back */ - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; - - return result; -} - -/* - * type 1: fdbcc, fscc, ftrapcc - * In this function, we know: - * (opcode & 0x01C0) == 0x0040 - */ -int -fpu_emul_type1(struct fpemu *fe, struct instruction *insn, int *typ) -{ - struct frame *frame = fe->fe_frame; - int advance, sig, branch; - int16_t displ; - - branch = test_cc(fe, insn->is_word1); - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr; - - insn->is_advance = 4; - sig = 0; - - switch (insn->is_opcode & 070) { - case 010: /* fdbcc */ - if (branch == -1) { - /* advance */ - insn->is_advance = 6; - } else if (!branch) { - /* decrement Dn and if (Dn != -1) branch */ - u_int16_t count = frame->f_regs[insn->is_opcode & 7]; - - if (count-- != 0) { - if (copyin((void *)(insn->is_pc + insn->is_advance), &displ, - sizeof(displ)) != 0) { -#ifdef DEBUG - printf("fpu_emul_type1: fault reading displacement\n"); -#endif - return SIGSEGV; - } - insn->is_advance += (int)displ; - /* XXX insn->is_nextpc = insn->is_pc + insn->is_advance; */ - } else { - insn->is_advance = 6; - } - /* write it back */ - frame->f_regs[insn->is_opcode & 7] &= 0xffff0000; - frame->f_regs[insn->is_opcode & 7] |= (u_int32_t)count; - } else { /* got a signal */ - sig = SIGFPE; - } - break; - - case 070: /* ftrapcc or fscc */ - advance = 4; - if ((insn->is_opcode & 07) >= 2) { - switch (insn->is_opcode & 07) { - case 3: /* long opr */ - advance += 2; - case 2: /* word opr */ - advance += 2; - case 4: /* no opr */ - break; - default: - return SIGILL; - break; - } - - if (branch == 0) { - /* no trap */ - insn->is_advance = advance; - sig = 0; - } else { - /* trap */ - sig = SIGILL; - *typ = ILL_ILLTRP; - } - break; - } /* if ((insn->is_opcode & 7) < 2), fall through to FScc */ - - default: /* fscc */ - insn->is_advance = 4; - insn->is_datasize = 1; /* always byte */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ); - if (sig) { - break; - } - if (branch == -1 || branch == 0) { - /* set result */ - sig = fpu_store_ea(frame, insn, &insn->is_ea, (char *)&branch); - } else { - /* got an exception */ - sig = branch; - } - break; - } - return sig; -} - -/* - * Type 2 or 3: fbcc (also fnop) - * In this function, we know: - * (opcode & 0x0180) == 0x0080 - */ -int -fpu_emul_brcc(fe, insn) - struct fpemu *fe; - struct instruction *insn; -{ - int displ; - int sig; - u_int16_t word2; - - /* - * Get branch displacement. - */ - insn->is_advance = 4; - displ = insn->is_word1; - - if (insn->is_opcode & 0x40) { - if (copyin((void *)(insn->is_pc + insn->is_advance), &word2, - sizeof(word2)) != 0) { -#ifdef DEBUG - printf("fpu_emul_brcc: fault reading word2\n"); -#endif - return SIGSEGV; - } - displ <<= 16; - displ |= word2; - insn->is_advance += 2; - } else /* displacement is word sized */ - if (displ & 0x8000) - displ |= 0xFFFF0000; - - /* XXX: If CC, insn->is_pc += displ */ - sig = test_cc(fe, insn->is_opcode); - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr; - - if (fe->fe_fpsr & fe->fe_fpcr & FPSR_EXCP) { - return SIGFPE; /* caught an exception */ - } - if (sig == -1) { - /* branch does take place; 2 is the offset to the 1st disp word */ - insn->is_advance = displ + 2; - /* XXX insn->is_nextpc = insn->is_pc + insn->is_advance; */ - } else if (sig) { - return SIGILL; /* got a signal */ - } -#if DEBUG_FPE - printf("fpu_emul_brcc: %s insn @ %x (%x+%x) (disp=%x)\n", - (sig == -1) ? "BRANCH to" : "NEXT", - insn->is_pc + insn->is_advance, insn->is_pc, insn->is_advance, - displ); -#endif - return 0; -} diff --git a/sys/arch/m68k/fpe/fpu_emulate.h b/sys/arch/m68k/fpe/fpu_emulate.h deleted file mode 100644 index 6b99db93304..00000000000 --- a/sys/arch/m68k/fpe/fpu_emulate.h +++ /dev/null @@ -1,319 +0,0 @@ -/* $OpenBSD: fpu_emulate.h,v 1.7 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_emulate.h,v 1.11 2005/08/13 05:38:45 he Exp $ */ - -/* - * Copyright (c) 1995 Gordon Ross - * Copyright (c) 1995 Ken Nakata - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 4. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Gordon Ross - * - * 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. - */ - -#ifndef _FPU_EMULATE_H_ -#define _FPU_EMULATE_H_ - -#include <sys/types.h> - -/* - * Floating point emulator (tailored for SPARC/modified for m68k, but - * structurally machine-independent). - * - * Floating point numbers are carried around internally in an `expanded' - * or `unpacked' form consisting of: - * - sign - * - unbiased exponent - * - mantissa (`1.' + 80-bit fraction + guard + round) - * - sticky bit - * Any implied `1' bit is inserted, giving a 81-bit mantissa that is - * always nonzero. Additional low-order `guard' and `round' bits are - * scrunched in, making the entire mantissa 83 bits long. This is divided - * into three 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. - */ -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 */ - u_int fp_mant[3]; /* 83-bit mantissa */ -}; - -#define FP_NMANT 83 /* 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_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] */ - -#define CPYFPN(dst, src) \ -if ((dst) != (src)) { \ - (dst)->fp_class = (src)->fp_class; \ - (dst)->fp_sign = (src)->fp_sign; \ - (dst)->fp_exp = (src)->fp_exp; \ - (dst)->fp_sticky = (src)->fp_sticky; \ - (dst)->fp_mant[0] = (src)->fp_mant[0]; \ - (dst)->fp_mant[1] = (src)->fp_mant[1]; \ - (dst)->fp_mant[2] = (src)->fp_mant[2]; \ -} - -/* - * Number classes. Since zero, Inf, and NaN cannot be represented using - * the above layout, we distinguish these from other numbers via a 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 ((u_int)(x)->fp_class > (u_int)(y)->fp_class) \ - SWAP(x, y); \ -} -#define SWAP(x, y) { \ - struct fpn *swap; \ - swap = (x), (x) = (y), (y) = swap; \ -} - -/* - * Emulator state. - */ -struct fpemu { - struct frame *fe_frame; /* integer regs, etc */ - struct fpframe *fe_fpframe; /* FP registers, etc */ - u_int fe_fpsr; /* fpsr copy (modified during op) */ - u_int fe_fpcr; /* fpcr copy */ - struct fpn fe_f1; /* operand 1 */ - struct fpn fe_f2; /* operand 2, if required */ - struct fpn fe_f3; /* available storage for result */ -}; - -/***************************************************************************** - * End of definitions derived from Sparc FPE - *****************************************************************************/ - -/* - * Internal info about a decoded effective address. - */ -struct insn_ea { - int ea_regnum; - int ea_ext[3]; /* extension words if any */ - int ea_flags; /* flags == 0 means mode 2: An@ */ -#define EA_DIRECT 0x001 /* mode [01]: Dn or An */ -#define EA_PREDECR 0x002 /* mode 4: An@- */ -#define EA_POSTINCR 0x004 /* mode 3: An@+ */ -#define EA_OFFSET 0x008 /* mode 5 or (7,2): APC@(d16) */ -#define EA_INDEXED 0x010 /* mode 6 or (7,3): APC@(Xn:*:*,d8) etc */ -#define EA_ABS 0x020 /* mode (7,[01]): abs */ -#define EA_PC_REL 0x040 /* mode (7,[23]): PC@(d16) etc */ -#define EA_IMMED 0x080 /* mode (7,4): #immed */ -#define EA_MEM_INDIR 0x100 /* mode 6 or (7,3): APC@(Xn:*:*,*)@(*) etc */ -#define EA_BASE_SUPPRSS 0x200 /* mode 6 or (7,3): base register suppressed */ -#define EA_FRAME_EA 0x400 /* MC68LC040 only: precalculated EA from - format 4 stack frame */ - int ea_moffs; /* offset used for fmoveMulti */ -}; - -#define ea_offset ea_ext[0] /* mode 5: offset word */ -#define ea_absaddr ea_ext[0] /* mode (7,[01]): absolute address */ -#define ea_immed ea_ext /* mode (7,4): immediate value */ -#define ea_basedisp ea_ext[0] /* mode 6: base displacement */ -#define ea_outerdisp ea_ext[1] /* mode 6: outer displacement */ -#define ea_idxreg ea_ext[2] /* mode 6: index register number */ -#define ea_fea ea_ext[0] /* MC68LC040 only: frame EA */ - -struct instruction { - u_int is_pc; /* insn's address */ - u_int is_nextpc; /* next PC */ - int is_advance; /* length of instruction */ - int is_datasize; /* size of memory operand */ - int is_opcode; /* opcode word */ - int is_word1; /* second word */ - struct insn_ea is_ea; /* decoded effective address mode */ -}; - -/* - * FP data types - */ -#define FTYPE_LNG 0 /* Long Word Integer */ -#define FTYPE_SNG 1 /* Single Prec */ -#define FTYPE_EXT 2 /* Extended Prec */ -#define FTYPE_BCD 3 /* Packed BCD */ -#define FTYPE_WRD 4 /* Word Integer */ -#define FTYPE_DBL 5 /* Double Prec */ -#define FTYPE_BYT 6 /* Byte Integer */ - -/* - * MC68881/68882 FPcr bit definitions (should these go to <m68k/reg.h> - * or <m68k/fpu.h> or something?) - */ - -/* fpsr */ -#define FPSR_CCB 0xff000000 -# define FPSR_NEG 0x08000000 -# define FPSR_ZERO 0x04000000 -# define FPSR_INF 0x02000000 -# define FPSR_NAN 0x01000000 -#define FPSR_QTT 0x00ff0000 -# define FPSR_QSG 0x00800000 -# define FPSR_QUO 0x007f0000 -#define FPSR_EXCP 0x0000ff00 -# define FPSR_BSUN 0x00008000 -# define FPSR_SNAN 0x00004000 -# define FPSR_OPERR 0x00002000 -# define FPSR_OVFL 0x00001000 -# define FPSR_UNFL 0x00000800 -# define FPSR_DZ 0x00000400 -# define FPSR_INEX2 0x00000200 -# define FPSR_INEX1 0x00000100 -#define FPSR_AEX 0x000000ff -# define FPSR_AIOP 0x00000080 -# define FPSR_AOVFL 0x00000040 -# define FPSR_AUNFL 0x00000020 -# define FPSR_ADZ 0x00000010 -# define FPSR_AINEX 0x00000008 - -/* fpcr */ -#define FPCR_EXCP FPSR_EXCP -# define FPCR_BSUN FPSR_BSUN -# define FPCR_SNAN FPSR_SNAN -# define FPCR_OPERR FPSR_OPERR -# define FPCR_OVFL FPSR_OVFL -# define FPCR_UNFL FPSR_UNFL -# define FPCR_DZ FPSR_DZ -# define FPCR_INEX2 FPSR_INEX2 -# define FPCR_INEX1 FPSR_INEX1 -#define FPCR_MODE 0x000000ff -# define FPCR_PREC 0x000000c0 -# define FPCR_EXTD 0x00000000 -# define FPCR_SNGL 0x00000040 -# define FPCR_DBL 0x00000080 -# define FPCR_ROUND 0x00000030 -# define FPCR_NEAR 0x00000000 -# define FPCR_ZERO 0x00000010 -# define FPCR_MINF 0x00000020 -# define FPCR_PINF 0x00000030 - -/* - * Other functions. - */ - -/* Build a new Quiet NaN (sign=0, frac=all 1's). */ -struct fpn *fpu_newnan(struct fpemu *fe); - -/* - * 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(struct fpn *fp, int shr); -/* - * Round a number according to the round mode in FPCR - */ -int fpu_round(struct fpemu *fe, struct fpn *fp); - -/* type conversion */ -void fpu_explode(struct fpemu *fe, struct fpn *fp, int t, u_int *src); -void fpu_implode(struct fpemu *fe, struct fpn *fp, int t, u_int *dst); - -/* - * non-static emulation functions - */ -/* type 0 */ -int fpu_emul_fmovecr(struct fpemu *fe, struct instruction *insn, int *typ); -int fpu_emul_fstore(struct fpemu *fe, struct instruction *insn, int *typ); -int fpu_emul_fscale(struct fpemu *fe, struct instruction *insn, int *typ); - -/* - * include function declarations of those which are called by fpu_emul_arith() - */ -#include <m68k/fpe/fpu_arith_proto.h> - -int fpu_emulate(struct frame *frame, struct fpframe *fpf, int *typ); - -/* - * "helper" functions - */ -/* return values from constant rom */ -struct fpn *fpu_const(struct fpn *fp, u_int offset); -/* update exceptions and FPSR */ -int fpu_upd_excp(struct fpemu *fe); -u_int fpu_upd_fpsr(struct fpemu *fe, struct fpn *fp) ; - -/* address mode decoder, and load/store */ -int fpu_decode_ea(struct frame *frame, struct instruction *insn, - struct insn_ea *ea, int modreg, int *typ); -int fpu_load_ea(struct frame *frame, struct instruction *insn, - struct insn_ea *ea, char *dst, int *typ); -int fpu_store_ea(struct frame *frame, struct instruction *insn, - struct insn_ea *ea, char *src); - -/* fpu_subr.c */ -void fpu_norm(struct fpn *fp); - -#if !defined(FPE_DEBUG) -# define FPE_DEBUG 0 -#endif - -#endif /* _FPU_EMULATE_H_ */ diff --git a/sys/arch/m68k/fpe/fpu_explode.c b/sys/arch/m68k/fpe/fpu_explode.c deleted file mode 100644 index e372d1c7255..00000000000 --- a/sys/arch/m68k/fpe/fpu_explode.c +++ /dev/null @@ -1,280 +0,0 @@ -/* $OpenBSD: fpu_explode.c,v 1.6 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_explode.c,v 1.6 2003/10/23 15:07:30 kleink Exp $ */ - -/* - * 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 - */ - -/* - * FPU subroutines: `explode' the machine's `packed binary' format numbers - * into our internal format. - */ - -#include <sys/types.h> -#include <sys/systm.h> - -#include <machine/ieee.h> -#include <machine/reg.h> - -#include <m68k/fpe/fpu_arith.h> -#include <m68k/fpe/fpu_emulate.h> - - -/* Conversion to internal format -- note asymmetry. */ -int fpu_itof(struct fpn *fp, u_int i); -int fpu_stof(struct fpn *fp, u_int i); -int fpu_dtof(struct fpn *fp, u_int i, u_int j); -int fpu_xtof(struct fpn *fp, u_int i, u_int j, u_int k); - -/* - * 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; - u_int 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; - fp->fp_mant[0] = (int)i < 0 ? -i : i; - fp->fp_mant[1] = 0; - fp->fp_mant[2] = 0; - fpu_norm(fp); - return (FPC_NUM); -} - -#define mask(nbits) ((1 << (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; \ - 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; \ - 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; \ - 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; - u_int i; -{ - int exp; - u_int 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; - u_int i, j; -{ - int exp; - u_int 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); -} - -/* - * 96-bit extended -> fpn. - */ -int -fpu_xtof(fp, i, j, k) - struct fpn *fp; - u_int i, j, k; -{ - int exp; - u_int frac, f0, f1, f2; -#define EXT_SHIFT (EXT_FRACBITS - 1 - 32 - FP_LG) - - exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS); - f0 = j >> EXT_SHIFT; - f1 = (j << (32 - EXT_SHIFT)) | (k >> EXT_SHIFT); - f2 = k << (32 - EXT_SHIFT); - frac = j | k; - - /* m68k extended does not imply denormal by exp==0 */ - if (exp == 0) { - if (frac == 0) - return (FPC_ZERO); - fp->fp_exp = - EXT_EXP_BIAS; - fp->fp_mant[0] = f0; - fp->fp_mant[1] = f1; - fp->fp_mant[2] = f2; - fpu_norm(fp); - return (FPC_NUM); - } - if (exp == (2 * EXT_EXP_BIAS + 1)) { - if (frac == 0) - return (FPC_INF); - fp->fp_mant[0] = f0; - fp->fp_mant[1] = f1; - fp->fp_mant[2] = f2; - return (FPC_QNAN); - } - fp->fp_exp = exp - EXT_EXP_BIAS; - fp->fp_mant[0] = FP_1 | f0; - fp->fp_mant[1] = f1; - fp->fp_mant[2] = f2; - return (FPC_NUM); -} - -/* - * Explode the contents of a memory operand. - */ -void -fpu_explode(fe, fp, type, space) - struct fpemu *fe; - struct fpn *fp; - int type; - u_int *space; -{ - u_int s; - - s = space[0]; - fp->fp_sign = s >> 31; - fp->fp_sticky = 0; - switch (type) { - - case FTYPE_BYT: - s >>= 8; - case FTYPE_WRD: - s >>= 16; - case FTYPE_LNG: - s = fpu_itof(fp, s); - break; - - case FTYPE_SNG: - s = fpu_stof(fp, s); - break; - - case FTYPE_DBL: - s = fpu_dtof(fp, s, space[1]); - break; - - case FTYPE_EXT: - s = fpu_xtof(fp, s, space[1], space[2]); - break; - - default: - panic("fpu_explode"); - } - if (s == 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_fpsr |= FPSR_SNAN; /* assert SNAN exception */ - s = FPC_SNAN; - } - fp->fp_class = s; -} diff --git a/sys/arch/m68k/fpe/fpu_fmovecr.c b/sys/arch/m68k/fpe/fpu_fmovecr.c deleted file mode 100644 index a8392202709..00000000000 --- a/sys/arch/m68k/fpe/fpu_fmovecr.c +++ /dev/null @@ -1,119 +0,0 @@ -/* $OpenBSD: fpu_fmovecr.c,v 1.8 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_fmovecr.c,v 1.10 2003/07/15 02:43:09 lukem Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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. Neither the name of the author 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 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. - * - * @(#)fpu_fmovecr.c 10/8/95 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <machine/frame.h> - -#include <m68k/fpe/fpu_emulate.h> - -/* XXX: quick consistency check */ -#if (FP_1 != 0x40000) -Error you have to change this table when changing the mantissa size -#endif - -static struct fpn constrom[] = { - /* fp_class, fp_sign, fp_exp, fp_sticky, fp_mant[0] ... [2] */ - { FPC_NUM, 0, 1, 0, { 0x6487e, 0xd5110b46, 0x11a80000 } }, - { FPC_NUM, 0, -2, 0, { 0x4d104, 0xd427de7f, 0xbcc00000 } }, - { FPC_NUM, 0, 1, 0, { 0x56fc2, 0xa2c515da, 0x54d00000 } }, - { FPC_NUM, 0, 0, 0, { 0x5c551, 0xd94ae0bf, 0x85e00000 } }, - { FPC_NUM, 0, -2, 0, { 0x6f2de, 0xc549b943, 0x8ca80000 } }, - { FPC_ZERO, 0, 0, 0, { 0x0, 0x0, 0x0 } }, - { FPC_NUM, 0, -1, 0, { 0x58b90, 0xbfbe8e7b, 0xcd600000 } }, - { FPC_NUM, 0, 1, 0, { 0x49aec, 0x6eed5545, 0x60b80000 } }, - { FPC_NUM, 0, 0, 0, { 0x40000, 0x0, 0x0 } }, - { FPC_NUM, 0, 3, 0, { 0x50000, 0x0, 0x0 } }, - { FPC_NUM, 0, 6, 0, { 0x64000, 0x0, 0x0 } }, - { FPC_NUM, 0, 13, 0, { 0x4e200, 0x0, 0x0 } }, - { FPC_NUM, 0, 26, 0, { 0x5f5e1, 0x0, 0x0 } }, - { FPC_NUM, 0, 53, 0, { 0x470de, 0x4df82000, 0x0 } }, - { FPC_NUM, 0, 106, 0, { 0x4ee2d, 0x6d415b85, 0xacf00000 } }, - { FPC_NUM, 0, 212, 0, { 0x613c0, 0xfa4ffe7d, 0x36a80000 } }, - { FPC_NUM, 0, 425, 0, { 0x49dd2, 0x3e4c074c, 0x67000000 } }, - { FPC_NUM, 0, 850, 0, { 0x553f7, 0x5fdcefce, 0xf4700000 } }, - { FPC_NUM, 0, 1700, 0, { 0x718cd, 0x5753074, 0x8e380000 } }, - { FPC_NUM, 0, 3401, 0, { 0x64bb3, 0xac340ba8, 0x60b80000 } }, - { FPC_NUM, 0, 6803, 0, { 0x4f459, 0xdaee29ea, 0xef280000 } }, - { FPC_NUM, 0, 13606, 0, { 0x62302, 0x90145104, 0xbcd80000 } }, -}; - -struct fpn * -fpu_const(fp, offset) - struct fpn *fp; - u_int offset; -{ - struct fpn *r; - -#ifdef DEBUG - if (fp == NULL) { - panic("fpu_const: NULL pointer passed"); - } -#endif - if (offset == 0) { - r = &constrom[0]; - } else if (0xb <= offset && offset <= 0xe) { - r = &constrom[offset - 0xb + 1]; - } else if (0x30 <= offset && offset <= 0x3f) { - r = &constrom[offset - 0x30 + 6]; - } else { - /* return 0.0 for anything else (incl. valid offset 0xf) */ - r = &constrom[5]; - } - - CPYFPN(fp, r); - - return fp; -} - -int -fpu_emul_fmovecr(struct fpemu *fe, struct instruction *insn, int *typ) -{ - int dstreg, offset; - u_int *fpreg; - - dstreg = (insn->is_word1 >> 7) & 0x7; - offset = insn->is_word1 & 0x7F; - fpreg = &(fe->fe_fpframe->fpf_regs[0]); - - (void)fpu_const(&fe->fe_f3, offset); - (void)fpu_upd_fpsr(fe, &fe->fe_f3); - fpu_implode(fe, &fe->fe_f3, FTYPE_EXT, &fpreg[dstreg * 3]); -#if DEBUG_FPE - printf(" fpu_emul_fmovecr: result %08x,%08x,%08x to FP%d\n", - fpreg[dstreg * 3], fpreg[dstreg * 3 + 1], fpreg[dstreg * 3 + 2], - dstreg); -#endif - return 0; -} diff --git a/sys/arch/m68k/fpe/fpu_fscale.c b/sys/arch/m68k/fpe/fpu_fscale.c deleted file mode 100644 index db536ba78ec..00000000000 --- a/sys/arch/m68k/fpe/fpu_fscale.c +++ /dev/null @@ -1,333 +0,0 @@ -/* $OpenBSD: fpu_fscale.c,v 1.8 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_fscale.c,v 1.11 2003/07/15 02:43:10 lukem Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 4. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Gordon Ross - * - * 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. - */ - -/* - * FSCALE - separated from the other type0 arithmetic instructions - * for performance reason; maybe unnecessary, but FSCALE assumes - * the source operand be an integer. It performs type conversion - * only if the source operand is *not* an integer. - */ - -#include <sys/types.h> -#include <sys/signal.h> -#include <sys/systm.h> -#include <machine/frame.h> - -#include <m68k/fpe/fpu_emulate.h> - -int -fpu_emul_fscale(struct fpemu *fe, struct instruction *insn, int *typ) -{ - struct frame *frame; - u_int *fpregs; - int word1, sig; - int regnum, format; - int scale, sign, exp; - u_int m0, m1; - u_int buf[3], fpsr; -#if DEBUG_FPE - int flags; - char regname; -#endif - - scale = sig = 0; - frame = fe->fe_frame; - fpregs = &(fe->fe_fpframe->fpf_regs[0]); - /* clear all exceptions and conditions */ - fpsr = fe->fe_fpsr & ~FPSR_EXCP & ~FPSR_CCB; -#if DEBUG_FPE - printf("fpu_emul_fscale: FPSR = %08x, FPCR = %08x\n", fpsr, fe->fe_fpcr); -#endif - - word1 = insn->is_word1; - format = (word1 >> 10) & 7; - regnum = (word1 >> 7) & 7; - - fe->fe_fpcr &= FPCR_ROUND; - fe->fe_fpcr |= FPCR_ZERO; - - /* get the source operand */ - if ((word1 & 0x4000) == 0) { -#if DEBUG_FPE - printf("fpu_emul_fscale: FP%d op FP%d => FP%d\n", - format, regnum, regnum); - /* the operand is an FP reg */ - printf("fpu_emul_scale: src opr FP%d=%08x%08x%08x\n", - format, fpregs[format*3], fpregs[format*3+1], - fpregs[format*3+2]); -#endif - fpu_explode(fe, &fe->fe_f2, FTYPE_EXT, &fpregs[format * 3]); - fpu_implode(fe, &fe->fe_f2, FTYPE_LNG, buf); - scale = buf[0]; - } else { - /* the operand is in memory */ - if (format == FTYPE_DBL) { - insn->is_datasize = 8; - } else if (format == FTYPE_SNG || format == FTYPE_LNG) { - insn->is_datasize = 4; - } else if (format == FTYPE_WRD) { - insn->is_datasize = 2; - } else if (format == FTYPE_BYT) { - insn->is_datasize = 1; - } else if (format == FTYPE_EXT) { - insn->is_datasize = 12; - } else { - /* invalid or unsupported operand format */ - *typ = ILL_ILLOPN; - sig = SIGILL; - return sig; - } - - /* Get effective address. (modreg=opcode&077) */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ); - if (sig) { -#if DEBUG_FPE - printf("fpu_emul_fscale: error in decode_ea\n"); -#endif - return sig; - } - -#if DEBUG_FPE - printf("fpu_emul_fscale: addr mode = "); - flags = insn->is_ea.ea_flags; - regname = (insn->is_ea.ea_regnum & 8) ? 'a' : 'd'; - - if (flags & EA_DIRECT) { - printf("%c%d\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_PREDECR) { - printf("%c%d@-\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_POSTINCR) { - printf("%c%d@+\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_OFFSET) { - printf("%c%d@(%d)\n", regname, insn->is_ea.ea_regnum & 7, - insn->is_ea.ea_offset); - } else if (flags & EA_INDEXED) { - printf("%c%d@(...)\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_ABS) { - printf("0x%08x\n", insn->is_ea.ea_absaddr); - } else if (flags & EA_PC_REL) { - printf("pc@(%d)\n", insn->is_ea.ea_offset); - } else if (flags & EA_IMMED) { - printf("#0x%08x%08x%08x\n", - insn->is_ea.ea_immed[0], insn->is_ea.ea_immed[1], - insn->is_ea.ea_immed[2]); - } else { - printf("%c%d@\n", regname, insn->is_ea.ea_regnum & 7); - } -#endif - fpu_load_ea(frame, insn, &insn->is_ea, (char *)buf, typ); - -#if DEBUG_FPE - printf("fpu_emul_fscale: src = %08x%08x%08x, siz = %d\n", - buf[0], buf[1], buf[2], insn->is_datasize); -#endif - if (format == FTYPE_LNG) { - /* nothing */ - scale = buf[0]; - } else if (format == FTYPE_WRD) { - /* sign-extend */ - scale = buf[0] & 0xffff; - if (scale & 0x8000) { - scale |= 0xffff0000; - } - } else if (format == FTYPE_BYT) { - /* sign-extend */ - scale = buf[0] & 0xff; - if (scale & 0x80) { - scale |= 0xffffff00; - } - } else if (format == FTYPE_DBL || format == FTYPE_SNG || - format == FTYPE_EXT) { - fpu_explode(fe, &fe->fe_f2, format, buf); - fpu_implode(fe, &fe->fe_f2, FTYPE_LNG, buf); - scale = buf[0]; - } - /* make it look like we've got an FP oprand */ - fe->fe_f2.fp_class = (buf[0] == 0) ? FPC_ZERO : FPC_NUM; - } - - /* assume there's no exception */ - sig = 0; - - /* it's barbaric but we're going to operate directly on - * the dst operand's bit pattern */ - sign = fpregs[regnum * 3] & 0x80000000; - exp = (fpregs[regnum * 3] & 0x7fff0000) >> 16; - m0 = fpregs[regnum * 3 + 1]; - m1 = fpregs[regnum * 3 + 2]; - - switch (fe->fe_f2.fp_class) { - case FPC_SNAN: - fpsr |= FPSR_SNAN; - case FPC_QNAN: - /* dst = NaN */ - exp = 0x7fff; - m0 = m1 = 0xffffffff; - break; - case FPC_ZERO: - case FPC_NUM: - if ((0 < exp && exp < 0x7fff) || - (exp == 0 && (m0 | m1) != 0)) { - /* normal or denormal */ - exp += scale; - if (exp < 0) { - /* underflow */ - u_int grs; /* guard, round and sticky */ - - exp = 0; - grs = m1 << (32 + exp); - m1 = m0 << (32 + exp) | m1 >> -exp; - m0 >>= -exp; - if (grs != 0) { - fpsr |= FPSR_INEX2; - - switch (fe->fe_fpcr & 0x30) { - case FPCR_MINF: - if (sign != 0) { - if (++m1 == 0 && - ++m0 == 0) { - m0 = 0x80000000; - exp++; - } - } - break; - case FPCR_NEAR: - if (grs == 0x80000000) { - /* tie */ - if ((m1 & 1) && - ++m1 == 0 && - ++m0 == 0) { - m0 = 0x80000000; - exp++; - } - } else if (grs & 0x80000000) { - if (++m1 == 0 && - ++m0 == 0) { - m0 = 0x80000000; - exp++; - } - } - break; - case FPCR_PINF: - if (sign == 0) { - if (++m1 == 0 && - ++m0 == 0) { - m0 = 0x80000000; - exp++; - } - } - break; - case FPCR_ZERO: - break; - } - } - if (exp == 0 && (m0 & 0x80000000) == 0) { - fpsr |= FPSR_UNFL; - if ((m0 | m1) == 0) { - fpsr |= FPSR_ZERO; - } - } - } else if (exp >= 0x7fff) { - /* overflow --> result = Inf */ - /* but first, try to normalize in case it's an unnormalized */ - while ((m0 & 0x80000000) == 0) { - exp--; - m0 = (m0 << 1) | (m1 >> 31); - m1 = m1 << 1; - } - /* if it's still too large, then return Inf */ - if (exp >= 0x7fff) { - exp = 0x7fff; - m0 = m1 = 0; - fpsr |= FPSR_OVFL | FPSR_INF; - } - } else if ((m0 & 0x80000000) == 0) { - /* - * it's a denormal; we try to normalize but - * result may and may not be a normal. - */ - while (exp > 0 && (m0 & 0x80000000) == 0) { - exp--; - m0 = (m0 << 1) | (m1 >> 31); - m1 = m1 << 1; - } - if ((m0 & 0x80000000) == 0) { - fpsr |= FPSR_UNFL; - } - } /* exp in range and mantissa normalized */ - } else if (exp == 0 && m0 == 0 && m1 == 0) { - /* dst is Zero */ - fpsr |= FPSR_ZERO; - } /* else we know exp == 0x7fff */ - else if ((m0 | m1) == 0) { - fpsr |= FPSR_INF; - } else if ((m0 & 0x40000000) == 0) { - /* a signaling NaN */ - fpsr |= FPSR_NAN | FPSR_SNAN; - } else { - /* a quiet NaN */ - fpsr |= FPSR_NAN; - } - break; - case FPC_INF: - /* dst = NaN */ - exp = 0x7fff; - m0 = m1 = 0xffffffff; - fpsr |= FPSR_OPERR | FPSR_NAN; - break; - default: -#ifdef DEBUG - panic("fpu_emul_fscale: invalid fp class"); -#endif - break; - } - - /* store the result */ - fpregs[regnum * 3] = sign | (exp << 16); - fpregs[regnum * 3 + 1] = m0; - fpregs[regnum * 3 + 2] = m1; - - if (sign) { - fpsr |= FPSR_NEG; - } - - /* update fpsr according to the result of operation */ - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; - -#if DEBUG_FPE - printf("fpu_emul_fscale: FPSR = %08x, FPCR = %08x\n", - fe->fe_fpsr, fe->fe_fpcr); -#endif - - return (fpsr & fe->fe_fpcr & FPSR_EXCP) ? SIGFPE : sig; -} diff --git a/sys/arch/m68k/fpe/fpu_fstore.c b/sys/arch/m68k/fpe/fpu_fstore.c deleted file mode 100644 index 097d4e57fb1..00000000000 --- a/sys/arch/m68k/fpe/fpu_fstore.c +++ /dev/null @@ -1,132 +0,0 @@ -/* $OpenBSD: fpu_fstore.c,v 1.6 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_fstore.c,v 1.8 2003/07/15 02:43:10 lukem Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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 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/types.h> -#include <sys/signal.h> -#include <sys/systm.h> -#include <machine/frame.h> - -#include <m68k/fpe/fpu_emulate.h> - -/* - * type 0: fmove mem/fpr->fpr - * In this function, we know - * (opcode & 0x01c0) == 0 - * (word1 & 0xe000) == 0x6000 - */ -int -fpu_emul_fstore(struct fpemu *fe, struct instruction *insn, int *typ) -{ - struct frame *frame = fe->fe_frame; - u_int *fpregs = fe->fe_fpframe->fpf_regs; - int word1, sig; - int regnum; - int format; - u_int buf[3]; - -#if DEBUG_FPE - printf(" fpu_emul_fstore: frame at %p fpframe at %p\n", - frame, fe->fe_fpframe); -#endif - - word1 = insn->is_word1; - format = (word1 >> 10) & 7; - regnum = (word1 >> 7) & 7; - - insn->is_advance = 4; - - if (format == FTYPE_DBL) { - insn->is_datasize = 8; - } else if (format == FTYPE_SNG || format == FTYPE_LNG) { - insn->is_datasize = 4; - } else if (format == FTYPE_WRD) { - insn->is_datasize = 2; - format = FTYPE_LNG; - } else if (format == FTYPE_BYT) { - insn->is_datasize = 1; - format = FTYPE_LNG; - } else if (format == FTYPE_EXT) { - insn->is_datasize = 12; - } else { - /* invalid or unsupported operand format */ -#if DEBUG_FPE - printf(" fpu_emul_fstore: invalid format %d\n", format); -#endif - *typ = ILL_ILLOPN; - sig = SIGILL; - } -#if DEBUG_FPE - printf(" fpu_emul_fstore: format %d, size %d\n", - format, insn->is_datasize); -#endif - - fe->fe_fpsr &= ~FPSR_EXCP; - - /* Get effective address. (modreg=opcode&077) */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ); - if (sig) { -#if DEBUG_FPE - printf(" fpu_emul_fstore: failed in decode_ea sig=%d\n", sig); -#endif - return sig; - } - - if (insn->is_datasize > 4 && insn->is_ea.ea_flags == EA_DIRECT) { - /* trying to store dbl or ext into a data register */ -#ifdef DEBUG - printf(" fpu_fstore: attempted to store dbl/ext to reg\n"); -#endif - return SIGILL; - } - -#if DEBUG_FPE - printf(" fpu_emul_fstore: saving FP%d (%08x,%08x,%08x)\n", - regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1], - fpregs[regnum * 3 + 2]); -#endif - fpu_explode(fe, &fe->fe_f3, FTYPE_EXT, &fpregs[regnum * 3]); -#if DEBUG_FPE - { - static char *class_name[] = { "SNAN", "QNAN", "ZERO", "NUM", "INF" }; - printf(" fpu_emul_fstore: fpn (%s,%c,%d,%08x,%08x,%08x)\n", - class_name[fe->fe_f3.fp_class + 2], - fe->fe_f3.fp_sign ? '-' : '+', fe->fe_f3.fp_exp, - fe->fe_f3.fp_mant[0], fe->fe_f3.fp_mant[1], - fe->fe_f3.fp_mant[2]); - } -#endif - fpu_implode(fe, &fe->fe_f3, format, buf); - - fpu_store_ea(frame, insn, &insn->is_ea, (char *)buf); -#if DEBUG_FPE - printf(" fpu_emul_fstore: %08x,%08x,%08x size %d\n", - buf[0], buf[1], buf[2], insn->is_datasize); -#endif - - return 0; -} diff --git a/sys/arch/m68k/fpe/fpu_getexp.c b/sys/arch/m68k/fpe/fpu_getexp.c deleted file mode 100644 index 771de64f826..00000000000 --- a/sys/arch/m68k/fpe/fpu_getexp.c +++ /dev/null @@ -1,77 +0,0 @@ -/* $OpenBSD: fpu_getexp.c,v 1.3 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_getexp.c,v 1.1 1995/11/03 04:47:11 briggs Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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. Neither the name of the author 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 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. - * - * @(#)fpu_getexp.c 10/8/95 - */ - -#include <sys/types.h> - -#include <m68k/fpe/fpu_emulate.h> - -struct fpn * -fpu_getexp(fe) - struct fpemu *fe; -{ - struct fpn *fp = &fe->fe_f2; - - fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */ - - if (fp->fp_class == FPC_INF) { - fp = fpu_newnan(fe); - fe->fe_fpsr |= FPSR_OPERR; - } else if (fp->fp_class == FPC_NUM) { /* a number */ - fpu_explode(fe, &fe->fe_f3, FTYPE_LNG, &fp->fp_exp); - fp = &fe->fe_f3; - } else if (fp->fp_class == FPC_SNAN) { /* signaling NaN */ - fe->fe_fpsr |= FPSR_SNAN; - } /* else if fp == zero or fp == quiet NaN, return itself */ - return fp; -} - -struct fpn * -fpu_getman(fe) - struct fpemu *fe; -{ - struct fpn *fp = &fe->fe_f2; - - fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */ - - if (fp->fp_class == FPC_INF) { - fp = fpu_newnan(fe); - fe->fe_fpsr |= FPSR_OPERR; - } else if (fp->fp_class == FPC_NUM) { /* a number */ - fp->fp_exp = 0; - } else if (fp->fp_class == FPC_SNAN) { /* signaling NaN */ - fe->fe_fpsr |= FPSR_SNAN; - } /* else if fp == zero or fp == quiet NaN, return itself */ - return fp; -} - diff --git a/sys/arch/m68k/fpe/fpu_implode.c b/sys/arch/m68k/fpe/fpu_implode.c deleted file mode 100644 index ddfa8582fa9..00000000000 --- a/sys/arch/m68k/fpe/fpu_implode.c +++ /dev/null @@ -1,488 +0,0 @@ -/* $OpenBSD: fpu_implode.c,v 1.6 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_implode.c,v 1.8 2003/10/23 15:07:30 kleink Exp $ */ - -/* - * 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 - */ - -/* - * FPU subroutines: `implode' internal format numbers into the machine's - * `packed binary' format. - */ - -#include <sys/types.h> -#include <sys/systm.h> - -#include <machine/ieee.h> -#include <machine/reg.h> - -#include <m68k/fpe/fpu_emulate.h> -#include <m68k/fpe/fpu_arith.h> - -/* Conversion from internal format -- note asymmetry. */ -u_int fpu_ftoi(struct fpemu *fe, struct fpn *fp); -u_int fpu_ftos(struct fpemu *fe, struct fpn *fp); -u_int fpu_ftod(struct fpemu *fe, struct fpn *fp, u_int *); -u_int fpu_ftox(struct fpemu *fe, struct fpn *fp, u_int *); - -int toinf(struct fpemu *fe, int sign); - -/* - * 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. - */ -int -fpu_round(struct fpemu *fe, struct fpn *fp) -{ - u_int m0, m1, m2; - int gr, s; - - m0 = fp->fp_mant[0]; - m1 = fp->fp_mant[1]; - m2 = fp->fp_mant[2]; - gr = m2 & 3; - s = fp->fp_sticky; - - /* mant >>= 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_fpsr |= FPSR_INEX2; /* inexact */ - - /* Go to rounddown to round down; break to round up. */ - switch (fe->fe_fpcr & FPCR_ROUND) { - - case FPCR_NEAR: - 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 || (m2 & 1)) - break; - goto rounddown; - - case FPCR_ZERO: - /* Round towards zero, i.e., down. */ - goto rounddown; - - case FPCR_MINF: - /* Round towards -Inf: up if negative, down if positive. */ - if (fp->fp_sign) - break; - goto rounddown; - - case FPCR_PINF: - /* Round towards +Inf: up if positive, down otherwise. */ - if (!fp->fp_sign) - break; - goto rounddown; - } - - /* Bump low bit of mantissa, with carry. */ - if (++m2 == 0 && ++m1 == 0) - m0++; - fp->fp_sticky = 0; - fp->fp_mant[0] = m0; - fp->fp_mant[1] = m1; - fp->fp_mant[2] = m2; - return (1); - -rounddown: - fp->fp_sticky = 0; - fp->fp_mant[0] = m0; - fp->fp_mant[1] = m1; - fp->fp_mant[2] = m2; - 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. - */ -int -toinf(struct fpemu *fe, int sign) -{ - int inf; - - /* look at rounding direction */ - switch (fe->fe_fpcr & FPCR_ROUND) { - - default: - case FPCR_NEAR: /* the nearest value is always Inf */ - inf = 1; - break; - - case FPCR_ZERO: /* toward 0 => never towards Inf */ - inf = 0; - break; - - case FPCR_PINF: /* toward +Inf iff positive */ - inf = (sign == 0); - break; - - case FPCR_MINF: /* 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). - */ -u_int -fpu_ftoi(fe, fp) - struct fpemu *fe; - struct fpn *fp; -{ - u_int 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 fpu_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 - FP_NG - exp) != 0) - /* m68881/2 do not underflow when - converting to integer */; - fpu_round(fe, fp); - i = fp->fp_mant[2]; - if (i >= ((u_int)0x80000000 + sign)) - break; - return (sign ? -i : i); - - default: /* Inf, qNaN, sNaN */ - break; - } - /* overflow: replace any inexact exception with invalid */ - fe->fe_fpsr = (fe->fe_fpsr & ~FPSR_INEX2) | FPSR_OPERR; - return (0x7fffffff + sign); -} - -/* - * fpn -> single (32 bit single returned as return value). - * We assume <= 29 bits in a single-precision fraction (1.f part). - */ -u_int -fpu_ftos(fe, fp) - struct fpemu *fe; - struct fpn *fp; -{ - u_int 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. In the latter case, signal an underflow - * if the result was 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 */ - fe->fe_fpsr |= FPSR_UNFL; - /* -NG for g,r; -SNG_FRACBITS-exp for fraction */ - (void) fpu_shr(fp, FP_NMANT - FP_NG - SNG_FRACBITS - exp); - if (fpu_round(fe, fp) && fp->fp_mant[2] == SNG_EXP(1)) - return (sign | SNG_EXP(1) | 0); - if (fe->fe_fpsr & FPSR_INEX2) - fe->fe_fpsr |= FPSR_UNFL - /* mc68881/2 don't underflow when converting */; - return (sign | SNG_EXP(0) | fp->fp_mant[2]); - } - /* -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[2] & SNG_EXP(1 << FP_NG)) == 0) - panic("fpu_ftos"); -#endif - if (fpu_round(fe, fp) && fp->fp_mant[2] == SNG_EXP(2)) - exp++; - if (exp >= SNG_EXP_INFNAN) { - /* overflow to inf or to max single */ - fe->fe_fpsr |= FPSR_OPERR | FPSR_INEX2 | FPSR_OVFL; - 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[2] & 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. - */ -u_int -fpu_ftod(fe, fp, res) - struct fpemu *fe; - struct fpn *fp; - u_int *res; -{ - u_int 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); - res[1] = 0; - return (sign); - } - if (ISZERO(fp)) { - res[1] = 0; - return (sign); - } - - if ((exp = fp->fp_exp + DBL_EXP_BIAS) <= 0) { - fe->fe_fpsr |= FPSR_UNFL; - (void) fpu_shr(fp, FP_NMANT - FP_NG - DBL_FRACBITS - exp); - if (fpu_round(fe, fp) && fp->fp_mant[1] == DBL_EXP(1)) { - res[1] = 0; - return (sign | DBL_EXP(1) | 0); - } - if (fe->fe_fpsr & FPSR_INEX2) - fe->fe_fpsr |= FPSR_UNFL - /* mc68881/2 don't underflow when converting */; - exp = 0; - goto done; - } - (void) fpu_shr(fp, FP_NMANT - FP_NG - 1 - DBL_FRACBITS); - if (fpu_round(fe, fp) && fp->fp_mant[1] == DBL_EXP(2)) - exp++; - if (exp >= DBL_EXP_INFNAN) { - fe->fe_fpsr |= FPSR_OPERR | FPSR_INEX2 | FPSR_OVFL; - 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) | DBL_MASK); - } -done: - res[1] = fp->fp_mant[2]; - return (sign | DBL_EXP(exp) | (fp->fp_mant[1] & DBL_MASK)); -} - -/* - * fpn -> 68k extended (32 bit high-order result returned; two 32-bit low - * order result left in res[1] & res[2]). Assumes == 64 bits in extended - * precision fraction. - * - * This code mimics fpu_ftos; see it for comments. - */ -u_int -fpu_ftox(fe, fp, res) - struct fpemu *fe; - struct fpn *fp; - u_int *res; -{ - u_int sign = fp->fp_sign << 31; - int exp; - -#define EXT_EXP(e) ((e) << 16) -/* - * on m68k extended prec, significand does not share the same long - * word with exponent - */ -#define EXT_MASK 0 -#define EXT_EXPLICIT1 (1UL << (63 & 31)) -#define EXT_EXPLICIT2 (1UL << (64 & 31)) - - if (ISNAN(fp)) { - (void) fpu_shr(fp, FP_NMANT - EXT_FRACBITS); - exp = EXT_EXP_INFNAN; - goto done; - } - if (ISINF(fp)) { - sign |= EXT_EXP(EXT_EXP_INFNAN); - res[1] = res[2] = 0; - return (sign); - } - if (ISZERO(fp)) { - res[1] = res[2] = 0; - return (sign); - } - - if ((exp = fp->fp_exp + EXT_EXP_BIAS) < 0) { - fe->fe_fpsr |= FPSR_UNFL; - /* I'm not sure about this <=... exp==0 doesn't mean - it's a denormal in extended format */ - (void) fpu_shr(fp, FP_NMANT - FP_NG - EXT_FRACBITS - exp); - if (fpu_round(fe, fp) && fp->fp_mant[1] == EXT_EXPLICIT1) { - res[1] = res[2] = 0; - return (sign | EXT_EXP(1) | 0); - } - if (fe->fe_fpsr & FPSR_INEX2) - fe->fe_fpsr |= FPSR_UNFL - /* mc68881/2 don't underflow */; - exp = 0; - goto done; - } -#if (FP_NMANT - FP_NG - EXT_FRACBITS) > 0 - (void) fpu_shr(fp, FP_NMANT - FP_NG - EXT_FRACBITS); -#endif - if (fpu_round(fe, fp) && fp->fp_mant[0] == EXT_EXPLICIT2) - exp++; - if (exp >= EXT_EXP_INFNAN) { - fe->fe_fpsr |= FPSR_OPERR | FPSR_INEX2 | FPSR_OVFL; - if (toinf(fe, sign)) { - res[1] = res[2] = 0; - return (sign | EXT_EXP(EXT_EXP_INFNAN) | 0); - } - res[1] = res[2] = ~0; - return (sign | EXT_EXP(EXT_EXP_INFNAN) | EXT_MASK); - } -done: - res[1] = fp->fp_mant[1]; - res[2] = fp->fp_mant[2]; - return (sign | EXT_EXP(exp)); -} - -/* - * 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; - u_int *space; -{ - /* XXX Dont delete exceptions set here: fe->fe_fpsr &= ~FPSR_EXCP; */ - - switch (type) { - case FTYPE_LNG: - 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_ftox(fe, fp, space); - break; - - default: - panic("fpu_implode"); - } -} diff --git a/sys/arch/m68k/fpe/fpu_int.c b/sys/arch/m68k/fpe/fpu_int.c deleted file mode 100644 index 42fe85c05cf..00000000000 --- a/sys/arch/m68k/fpe/fpu_int.c +++ /dev/null @@ -1,124 +0,0 @@ -/* $OpenBSD: fpu_int.c,v 1.5 2010/05/10 02:00:50 krw Exp $ */ -/* $NetBSD: fpu_int.c,v 1.6 2003/07/15 02:43:10 lukem Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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. - * - * @(#)fpu_int.c - */ - -#include <sys/types.h> - -#include <machine/reg.h> - -#include <m68k/fpe/fpu_arith.h> -#include <m68k/fpe/fpu_emulate.h> - -/* FINTRZ - always round to zero */ -struct fpn * -fpu_intrz(fe) - struct fpemu *fe; -{ - struct fpn *x = &fe->fe_f2; - int sh, clr, mask, i; - - /* special cases first */ - if (x->fp_class != FPC_NUM) { - return x; - } - /* when |x| < 1.0 */ - if (x->fp_exp < 0) { - x->fp_class = FPC_ZERO; - x->fp_mant[0] = x->fp_mant[1] = x->fp_mant[2] = 0; - return x; - } - - /* real work */ - sh = FP_NMANT - 1 - x->fp_exp; - if (sh <= 0) { - return x; - } - - clr = 2 - sh / 32; - mask = (0xffffffff << (sh % 32)); - - for (i = 2; i > clr; i--) { - x->fp_mant[i] = 0; - } - x->fp_mant[i] &= mask; - - return x; -} - -/* FINT */ -struct fpn * -fpu_int(fe) - struct fpemu *fe; -{ - struct fpn *x = &fe->fe_f2; - int rsh, lsh, wsh, i; - - /* special cases first */ - if (x->fp_class != FPC_NUM) { - return x; - } - /* even if we have exponent == -1, we still have possibility - that the result >= 1.0 when mantissa ~= 1.0 and rounded up */ - if (x->fp_exp < -1) { - x->fp_class = FPC_ZERO; - x->fp_mant[0] = x->fp_mant[1] = x->fp_mant[2] = 0; - return x; - } - - /* real work */ - rsh = FP_NMANT - 1 - x->fp_exp; - if (rsh - FP_NG <= 0) { - return x; - } - - fpu_shr(x, rsh - FP_NG); /* shift to the right */ - - if (fpu_round(fe, x) == 1 /* rounded up */ && - x->fp_mant[2 - (FP_NMANT-rsh)/32] & (1 << ((FP_NMANT-rsh)%32)) - /* x >= 2.0 */) { - rsh--; /* reduce shift count by 1 */ - x->fp_exp++; /* adjust exponent */ - } - - /* shift it back to the left */ - wsh = rsh / 32; - lsh = rsh % 32; - rsh = 32 - lsh; - for (i = 0; i + wsh < 2; i++) { - x->fp_mant[i] = (x->fp_mant[i+wsh] << lsh) | (x->fp_mant[i+wsh+1] >> rsh); - } - x->fp_mant[i] = (x->fp_mant[i+wsh] << lsh); - i++; - for (; i < 3; i++) { - x->fp_mant[i] = 0; - } - - return x; -} diff --git a/sys/arch/m68k/fpe/fpu_log.c b/sys/arch/m68k/fpe/fpu_log.c deleted file mode 100644 index fb31d7d2b5a..00000000000 --- a/sys/arch/m68k/fpe/fpu_log.c +++ /dev/null @@ -1,602 +0,0 @@ -/* $OpenBSD: fpu_log.c,v 1.6 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_log.c,v 1.8 2003/07/15 02:43:10 lukem Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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. Neither the name of the author 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 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. - * - * @(#)fpu_log.c 10/8/95 - */ - -#include <sys/types.h> -#include <sys/systm.h> - -#include <m68k/fpe/fpu_emulate.h> - -static u_int logA6[] = { 0x3FC2499A, 0xB5E4040B }; -static u_int logA5[] = { 0xBFC555B5, 0x848CB7DB }; -static u_int logA4[] = { 0x3FC99999, 0x987D8730 }; -static u_int logA3[] = { 0xBFCFFFFF, 0xFF6F7E97 }; -static u_int logA2[] = { 0x3FD55555, 0x555555A4 }; -static u_int logA1[] = { 0xBFE00000, 0x00000008 }; - -static u_int logB5[] = { 0x3F175496, 0xADD7DAD6 }; -static u_int logB4[] = { 0x3F3C71C2, 0xFE80C7E0 }; -static u_int logB3[] = { 0x3F624924, 0x928BCCFF }; -static u_int logB2[] = { 0x3F899999, 0x999995EC }; -static u_int logB1[] = { 0x3FB55555, 0x55555555 }; - -/* sfpn = shortened fp number; can represent only positive numbers */ -static struct sfpn { - int sp_exp; - u_int sp_m0, sp_m1; -} logtbl[] = { - { 0x3FFE - 0x3fff, 0xFE03F80FU, 0xE03F80FEU }, - { 0x3FF7 - 0x3fff, 0xFF015358U, 0x833C47E2U }, - { 0x3FFE - 0x3fff, 0xFA232CF2U, 0x52138AC0U }, - { 0x3FF9 - 0x3fff, 0xBDC8D83EU, 0xAD88D549U }, - { 0x3FFE - 0x3fff, 0xF6603D98U, 0x0F6603DAU }, - { 0x3FFA - 0x3fff, 0x9CF43DCFU, 0xF5EAFD48U }, - { 0x3FFE - 0x3fff, 0xF2B9D648U, 0x0F2B9D65U }, - { 0x3FFA - 0x3fff, 0xDA16EB88U, 0xCB8DF614U }, - { 0x3FFE - 0x3fff, 0xEF2EB71FU, 0xC4345238U }, - { 0x3FFB - 0x3fff, 0x8B29B775U, 0x1BD70743U }, - { 0x3FFE - 0x3fff, 0xEBBDB2A5U, 0xC1619C8CU }, - { 0x3FFB - 0x3fff, 0xA8D839F8U, 0x30C1FB49U }, - { 0x3FFE - 0x3fff, 0xE865AC7BU, 0x7603A197U }, - { 0x3FFB - 0x3fff, 0xC61A2EB1U, 0x8CD907ADU }, - { 0x3FFE - 0x3fff, 0xE525982AU, 0xF70C880EU }, - { 0x3FFB - 0x3fff, 0xE2F2A47AU, 0xDE3A18AFU }, - { 0x3FFE - 0x3fff, 0xE1FC780EU, 0x1FC780E2U }, - { 0x3FFB - 0x3fff, 0xFF64898EU, 0xDF55D551U }, - { 0x3FFE - 0x3fff, 0xDEE95C4CU, 0xA037BA57U }, - { 0x3FFC - 0x3fff, 0x8DB956A9U, 0x7B3D0148U }, - { 0x3FFE - 0x3fff, 0xDBEB61EEU, 0xD19C5958U }, - { 0x3FFC - 0x3fff, 0x9B8FE100U, 0xF47BA1DEU }, - { 0x3FFE - 0x3fff, 0xD901B203U, 0x6406C80EU }, - { 0x3FFC - 0x3fff, 0xA9372F1DU, 0x0DA1BD17U }, - { 0x3FFE - 0x3fff, 0xD62B80D6U, 0x2B80D62CU }, - { 0x3FFC - 0x3fff, 0xB6B07F38U, 0xCE90E46BU }, - { 0x3FFE - 0x3fff, 0xD3680D36U, 0x80D3680DU }, - { 0x3FFC - 0x3fff, 0xC3FD0329U, 0x06488481U }, - { 0x3FFE - 0x3fff, 0xD0B69FCBU, 0xD2580D0BU }, - { 0x3FFC - 0x3fff, 0xD11DE0FFU, 0x15AB18CAU }, - { 0x3FFE - 0x3fff, 0xCE168A77U, 0x25080CE1U }, - { 0x3FFC - 0x3fff, 0xDE1433A1U, 0x6C66B150U }, - { 0x3FFE - 0x3fff, 0xCB8727C0U, 0x65C393E0U }, - { 0x3FFC - 0x3fff, 0xEAE10B5AU, 0x7DDC8ADDU }, - { 0x3FFE - 0x3fff, 0xC907DA4EU, 0x871146ADU }, - { 0x3FFC - 0x3fff, 0xF7856E5EU, 0xE2C9B291U }, - { 0x3FFE - 0x3fff, 0xC6980C69U, 0x80C6980CU }, - { 0x3FFD - 0x3fff, 0x82012CA5U, 0xA68206D7U }, - { 0x3FFE - 0x3fff, 0xC4372F85U, 0x5D824CA6U }, - { 0x3FFD - 0x3fff, 0x882C5FCDU, 0x7256A8C5U }, - { 0x3FFE - 0x3fff, 0xC1E4BBD5U, 0x95F6E947U }, - { 0x3FFD - 0x3fff, 0x8E44C60BU, 0x4CCFD7DEU }, - { 0x3FFE - 0x3fff, 0xBFA02FE8U, 0x0BFA02FFU }, - { 0x3FFD - 0x3fff, 0x944AD09EU, 0xF4351AF6U }, - { 0x3FFE - 0x3fff, 0xBD691047U, 0x07661AA3U }, - { 0x3FFD - 0x3fff, 0x9A3EECD4U, 0xC3EAA6B2U }, - { 0x3FFE - 0x3fff, 0xBB3EE721U, 0xA54D880CU }, - { 0x3FFD - 0x3fff, 0xA0218434U, 0x353F1DE8U }, - { 0x3FFE - 0x3fff, 0xB92143FAU, 0x36F5E02EU }, - { 0x3FFD - 0x3fff, 0xA5F2FCABU, 0xBBC506DAU }, - { 0x3FFE - 0x3fff, 0xB70FBB5AU, 0x19BE3659U }, - { 0x3FFD - 0x3fff, 0xABB3B8BAU, 0x2AD362A5U }, - { 0x3FFE - 0x3fff, 0xB509E68AU, 0x9B94821FU }, - { 0x3FFD - 0x3fff, 0xB1641795U, 0xCE3CA97BU }, - { 0x3FFE - 0x3fff, 0xB30F6352U, 0x8917C80BU }, - { 0x3FFD - 0x3fff, 0xB7047551U, 0x5D0F1C61U }, - { 0x3FFE - 0x3fff, 0xB11FD3B8U, 0x0B11FD3CU }, - { 0x3FFD - 0x3fff, 0xBC952AFEU, 0xEA3D13E1U }, - { 0x3FFE - 0x3fff, 0xAF3ADDC6U, 0x80AF3ADEU }, - { 0x3FFD - 0x3fff, 0xC2168ED0U, 0xF458BA4AU }, - { 0x3FFE - 0x3fff, 0xAD602B58U, 0x0AD602B6U }, - { 0x3FFD - 0x3fff, 0xC788F439U, 0xB3163BF1U }, - { 0x3FFE - 0x3fff, 0xAB8F69E2U, 0x8359CD11U }, - { 0x3FFD - 0x3fff, 0xCCECAC08U, 0xBF04565DU }, - { 0x3FFE - 0x3fff, 0xA9C84A47U, 0xA07F5638U }, - { 0x3FFD - 0x3fff, 0xD2420487U, 0x2DD85160U }, - { 0x3FFE - 0x3fff, 0xA80A80A8U, 0x0A80A80BU }, - { 0x3FFD - 0x3fff, 0xD7894992U, 0x3BC3588AU }, - { 0x3FFE - 0x3fff, 0xA655C439U, 0x2D7B73A8U }, - { 0x3FFD - 0x3fff, 0xDCC2C4B4U, 0x9887DACCU }, - { 0x3FFE - 0x3fff, 0xA4A9CF1DU, 0x96833751U }, - { 0x3FFD - 0x3fff, 0xE1EEBD3EU, 0x6D6A6B9EU }, - { 0x3FFE - 0x3fff, 0xA3065E3FU, 0xAE7CD0E0U }, - { 0x3FFD - 0x3fff, 0xE70D785CU, 0x2F9F5BDCU }, - { 0x3FFE - 0x3fff, 0xA16B312EU, 0xA8FC377DU }, - { 0x3FFD - 0x3fff, 0xEC1F392CU, 0x5179F283U }, - { 0x3FFE - 0x3fff, 0x9FD809FDU, 0x809FD80AU }, - { 0x3FFD - 0x3fff, 0xF12440D3U, 0xE36130E6U }, - { 0x3FFE - 0x3fff, 0x9E4CAD23U, 0xDD5F3A20U }, - { 0x3FFD - 0x3fff, 0xF61CCE92U, 0x346600BBU }, - { 0x3FFE - 0x3fff, 0x9CC8E160U, 0xC3FB19B9U }, - { 0x3FFD - 0x3fff, 0xFB091FD3U, 0x8145630AU }, - { 0x3FFE - 0x3fff, 0x9B4C6F9EU, 0xF03A3CAAU }, - { 0x3FFD - 0x3fff, 0xFFE97042U, 0xBFA4C2ADU }, - { 0x3FFE - 0x3fff, 0x99D722DAU, 0xBDE58F06U }, - { 0x3FFE - 0x3fff, 0x825EFCEDU, 0x49369330U }, - { 0x3FFE - 0x3fff, 0x9868C809U, 0x868C8098U }, - { 0x3FFE - 0x3fff, 0x84C37A7AU, 0xB9A905C9U }, - { 0x3FFE - 0x3fff, 0x97012E02U, 0x5C04B809U }, - { 0x3FFE - 0x3fff, 0x87224C2EU, 0x8E645FB7U }, - { 0x3FFE - 0x3fff, 0x95A02568U, 0x095A0257U }, - { 0x3FFE - 0x3fff, 0x897B8CACU, 0x9F7DE298U }, - { 0x3FFE - 0x3fff, 0x94458094U, 0x45809446U }, - { 0x3FFE - 0x3fff, 0x8BCF55DEU, 0xC4CD05FEU }, - { 0x3FFE - 0x3fff, 0x92F11384U, 0x0497889CU }, - { 0x3FFE - 0x3fff, 0x8E1DC0FBU, 0x89E125E5U }, - { 0x3FFE - 0x3fff, 0x91A2B3C4U, 0xD5E6F809U }, - { 0x3FFE - 0x3fff, 0x9066E68CU, 0x955B6C9BU }, - { 0x3FFE - 0x3fff, 0x905A3863U, 0x3E06C43BU }, - { 0x3FFE - 0x3fff, 0x92AADE74U, 0xC7BE59E0U }, - { 0x3FFE - 0x3fff, 0x8F1779D9U, 0xFDC3A219U }, - { 0x3FFE - 0x3fff, 0x94E9BFF6U, 0x15845643U }, - { 0x3FFE - 0x3fff, 0x8DDA5202U, 0x37694809U }, - { 0x3FFE - 0x3fff, 0x9723A1B7U, 0x20134203U }, - { 0x3FFE - 0x3fff, 0x8CA29C04U, 0x6514E023U }, - { 0x3FFE - 0x3fff, 0x995899C8U, 0x90EB8990U }, - { 0x3FFE - 0x3fff, 0x8B70344AU, 0x139BC75AU }, - { 0x3FFE - 0x3fff, 0x9B88BDAAU, 0x3A3DAE2FU }, - { 0x3FFE - 0x3fff, 0x8A42F870U, 0x5669DB46U }, - { 0x3FFE - 0x3fff, 0x9DB4224FU, 0xFFE1157CU }, - { 0x3FFE - 0x3fff, 0x891AC73AU, 0xE9819B50U }, - { 0x3FFE - 0x3fff, 0x9FDADC26U, 0x8B7A12DAU }, - { 0x3FFE - 0x3fff, 0x87F78087U, 0xF78087F8U }, - { 0x3FFE - 0x3fff, 0xA1FCFF17U, 0xCE733BD4U }, - { 0x3FFE - 0x3fff, 0x86D90544U, 0x7A34ACC6U }, - { 0x3FFE - 0x3fff, 0xA41A9E8FU, 0x5446FB9FU }, - { 0x3FFE - 0x3fff, 0x85BF3761U, 0x2CEE3C9BU }, - { 0x3FFE - 0x3fff, 0xA633CD7EU, 0x6771CD8BU }, - { 0x3FFE - 0x3fff, 0x84A9F9C8U, 0x084A9F9DU }, - { 0x3FFE - 0x3fff, 0xA8489E60U, 0x0B435A5EU }, - { 0x3FFE - 0x3fff, 0x83993052U, 0x3FBE3368U }, - { 0x3FFE - 0x3fff, 0xAA59233CU, 0xCCA4BD49U }, - { 0x3FFE - 0x3fff, 0x828CBFBEU, 0xB9A020A3U }, - { 0x3FFE - 0x3fff, 0xAC656DAEU, 0x6BCC4985U }, - { 0x3FFE - 0x3fff, 0x81848DA8U, 0xFAF0D277U }, - { 0x3FFE - 0x3fff, 0xAE6D8EE3U, 0x60BB2468U }, - { 0x3FFE - 0x3fff, 0x80808080U, 0x80808081U }, - { 0x3FFE - 0x3fff, 0xB07197A2U, 0x3C46C654U }, -}; - -struct fpn *__fpu_logn(struct fpemu *fe); - -/* - * natural log - algorithm taken from Motorola FPSP, - * except this doesn't bother to check for invalid input. - */ -struct fpn * -__fpu_logn(fe) - struct fpemu *fe; -{ - static struct fpn X, F, U, V, W, KLOG2; - struct fpn *d; - int i, k; - - CPYFPN(&X, &fe->fe_f2); - - /* see if |X-1| < 1/16 approx. */ - if ((-1 == X.fp_exp && (0xf07d0000U >> (31 - FP_LG)) <= X.fp_mant[0]) || - (0 == X.fp_exp && X.fp_mant[0] <= (0x88410000U >> (31 - FP_LG)))) { - /* log near 1 */ -#if FPE_DEBUG - printf("__fpu_logn: log near 1\n"); -#endif - - fpu_const(&fe->fe_f1, 0x32); - /* X+1 */ - d = fpu_add(fe); - CPYFPN(&V, d); - - CPYFPN(&fe->fe_f1, &X); - fpu_const(&fe->fe_f2, 0x32); /* 1.0 */ - fe->fe_f2.fp_sign = 1; /* -1.0 */ - /* X-1 */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - /* 2(X-1) */ - fe->fe_f1.fp_exp++; /* *= 2 */ - CPYFPN(&fe->fe_f2, &V); - /* U=2(X-1)/(X+1) */ - d = fpu_div(fe); - CPYFPN(&U, d); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, d); - /* V=U*U */ - d = fpu_mul(fe); - CPYFPN(&V, d); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, d); - /* W=V*V */ - d = fpu_mul(fe); - CPYFPN(&W, d); - - /* calculate U+U*V*([B1+W*(B3+W*B5)]+[V*(B2+W*B4)]) */ - - /* B1+W*(B3+W*B5) part */ - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logB5); - /* W*B5 */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logB3); - /* B3+W*B5 */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &W); - /* W*(B3+W*B5) */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logB1); - /* B1+W*(B3+W*B5) */ - d = fpu_add(fe); - CPYFPN(&X, d); - - /* [V*(B2+W*B4)] part */ - CPYFPN(&fe->fe_f1, &W); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logB4); - /* W*B4 */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logB2); - /* B2+W*B4 */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &V); - /* V*(B2+W*B4) */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &X); - /* B1+W*(B3+W*B5)+V*(B2+W*B4) */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &V); - /* V*(B1+W*(B3+W*B5)+V*(B2+W*B4)) */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &U); - /* U*V*(B1+W*(B3+W*B5)+V*(B2+W*B4)) */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &U); - /* U+U*V*(B1+W*(B3+W*B5)+V*(B2+W*B4)) */ - d = fpu_add(fe); - } else /* the usual case */ { -#if FPE_DEBUG - printf("__fpu_logn: the usual case. X=(%d,%08x,%08x...)\n", - X.fp_exp, X.fp_mant[0], X.fp_mant[1]); -#endif - - k = X.fp_exp; - /* X <- Y */ - X.fp_exp = fe->fe_f2.fp_exp = 0; - - /* get the most significant 7 bits of X */ - F.fp_class = FPC_NUM; - F.fp_sign = 0; - F.fp_exp = X.fp_exp; - F.fp_mant[0] = X.fp_mant[0] & (0xfe000000U >> (31 - FP_LG)); - F.fp_mant[0] |= (0x01000000U >> (31 - FP_LG)); - F.fp_mant[1] = F.fp_mant[2] = 0; - F.fp_sticky = 0; - -#if FPE_DEBUG - printf("__fpu_logn: X=Y*2^k=(%d,%08x,%08x...)*2^%d\n", - fe->fe_f2.fp_exp, fe->fe_f2.fp_mant[0], - fe->fe_f2.fp_mant[1], k); - printf("__fpu_logn: F=(%d,%08x,%08x...)\n", - F.fp_exp, F.fp_mant[0], F.fp_mant[1]); -#endif - - /* index to the table */ - i = (F.fp_mant[0] >> (FP_LG - 7)) & 0x7e; - -#if FPE_DEBUG - printf("__fpu_logn: index to logtbl i=%d(%x)\n", i, i); -#endif - - CPYFPN(&fe->fe_f1, &F); - /* -F */ - fe->fe_f1.fp_sign = 1; - /* Y-F */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - - /* fe_f2 = 1/F */ - fe->fe_f2.fp_class = FPC_NUM; - fe->fe_f2.fp_sign = fe->fe_f2.fp_sticky = fe->fe_f2.fp_mant[2] = 0; - fe->fe_f2.fp_exp = logtbl[i].sp_exp; - fe->fe_f2.fp_mant[0] = (logtbl[i].sp_m0 >> (31 - FP_LG)); - fe->fe_f2.fp_mant[1] = (logtbl[i].sp_m0 << (FP_LG + 1)) | - (logtbl[i].sp_m1 >> (31 - FP_LG)); - fe->fe_f2.fp_mant[2] = (u_int)(logtbl[i].sp_m1 << (FP_LG + 1)); - -#if FPE_DEBUG - printf("__fpu_logn: 1/F=(%d,%08x,%08x...)\n", fe->fe_f2.fp_exp, - fe->fe_f2.fp_mant[0], fe->fe_f2.fp_mant[1]); -#endif - - /* U = (Y-F) * (1/F) */ - d = fpu_mul(fe); - CPYFPN(&U, d); - - /* KLOG2 = K * ln(2) */ - /* fe_f1 == (fpn)k */ - fpu_explode(fe, &fe->fe_f1, FTYPE_LNG, &k); - (void)fpu_const(&fe->fe_f2, 0x30 /* ln(2) */); -#if FPE_DEBUG - printf("__fpu_logn: fp(k)=(%d,%08x,%08x...)\n", fe->fe_f1.fp_exp, - fe->fe_f1.fp_mant[0], fe->fe_f1.fp_mant[1]); - printf("__fpu_logn: ln(2)=(%d,%08x,%08x...)\n", fe->fe_f2.fp_exp, - fe->fe_f2.fp_mant[0], fe->fe_f2.fp_mant[1]); -#endif - /* K * LOGOF2 */ - d = fpu_mul(fe); - CPYFPN(&KLOG2, d); - - /* V=U*U */ - CPYFPN(&fe->fe_f1, &U); - CPYFPN(&fe->fe_f2, &U); - d = fpu_mul(fe); - CPYFPN(&V, d); - - /* - * approximation of LOG(1+U) by - * (U+V*(A1+V*(A3+V*A5)))+(U*V*(A2+V*(A4+V*A6))) - */ - - /* (U+V*(A1+V*(A3+V*A5))) part */ - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logA5); - /* V*A5 */ - d = fpu_mul(fe); - - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logA3); - /* A3+V*A5 */ - d = fpu_add(fe); - - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &V); - /* V*(A3+V*A5) */ - d = fpu_mul(fe); - - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logA1); - /* A1+V*(A3+V*A5) */ - d = fpu_add(fe); - - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &V); - /* V*(A1+V*(A3+V*A5)) */ - d = fpu_mul(fe); - - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &U); - /* U+V*(A1+V*(A3+V*A5)) */ - d = fpu_add(fe); - - CPYFPN(&X, d); - - /* (U*V*(A2+V*(A4+V*A6))) part */ - CPYFPN(&fe->fe_f1, &V); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logA6); - /* V*A6 */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logA4); - /* A4+V*A6 */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &V); - /* V*(A4+V*A6) */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - fpu_explode(fe, &fe->fe_f2, FTYPE_DBL, logA2); - /* A2+V*(A4+V*A6) */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &V); - /* V*(A2+V*(A4+V*A6)) */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &U); - /* U*V*(A2+V*(A4+V*A6)) */ - d = fpu_mul(fe); - CPYFPN(&fe->fe_f1, d); - i++; - /* fe_f2 = logtbl[i+1] (== LOG(F)) */ - fe->fe_f2.fp_class = FPC_NUM; - fe->fe_f2.fp_sign = fe->fe_f2.fp_sticky = fe->fe_f2.fp_mant[2] = 0; - fe->fe_f2.fp_exp = logtbl[i].sp_exp; - fe->fe_f2.fp_mant[0] = (logtbl[i].sp_m0 >> (31 - FP_LG)); - fe->fe_f2.fp_mant[1] = (logtbl[i].sp_m0 << (FP_LG + 1)) | - (logtbl[i].sp_m1 >> (31 - FP_LG)); - fe->fe_f2.fp_mant[2] = (logtbl[i].sp_m1 << (FP_LG + 1)); - -#if FPE_DEBUG - printf("__fpu_logn: ln(F)=(%d,%08x,%08x,...)\n", fe->fe_f2.fp_exp, - fe->fe_f2.fp_mant[0], fe->fe_f2.fp_mant[1]); -#endif - - /* LOG(F)+U*V*(A2+V*(A4+V*A6)) */ - d = fpu_add(fe); - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &X); - /* LOG(F)+U+V*(A1+V*(A3+V*A5))+U*V*(A2+V*(A4+V*A6)) */ - d = fpu_add(fe); - -#if FPE_DEBUG - printf("__fpu_logn: ln(Y)=(%c,%d,%08x,%08x,%08x)\n", - d->fp_sign ? '-' : '+', d->fp_exp, - d->fp_mant[0], d->fp_mant[1], d->fp_mant[2]); -#endif - - CPYFPN(&fe->fe_f1, d); - CPYFPN(&fe->fe_f2, &KLOG2); - /* K*LOGOF2+LOG(F)+U+V*(A1+V*(A3+V*A5))+U*V*(A2+V*(A4+V*A6)) */ - d = fpu_add(fe); - } - - return d; -} - -struct fpn * -fpu_log10(fe) - struct fpemu *fe; -{ - struct fpn *fp = &fe->fe_f2; - u_int fpsr; - - fpsr = fe->fe_fpsr & ~FPSR_EXCP; /* clear all exceptions */ - - if (fp->fp_class >= FPC_NUM) { - if (fp->fp_sign) { /* negative number or Inf */ - fp = fpu_newnan(fe); - fpsr |= FPSR_OPERR; - } else if (fp->fp_class == FPC_NUM) { - /* the real work here */ - fp = __fpu_logn(fe); - if (fp != &fe->fe_f1) - CPYFPN(&fe->fe_f1, fp); - (void)fpu_const(&fe->fe_f2, 0x31 /* ln(10) */); - fp = fpu_div(fe); - } /* else if fp == +Inf, return +Inf */ - } else if (fp->fp_class == FPC_ZERO) { - /* return -Inf */ - fp->fp_class = FPC_INF; - fp->fp_sign = 1; - fpsr |= FPSR_DZ; - } else if (fp->fp_class == FPC_SNAN) { - fpsr |= FPSR_SNAN; - fp = fpu_newnan(fe); - } else { - fp = fpu_newnan(fe); - } - - fe->fe_fpsr = fpsr; - - return fp; -} - -struct fpn * -fpu_log2(fe) - struct fpemu *fe; -{ - struct fpn *fp = &fe->fe_f2; - u_int fpsr; - - fpsr = fe->fe_fpsr & ~FPSR_EXCP; /* clear all exceptions */ - - if (fp->fp_class >= FPC_NUM) { - if (fp->fp_sign) { /* negative number or Inf */ - fp = fpu_newnan(fe); - fpsr |= FPSR_OPERR; - } else if (fp->fp_class == FPC_NUM) { - /* the real work here */ - if (fp->fp_mant[0] == FP_1 && fp->fp_mant[1] == 0 && - fp->fp_mant[2] == 0) { - /* fp == 2.0 ^ exp <--> log2(fp) == exp */ - fpu_explode(fe, &fe->fe_f3, FTYPE_LNG, &fp->fp_exp); - fp = &fe->fe_f3; - } else { - fp = __fpu_logn(fe); - if (fp != &fe->fe_f1) - CPYFPN(&fe->fe_f1, fp); - (void)fpu_const(&fe->fe_f2, 0x30 /* ln(2) */); - fp = fpu_div(fe); - } - } /* else if fp == +Inf, return +Inf */ - } else if (fp->fp_class == FPC_ZERO) { - /* return -Inf */ - fp->fp_class = FPC_INF; - fp->fp_sign = 1; - fpsr |= FPSR_DZ; - } else if (fp->fp_class == FPC_SNAN) { - fpsr |= FPSR_SNAN; - fp = fpu_newnan(fe); - } else { - fp = fpu_newnan(fe); - } - - fe->fe_fpsr = fpsr; - return fp; -} - -struct fpn * -fpu_logn(fe) - struct fpemu *fe; -{ - struct fpn *fp = &fe->fe_f2; - u_int fpsr; - - fpsr = fe->fe_fpsr & ~FPSR_EXCP; /* clear all exceptions */ - - if (fp->fp_class >= FPC_NUM) { - if (fp->fp_sign) { /* negative number or Inf */ - fp = fpu_newnan(fe); - fpsr |= FPSR_OPERR; - } else if (fp->fp_class == FPC_NUM) { - /* the real work here */ - fp = __fpu_logn(fe); - } /* else if fp == +Inf, return +Inf */ - } else if (fp->fp_class == FPC_ZERO) { - /* return -Inf */ - fp->fp_class = FPC_INF; - fp->fp_sign = 1; - fpsr |= FPSR_DZ; - } else if (fp->fp_class == FPC_SNAN) { - fpsr |= FPSR_SNAN; - fp = fpu_newnan(fe); - } else { - fp = fpu_newnan(fe); - } - - fe->fe_fpsr = fpsr; - - return fp; -} - -struct fpn * -fpu_lognp1(fe) - struct fpemu *fe; -{ - struct fpn *fp; - - /* build a 1.0 */ - fp = fpu_const(&fe->fe_f1, 0x32); /* get 1.0 */ - /* fp = 1.0 + f2 */ - fp = fpu_add(fe); - - /* copy the result to the src opr */ - if (&fe->fe_f2 != fp) - CPYFPN(&fe->fe_f2, fp); - - return fpu_logn(fe); -} diff --git a/sys/arch/m68k/fpe/fpu_mul.c b/sys/arch/m68k/fpe/fpu_mul.c deleted file mode 100644 index e1027ad4f4c..00000000000 --- a/sys/arch/m68k/fpe/fpu_mul.c +++ /dev/null @@ -1,212 +0,0 @@ -/* $OpenBSD: fpu_mul.c,v 1.5 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_mul.c,v 1.4 2003/08/07 16:28:11 agc Exp $ */ - -/* - * 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 - */ - -/* - * Perform an FPU multiply (return x * y). - */ - -#include <sys/types.h> - -#include <machine/reg.h> - -#include <m68k/fpe/fpu_arith.h> -#include <m68k/fpe/fpu_emulate.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 variables in the hope that this may be 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 a2, a1, a0, 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)) { - y->fp_sign ^= x->fp_sign; - 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. - */ - x2 = x->fp_mant[2]; - x1 = x->fp_mant[1]; - x0 = x->fp_mant[0]; - sticky = a2 = a1 = a0 = 0; - -#define ADD /* A += X */ \ - FPU_ADDS(a2, a2, x2); \ - FPU_ADDCS(a1, a1, x1); \ - FPU_ADDC(a0, a0, x0) - -#define SHR1 /* A >>= 1, with sticky */ \ - sticky |= a2 & 1, \ - a2 = (a2 >> 1) | (a1 << 31), a1 = (a1 >> 1) | (a0 << 31), a0 >>= 1 - -#define SHR32 /* A >>= 32, with sticky */ \ - sticky |= 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[2]) == 0) { - /* SHR32; */ /* unneeded since A==0 */ - } else { - bit = 1 << FP_NG; - 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[2] = a2; - x->fp_mant[1] = a1; - x->fp_mant[0] = a0; - return (x); -} diff --git a/sys/arch/m68k/fpe/fpu_rem.c b/sys/arch/m68k/fpe/fpu_rem.c deleted file mode 100644 index 5e8d76b4c39..00000000000 --- a/sys/arch/m68k/fpe/fpu_rem.c +++ /dev/null @@ -1,232 +0,0 @@ -/* $OpenBSD: fpu_rem.c,v 1.5 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_rem.c,v 1.5 2003/07/15 02:43:10 lukem Exp $ */ - -/* - * Copyright (c) 1995 Ken Nakata - * 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. Neither the name of the author 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 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. - * - * @(#)fpu_rem.c 10/24/95 - */ - -#include <sys/types.h> -#include <sys/signal.h> -#include <machine/frame.h> - -#include <m68k/fpe/fpu_emulate.h> - -/* - * ALGORITHM - * - * Step 1. Save and strip signs of X and Y: signX := sign(X), - * signY := sign(Y), X := *X*, Y := *Y*, - * signQ := signX EOR signY. Record whether MOD or REM - * is requested. - * - * Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0. - * If (L < 0) then - * R := X, go to Step 4. - * else - * R := 2^(-L)X, j := L. - * endif - * - * Step 3. Perform MOD(X,Y) - * 3.1 If R = Y, go to Step 9. - * 3.2 If R > Y, then { R := R - Y, Q := Q + 1} - * 3.3 If j = 0, go to Step 4. - * 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to - * Step 3.1. - * - * Step 4. At this point, R = X - QY = MOD(X,Y). Set - * Last_Subtract := false (used in Step 7 below). If - * MOD is requested, go to Step 6. - * - * Step 5. R = MOD(X,Y), but REM(X,Y) is requested. - * 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to - * Step 6. - * 5.2 If R > Y/2, then { set Last_Subtract := true, - * Q := Q + 1, Y := signY*Y }. Go to Step 6. - * 5.3 This is the tricky case of R = Y/2. If Q is odd, - * then { Q := Q + 1, signX := -signX }. - * - * Step 6. R := signX*R. - * - * Step 7. If Last_Subtract = true, R := R - Y. - * - * Step 8. Return signQ, last 7 bits of Q, and R as required. - * - * Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus, - * X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1), - * R := 0. Return signQ, last 7 bits of Q, and R. - */ - -struct fpn *__fpu_modrem(struct fpemu *fe, int modrem); - -struct fpn * -__fpu_modrem(fe, modrem) - struct fpemu *fe; - int modrem; -{ - static struct fpn X, Y; - struct fpn *x, *y, *r; - u_int signX, signY, signQ; - int j, k, l, q; - int Last_Subtract; - - CPYFPN(&X, &fe->fe_f1); - CPYFPN(&Y, &fe->fe_f2); - x = &X; - y = &Y; - r = &fe->fe_f2; - - /* - * Step 1 - */ - signX = x->fp_sign; - signY = y->fp_sign; - signQ = (signX ^ signY); - x->fp_sign = y->fp_sign = 0; - - /* - * Step 2 - */ - l = x->fp_exp - y->fp_exp; - k = 0; - q = 0; - if (l >= 0) { - CPYFPN(r, x); - r->fp_exp -= l; - j = l; - - /* - * Step 3 - */ - while (y->fp_exp != r->fp_exp || y->fp_mant[0] != r->fp_mant[0] || - y->fp_mant[1] != r->fp_mant[1] || - y->fp_mant[2] != r->fp_mant[2]) { - - /* Step 3.2 */ - if (y->fp_exp < r->fp_exp || y->fp_mant[0] < r->fp_mant[0] || - y->fp_mant[1] < r->fp_mant[1] || - y->fp_mant[2] < r->fp_mant[2]) { - CPYFPN(&fe->fe_f1, r); - CPYFPN(&fe->fe_f2, y); - fe->fe_f2.fp_sign = 1; - r = fpu_add(fe); - q++; - } - - /* Step 3.3 */ - if (j == 0) - goto Step4; - - /* Step 3.4 */ - k++; - j--; - q += q; - r->fp_exp++; - } - /* Step 9 */ - goto Step9; - } - Step4: - Last_Subtract = 0; - if (modrem == 0) - goto Step6; - - /* - * Step 5 - */ - /* Step 5.1 */ - if (r->fp_exp + 1 < y->fp_exp || - (r->fp_exp + 1 == y->fp_exp && - (r->fp_mant[0] < y->fp_mant[0] || r->fp_mant[1] < y->fp_mant[1] || - r->fp_mant[2] < y->fp_mant[2]))) - /* if r < y/2 */ - goto Step6; - /* Step 5.2 */ - if (r->fp_exp + 1 != y->fp_exp || - r->fp_mant[0] != y->fp_mant[0] || r->fp_mant[1] != y->fp_mant[1] || - r->fp_mant[2] != y->fp_mant[2]) { - /* if (!(r < y/2) && !(r == y/2)) */ - Last_Subtract = 1; - q++; - y->fp_sign = signY; - } else { - /* Step 5.3 */ - /* r == y/2 */ - if (q % 2) { - q++; - signX = !signX; - } - } - - Step6: - r->fp_sign = signX; - - /* - * Step 7 - */ - if (Last_Subtract) { - CPYFPN(&fe->fe_f1, r); - CPYFPN(&fe->fe_f2, y); - fe->fe_f2.fp_sign = !y->fp_sign; - r = fpu_add(fe); - } - /* - * Step 8 - */ - q &= 0x7f; - q |= (signQ << 7); - fe->fe_fpframe->fpf_fpsr = - fe->fe_fpsr = - (fe->fe_fpsr & ~FPSR_QTT) | (q << 16); - return r; - - Step9: - fe->fe_f1.fp_class = FPC_ZERO; - q++; - q &= 0x7f; - q |= (signQ << 7); - fe->fe_fpframe->fpf_fpsr = - fe->fe_fpsr = - (fe->fe_fpsr & ~FPSR_QTT) | (q << 16); - return &fe->fe_f1; -} - -struct fpn * -fpu_rem(fe) - struct fpemu *fe; -{ - return __fpu_modrem(fe, 1); -} - -struct fpn * -fpu_mod(fe) - struct fpemu *fe; -{ - return __fpu_modrem(fe, 0); -} diff --git a/sys/arch/m68k/fpe/fpu_sqrt.c b/sys/arch/m68k/fpe/fpu_sqrt.c deleted file mode 100644 index c45a61c51c9..00000000000 --- a/sys/arch/m68k/fpe/fpu_sqrt.c +++ /dev/null @@ -1,360 +0,0 @@ -/* $OpenBSD: fpu_sqrt.c,v 1.5 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_sqrt.c,v 1.4 2003/08/07 16:28:12 agc Exp $ */ - -/* - * 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 - */ - -/* - * Perform an FPU square root (return sqrt(x)). - */ - -#include <sys/types.h> - -#include <machine/reg.h> - -#include <m68k/fpe/fpu_arith.h> -#include <m68k/fpe/fpu_emulate.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_f2; - u_int bit, q, tt; - u_int x0, x1, x2; - u_int y0, y1, y2; - u_int d0, d1, d2; - int e; - FPU_DECL_CARRY - - /* - * 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(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 <<= 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]; - 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 `(1 << 31) << 1', we also do the top bit - * outside of each per-word loop. - * - * The calculation `t = y + bit' breaks down into `t0 = y0, ..., - * t2 = y2, 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 - - /* - * 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; - return (x); -} diff --git a/sys/arch/m68k/fpe/fpu_subr.c b/sys/arch/m68k/fpe/fpu_subr.c deleted file mode 100644 index e59567d7c12..00000000000 --- a/sys/arch/m68k/fpe/fpu_subr.c +++ /dev/null @@ -1,209 +0,0 @@ -/* $OpenBSD: fpu_subr.c,v 1.5 2006/06/11 20:43:28 miod Exp $ */ -/* $NetBSD: fpu_subr.c,v 1.6 2003/08/07 16:28:12 agc Exp $ */ - -/* - * 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 - */ - -/* - * FPU subroutines. - */ - -#include <sys/types.h> -#include <sys/systm.h> - -#include <machine/reg.h> - -#include <m68k/fpe/fpu_emulate.h> -#include <m68k/fpe/fpu_arith.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) -{ - u_int m0, m1, m2, s; - int lsh; - -#ifdef DIAGNOSTIC - if (rsh < 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp))) - panic("fpu_rightshift 1"); -#endif - - m0 = fp->fp_mant[0]; - m1 = fp->fp_mant[1]; - m2 = fp->fp_mant[2]; - - /* If shifting all the bits out, take a shortcut. */ - if (rsh >= FP_NMANT) { -#ifdef DIAGNOSTIC - if ((m0 | m1 | m2) == 0) - panic("fpu_rightshift 2"); -#endif - fp->fp_mant[0] = 0; - fp->fp_mant[1] = 0; - fp->fp_mant[2] = 0; -#ifdef notdef - if ((m0 | m1 | m2) == 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 * 2) { - s |= m2 | m1; - m2 = m0, m1 = 0, m0 = 0; - } else if (rsh >= 32) { - s |= m2; - m2 = m1, m1 = m0, m0 = 0; - } - - /* Handle any remaining partial word. */ - if ((rsh &= 31) != 0) { - lsh = 32 - rsh; - s |= 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_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[2] == 0). - */ -void -fpu_norm(struct fpn *fp) -{ - u_int m0, m1, m2, 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]; - - /* Handle severe subnormals with 32-bit moves. */ - if (m0 == 0) { - if (m1) { - m0 = m1; - m1 = m2; - m2 = 0; - exp -= 32; - } else if (m2) { - m0 = m2; - m1 = 0; - m2 = 0; - exp -= 2 * 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 m2==0. - */ - __asm __volatile("bfffo %1{#0:#32},%0" : "=d"(rsh) : "g"(m0)); - rsh = 31 - rsh - FP_LG; - exp += rsh; - lsh = 32 - rsh; - m2 = m1 << lsh; - m1 = (m1 >> rsh) | (m0 << lsh); - m0 = (m0 >> rsh); - } else if (m0 < nrm) { - /* - * We have a regular denorm (a subnormal number), and need - * to shift it left. - */ - __asm __volatile("bfffo %1{#0:#32},%0" : "=d"(lsh) : "g"(m0)); - lsh = FP_LG - 31 + lsh; - exp -= lsh; - rsh = 32 - lsh; - m0 = (m0 << lsh) | (m1 >> rsh); - m1 = (m1 << lsh) | (m2 >> rsh); - m2 <<= lsh; - } - - fp->fp_exp = exp; - fp->fp_mant[0] = m0; - fp->fp_mant[1] = m1; - fp->fp_mant[2] = m2; -} - -/* - * Concoct a `fresh' Quiet NaN per Appendix N. - * As a side effect, we set OPERR for the current exceptions. - */ -struct fpn * -fpu_newnan(struct fpemu *fe) -{ - struct fpn *fp; - - fe->fe_fpsr |= FPSR_OPERR; - 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] = ~0; - return (fp); -} |