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