Annotation of nono/fpe/fpu_mul.c, revision 1.1

1.1     ! root        1: /*     $NetBSD: fpu_mul.c,v 1.9 2016/12/06 06:41:14 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_mul.c   8.1 (Berkeley) 6/11/93
        !            41:  */
        !            42: 
        !            43: /*
        !            44:  * Perform an FPU multiply (return x * y).
        !            45:  */
        !            46: 
        !            47: #include "fpu_arith.h"
        !            48: #include "fpu_emulate.h"
        !            49: 
        !            50: /*
        !            51:  * The multiplication algorithm for normal numbers is as follows:
        !            52:  *
        !            53:  * The fraction of the product is built in the usual stepwise fashion.
        !            54:  * Each step consists of shifting the accumulator right one bit
        !            55:  * (maintaining any guard bits) and, if the next bit in y is set,
        !            56:  * adding the multiplicand (x) to the accumulator.  Then, in any case,
        !            57:  * we advance one bit leftward in y.  Algorithmically:
        !            58:  *
        !            59:  *     A = 0;
        !            60:  *     for (bit = 0; bit < FP_NMANT; bit++) {
        !            61:  *             sticky |= A & 1, A >>= 1;
        !            62:  *             if (Y & (1 << bit))
        !            63:  *                     A += X;
        !            64:  *     }
        !            65:  *
        !            66:  * (X and Y here represent the mantissas of x and y respectively.)
        !            67:  * The resultant accumulator (A) is the product's mantissa.  It may
        !            68:  * be as large as 11.11111... in binary and hence may need to be
        !            69:  * shifted right, but at most one bit.
        !            70:  *
        !            71:  * Since we do not have efficient multiword arithmetic, we code the
        !            72:  * accumulator as four separate words, just like any other mantissa.
        !            73:  *
        !            74:  * In the algorithm above, the bits in y are inspected one at a time.
        !            75:  * We will pick them up 32 at a time and then deal with those 32, one
        !            76:  * at a time.  Note, however, that we know several things about y:
        !            77:  *
        !            78:  *    - the guard and round bits at the bottom are sure to be zero;
        !            79:  *
        !            80:  *    - often many low bits are zero (y is often from a single or double
        !            81:  *     precision source);
        !            82:  *
        !            83:  *    - bit FP_NMANT-1 is set, and FP_1*2 fits in a word.
        !            84:  *
        !            85:  * We can also test for 32-zero-bits swiftly.  In this case, the center
        !            86:  * part of the loop---setting sticky, shifting A, and not adding---will
        !            87:  * run 32 times without adding X to A.  We can do a 32-bit shift faster
        !            88:  * by simply moving words.  Since zeros are common, we optimize this case.
        !            89:  * Furthermore, since A is initially zero, we can omit the shift as well
        !            90:  * until we reach a nonzero word.
        !            91:  */
        !            92: struct fpn *
        !            93: fpu_mul(struct fpemu *fe)
        !            94: {
        !            95:        struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
        !            96:        uint32_t a2, a1, a0, x2, x1, x0, bit, m;
        !            97:        int sticky;
        !            98:        FPU_DECL_CARRY
        !            99: 
        !           100:        /*
        !           101:         * Put the `heavier' operand on the right (see fpu_emu.h).
        !           102:         * Then we will have one of the following cases, taken in the
        !           103:         * following order:
        !           104:         *
        !           105:         *  - y = NaN.  Implied: if only one is a signalling NaN, y is.
        !           106:         *      The result is y.
        !           107:         *  - y = Inf.  Implied: x != NaN (is 0, number, or Inf: the NaN
        !           108:         *    case was taken care of earlier).
        !           109:         *      If x = 0, the result is NaN.  Otherwise the result
        !           110:         *      is y, with its sign reversed if x is negative.
        !           111:         *  - x = 0.  Implied: y is 0 or number.
        !           112:         *      The result is 0 (with XORed sign as usual).
        !           113:         *  - other.  Implied: both x and y are numbers.
        !           114:         *      The result is x * y (XOR sign, multiply bits, add exponents).
        !           115:         */
        !           116:        ORDER(x, y);
        !           117:        if (ISNAN(y)) {
        !           118:                return (y);
        !           119:        }
        !           120:        if (ISINF(y)) {
        !           121:                if (ISZERO(x))
        !           122:                        return (fpu_newnan(fe));
        !           123:                y->fp_sign ^= x->fp_sign;
        !           124:                return (y);
        !           125:        }
        !           126:        if (ISZERO(x)) {
        !           127:                x->fp_sign ^= y->fp_sign;
        !           128:                return (x);
        !           129:        }
        !           130: 
        !           131:        /*
        !           132:         * Setup.  In the code below, the mask `m' will hold the current
        !           133:         * mantissa byte from y.  The variable `bit' denotes the bit
        !           134:         * within m.  We also define some macros to deal with everything.
        !           135:         */
        !           136:        x2 = x->fp_mant[2];
        !           137:        x1 = x->fp_mant[1];
        !           138:        x0 = x->fp_mant[0];
        !           139:        sticky = a2 = a1 = a0 = 0;
        !           140: 
        !           141: #define        ADD     /* A += X */ \
        !           142:        FPU_ADDS(a2, a2, x2); \
        !           143:        FPU_ADDCS(a1, a1, x1); \
        !           144:        FPU_ADDC(a0, a0, x0)
        !           145: 
        !           146: #define        SHR1    /* A >>= 1, with sticky */ \
        !           147:        sticky |= a2 & 1, \
        !           148:        a2 = (a2 >> 1) | (a1 << 31), a1 = (a1 >> 1) | (a0 << 31), a0 >>= 1
        !           149: 
        !           150: #define        SHR32   /* A >>= 32, with sticky */ \
        !           151:        sticky |= a2, a2 = a1, a1 = a0, a0 = 0
        !           152: 
        !           153: #define        STEP    /* each 1-bit step of the multiplication */ \
        !           154:        SHR1; if (bit & m) { ADD; }; bit <<= 1
        !           155: 
        !           156:        /*
        !           157:         * We are ready to begin.  The multiply loop runs once for each
        !           158:         * of the four 32-bit words.  Some words, however, are special.
        !           159:         * As noted above, the low order bits of Y are often zero.  Even
        !           160:         * if not, the first loop can certainly skip the guard bits.
        !           161:         * The last word of y has its highest 1-bit in position FP_NMANT-1,
        !           162:         * so we stop the loop when we move past that bit.
        !           163:         */
        !           164:        if ((m = y->fp_mant[2]) == 0) {
        !           165:                /* SHR32; */                    /* unneeded since A==0 */
        !           166:        } else {
        !           167:                bit = 1 << FP_NG;
        !           168:                do {
        !           169:                        STEP;
        !           170:                } while (bit != 0);
        !           171:        }
        !           172:        if ((m = y->fp_mant[1]) == 0) {
        !           173:                SHR32;
        !           174:        } else {
        !           175:                bit = 1;
        !           176:                do {
        !           177:                        STEP;
        !           178:                } while (bit != 0);
        !           179:        }
        !           180:        m = y->fp_mant[0];              /* definitely != 0 */
        !           181:        bit = 1;
        !           182:        do {
        !           183:                STEP;
        !           184:        } while (bit <= m);
        !           185: 
        !           186:        /*
        !           187:         * Done with mantissa calculation.  Get exponent and handle
        !           188:         * 11.111...1 case, then put result in place.  We reuse x since
        !           189:         * it already has the right class (FP_NUM).
        !           190:         */
        !           191:        m = x->fp_exp + y->fp_exp;
        !           192:        if (a0 >= FP_2) {
        !           193:                SHR1;
        !           194:                m++;
        !           195:        }
        !           196:        x->fp_sign ^= y->fp_sign;
        !           197:        x->fp_exp = m;
        !           198:        x->fp_sticky = sticky;
        !           199:        x->fp_mant[2] = a2;
        !           200:        x->fp_mant[1] = a1;
        !           201:        x->fp_mant[0] = a0;
        !           202:        return (x);
        !           203: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.