Annotation of sys/arch/sparc64/fpu/fpu_subr.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: fpu_subr.c,v 1.2 2003/06/02 23:27:55 millert Exp $ */
! 2: /* $NetBSD: fpu_subr.c,v 1.3 1996/03/14 19:42:01 christos Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1992, 1993
! 6: * The Regents of the University of California. All rights reserved.
! 7: *
! 8: * This software was developed by the Computer Systems Engineering group
! 9: * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
! 10: * contributed to Berkeley.
! 11: *
! 12: * All advertising materials mentioning features or use of this software
! 13: * must display the following acknowledgement:
! 14: * This product includes software developed by the University of
! 15: * California, Lawrence Berkeley Laboratory.
! 16: *
! 17: * Redistribution and use in source and binary forms, with or without
! 18: * modification, are permitted provided that the following conditions
! 19: * are met:
! 20: * 1. Redistributions of source code must retain the above copyright
! 21: * notice, this list of conditions and the following disclaimer.
! 22: * 2. Redistributions in binary form must reproduce the above copyright
! 23: * notice, this list of conditions and the following disclaimer in the
! 24: * documentation and/or other materials provided with the distribution.
! 25: * 3. Neither the name of the University nor the names of its contributors
! 26: * may be used to endorse or promote products derived from this software
! 27: * without specific prior written permission.
! 28: *
! 29: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 32: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 33: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 39: * SUCH DAMAGE.
! 40: *
! 41: * @(#)fpu_subr.c 8.1 (Berkeley) 6/11/93
! 42: */
! 43:
! 44: /*
! 45: * FPU subroutines.
! 46: */
! 47:
! 48: #include <sys/types.h>
! 49: #ifdef DIAGNOSTIC
! 50: #include <sys/systm.h>
! 51: #endif
! 52:
! 53: #include <machine/reg.h>
! 54: #include <machine/instr.h>
! 55:
! 56: #include <sparc64/fpu/fpu_arith.h>
! 57: #include <sparc64/fpu/fpu_emu.h>
! 58: #include <sparc64/fpu/fpu_extern.h>
! 59:
! 60: /*
! 61: * Shift the given number right rsh bits. Any bits that `fall off' will get
! 62: * shoved into the sticky field; we return the resulting sticky. Note that
! 63: * shifting NaNs is legal (this will never shift all bits out); a NaN's
! 64: * sticky field is ignored anyway.
! 65: */
! 66: int
! 67: fpu_shr(register struct fpn *fp, register int rsh)
! 68: {
! 69: register u_int m0, m1, m2, m3, s;
! 70: register int lsh;
! 71:
! 72: #ifdef DIAGNOSTIC
! 73: if (rsh <= 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp)))
! 74: panic("fpu_rightshift 1");
! 75: #endif
! 76:
! 77: m0 = fp->fp_mant[0];
! 78: m1 = fp->fp_mant[1];
! 79: m2 = fp->fp_mant[2];
! 80: m3 = fp->fp_mant[3];
! 81:
! 82: /* If shifting all the bits out, take a shortcut. */
! 83: if (rsh >= FP_NMANT) {
! 84: #ifdef DIAGNOSTIC
! 85: if ((m0 | m1 | m2 | m3) == 0)
! 86: panic("fpu_rightshift 2");
! 87: #endif
! 88: fp->fp_mant[0] = 0;
! 89: fp->fp_mant[1] = 0;
! 90: fp->fp_mant[2] = 0;
! 91: fp->fp_mant[3] = 0;
! 92: #ifdef notdef
! 93: if ((m0 | m1 | m2 | m3) == 0)
! 94: fp->fp_class = FPC_ZERO;
! 95: else
! 96: #endif
! 97: fp->fp_sticky = 1;
! 98: return (1);
! 99: }
! 100:
! 101: /* Squish out full words. */
! 102: s = fp->fp_sticky;
! 103: if (rsh >= 32 * 3) {
! 104: s |= m3 | m2 | m1;
! 105: m3 = m0, m2 = 0, m1 = 0, m0 = 0;
! 106: } else if (rsh >= 32 * 2) {
! 107: s |= m3 | m2;
! 108: m3 = m1, m2 = m0, m1 = 0, m0 = 0;
! 109: } else if (rsh >= 32) {
! 110: s |= m3;
! 111: m3 = m2, m2 = m1, m1 = m0, m0 = 0;
! 112: }
! 113:
! 114: /* Handle any remaining partial word. */
! 115: if ((rsh &= 31) != 0) {
! 116: lsh = 32 - rsh;
! 117: s |= m3 << lsh;
! 118: m3 = (m3 >> rsh) | (m2 << lsh);
! 119: m2 = (m2 >> rsh) | (m1 << lsh);
! 120: m1 = (m1 >> rsh) | (m0 << lsh);
! 121: m0 >>= rsh;
! 122: }
! 123: fp->fp_mant[0] = m0;
! 124: fp->fp_mant[1] = m1;
! 125: fp->fp_mant[2] = m2;
! 126: fp->fp_mant[3] = m3;
! 127: fp->fp_sticky = s;
! 128: return (s);
! 129: }
! 130:
! 131: /*
! 132: * Force a number to be normal, i.e., make its fraction have all zero
! 133: * bits before FP_1, then FP_1, then all 1 bits. This is used for denorms
! 134: * and (sometimes) for intermediate results.
! 135: *
! 136: * Internally, this may use a `supernormal' -- a number whose fp_mant
! 137: * is greater than or equal to 2.0 -- so as a side effect you can hand it
! 138: * a supernormal and it will fix it (provided fp->fp_mant[3] == 0).
! 139: */
! 140: void
! 141: fpu_norm(register struct fpn *fp)
! 142: {
! 143: register u_int m0, m1, m2, m3, top, sup, nrm;
! 144: register int lsh, rsh, exp;
! 145:
! 146: exp = fp->fp_exp;
! 147: m0 = fp->fp_mant[0];
! 148: m1 = fp->fp_mant[1];
! 149: m2 = fp->fp_mant[2];
! 150: m3 = fp->fp_mant[3];
! 151:
! 152: /* Handle severe subnormals with 32-bit moves. */
! 153: if (m0 == 0) {
! 154: if (m1)
! 155: m0 = m1, m1 = m2, m2 = m3, m3 = 0, exp -= 32;
! 156: else if (m2)
! 157: m0 = m2, m1 = m3, m2 = 0, m3 = 0, exp -= 2 * 32;
! 158: else if (m3)
! 159: m0 = m3, m1 = 0, m2 = 0, m3 = 0, exp -= 3 * 32;
! 160: else {
! 161: fp->fp_class = FPC_ZERO;
! 162: return;
! 163: }
! 164: }
! 165:
! 166: /* Now fix any supernormal or remaining subnormal. */
! 167: nrm = FP_1;
! 168: sup = nrm << 1;
! 169: if (m0 >= sup) {
! 170: /*
! 171: * We have a supernormal number. We need to shift it right.
! 172: * We may assume m3==0.
! 173: */
! 174: for (rsh = 1, top = m0 >> 1; top >= sup; rsh++) /* XXX slow */
! 175: top >>= 1;
! 176: exp += rsh;
! 177: lsh = 32 - rsh;
! 178: m3 = m2 << lsh;
! 179: m2 = (m2 >> rsh) | (m1 << lsh);
! 180: m1 = (m1 >> rsh) | (m0 << lsh);
! 181: m0 = top;
! 182: } else if (m0 < nrm) {
! 183: /*
! 184: * We have a regular denorm (a subnormal number), and need
! 185: * to shift it left.
! 186: */
! 187: for (lsh = 1, top = m0 << 1; top < nrm; lsh++) /* XXX slow */
! 188: top <<= 1;
! 189: exp -= lsh;
! 190: rsh = 32 - lsh;
! 191: m0 = top | (m1 >> rsh);
! 192: m1 = (m1 << lsh) | (m2 >> rsh);
! 193: m2 = (m2 << lsh) | (m3 >> rsh);
! 194: m3 <<= lsh;
! 195: }
! 196:
! 197: fp->fp_exp = exp;
! 198: fp->fp_mant[0] = m0;
! 199: fp->fp_mant[1] = m1;
! 200: fp->fp_mant[2] = m2;
! 201: fp->fp_mant[3] = m3;
! 202: }
! 203:
! 204: /*
! 205: * Concoct a `fresh' Quiet NaN per Appendix N.
! 206: * As a side effect, we set NV (invalid) for the current exceptions.
! 207: */
! 208: struct fpn *
! 209: fpu_newnan(register struct fpemu *fe)
! 210: {
! 211: register struct fpn *fp;
! 212:
! 213: fe->fe_cx = FSR_NV;
! 214: fp = &fe->fe_f3;
! 215: fp->fp_class = FPC_QNAN;
! 216: fp->fp_sign = 0;
! 217: fp->fp_mant[0] = FP_1 - 1;
! 218: fp->fp_mant[1] = fp->fp_mant[2] = fp->fp_mant[3] = ~0;
! 219: return (fp);
! 220: }
CVSweb