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

1.1     ! root        1: /*     $NetBSD: fpu_fscale.c,v 1.16 2013/03/26 11:30:20 isaki Exp $    */
        !             2: 
        !             3: /*
        !             4:  * Copyright (c) 1995 Ken Nakata
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. The name of the author may not be used to endorse or promote products
        !            16:  *    derived from this software without specific prior written permission.
        !            17:  * 4. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed by Gordon Ross
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32: 
        !            33: /*
        !            34:  * FSCALE - separated from the other type0 arithmetic instructions
        !            35:  * for performance reason; maybe unnecessary, but FSCALE assumes
        !            36:  * the source operand be an integer.  It performs type conversion
        !            37:  * only if the source operand is *not* an integer.
        !            38:  */
        !            39: /*
        !            40:  * XM6i では他の type0 演算命令と同様に、ソースオペランドは f2 に fpn
        !            41:  * 形式で取得済みのところから実行する。ただしデスティネーションには
        !            42:  * 直接格納しているため、戻った fgen() 側では格納とフラグ処理は飛ばすこと。
        !            43:  *
        !            44:  * 本当は元ソースと XM6i_FPE で並べるべきだが、量が多いのでちょっと放置。
        !            45:  */
        !            46: 
        !            47: #include "fpu_emulate.h"
        !            48: 
        !            49: int
        !            50: fpu_emul_fscale(struct fpemu *fe, uint32_t word1)
        !            51: {
        !            52:        uint32_t *fpregs;
        !            53:        int sig;
        !            54:        int regnum;
        !            55:        int scale, sign, exp;
        !            56:        uint32_t m0, m1;
        !            57:        uint32_t buf[3], fpsr;
        !            58: #if DEBUG_FPE
        !            59:        int flags;
        !            60:        char regname;
        !            61: #endif
        !            62: 
        !            63:        scale = sig = 0;
        !            64:        fpregs = &(fe->fe_fpframe->fpf_regs[0]);
        !            65:        /* clear all exceptions and conditions */
        !            66:        fpsr = fe->fe_fpsr & ~FPSR_EXCP & ~FPSR_CCB;
        !            67: #if DEBUG_FPE
        !            68:        printf("fpu_emul_fscale: FPSR = %08x, FPCR = %08x\n", fpsr, fe->fe_fpcr);
        !            69: #endif
        !            70: 
        !            71:        regnum = (word1 >> 7) & 7;
        !            72: 
        !            73:        fe->fe_fpcr &= FPCR_ROUND;
        !            74:        fe->fe_fpcr |= FPCR_ZERO;
        !            75: 
        !            76:        /* 他の演算と同様にソースオペランドは f2 に fpn 形式で取得済みとする */
        !            77:        fpu_implode(fe, &fe->fe_f2, FTYPE_LNG, buf);
        !            78:        scale = buf[0];
        !            79: 
        !            80:        /* assume there's no exception */
        !            81:        sig = 0;
        !            82: 
        !            83:        /*
        !            84:         * it's barbaric but we're going to operate directly on
        !            85:         * the dst operand's bit pattern
        !            86:         */
        !            87:        sign = fpregs[regnum * 3] & 0x80000000;
        !            88:        exp = (fpregs[regnum * 3] & 0x7fff0000) >> 16;
        !            89:        m0 = fpregs[regnum * 3 + 1];
        !            90:        m1 = fpregs[regnum * 3 + 2];
        !            91: 
        !            92:        switch (fe->fe_f2.fp_class) {
        !            93:        case FPC_SNAN:
        !            94:                fpsr |= FPSR_SNAN;
        !            95:        case FPC_QNAN:
        !            96:                /* dst = NaN */
        !            97:                exp = 0x7fff;
        !            98:                m0 = m1 = 0xffffffff;
        !            99:                break;
        !           100:        case FPC_ZERO:
        !           101:        case FPC_NUM:
        !           102:                if ((0 < exp && exp < 0x7fff) ||
        !           103:                    (exp == 0 && (m0 | m1) != 0)) {
        !           104:                        /* normal or denormal */
        !           105:                        exp += scale;
        !           106:                        if (exp < 0) {
        !           107:                                /* underflow */
        !           108:                                uint32_t grs;   /* guard, round and sticky */
        !           109: 
        !           110:                                exp = 0;
        !           111:                                grs = m1 << (32 + exp);
        !           112:                                m1 = m0 << (32 + exp) | m1 >> -exp;
        !           113:                                m0 >>= -exp;
        !           114:                                if (grs != 0) {
        !           115:                                        fpsr |= FPSR_INEX2;
        !           116: 
        !           117:                                        switch (fe->fe_fpcr & 0x30) {
        !           118:                                        case FPCR_MINF:
        !           119:                                                if (sign != 0) {
        !           120:                                                        if (++m1 == 0 &&
        !           121:                                                            ++m0 == 0) {
        !           122:                                                                m0 = 0x80000000;
        !           123:                                                                exp++;
        !           124:                                                        }
        !           125:                                                }
        !           126:                                                break;
        !           127:                                        case FPCR_NEAR:
        !           128:                                                if (grs == 0x80000000) {
        !           129:                                                        /* tie */
        !           130:                                                        if ((m1 & 1) &&
        !           131:                                                            ++m1 == 0 &&
        !           132:                                                            ++m0 == 0) {
        !           133:                                                                m0 = 0x80000000;
        !           134:                                                                exp++;
        !           135:                                                        }
        !           136:                                                } else if (grs & 0x80000000) {
        !           137:                                                        if (++m1 == 0 &&
        !           138:                                                            ++m0 == 0) {
        !           139:                                                                m0 = 0x80000000;
        !           140:                                                                exp++;
        !           141:                                                        }
        !           142:                                                }
        !           143:                                                break;
        !           144:                                        case FPCR_PINF:
        !           145:                                                if (sign == 0) {
        !           146:                                                        if (++m1 == 0 &&
        !           147:                                                            ++m0 == 0) {
        !           148:                                                                m0 = 0x80000000;
        !           149:                                                                exp++;
        !           150:                                                        }
        !           151:                                                }
        !           152:                                                break;
        !           153:                                        case FPCR_ZERO:
        !           154:                                                break;
        !           155:                                        }
        !           156:                                }
        !           157:                                if (exp == 0 && (m0 & 0x80000000) == 0) {
        !           158:                                        fpsr |= FPSR_UNFL;
        !           159:                                        if ((m0 | m1) == 0) {
        !           160:                                                fpsr |= FPSR_ZERO;
        !           161:                                        }
        !           162:                                }
        !           163:                        } else if (exp >= 0x7fff) {
        !           164:                                /* overflow --> result = Inf */
        !           165:                                /*
        !           166:                                 * but first, try to normalize in case it's an
        !           167:                                 * unnormalized
        !           168:                                 */
        !           169:                                while ((m0 & 0x80000000) == 0) {
        !           170:                                        exp--;
        !           171:                                        m0 = (m0 << 1) | (m1 >> 31);
        !           172:                                        m1 = m1 << 1;
        !           173:                                }
        !           174:                                /* if it's still too large, then return Inf */
        !           175:                                if (exp >= 0x7fff) {
        !           176:                                        exp = 0x7fff;
        !           177:                                        m0 = m1 = 0;
        !           178:                                        fpsr |= FPSR_OVFL | FPSR_INF;
        !           179:                                }
        !           180:                        } else if ((m0 & 0x80000000) == 0) {
        !           181:                                /*
        !           182:                                 * it's a denormal; we try to normalize but
        !           183:                                 * result may and may not be a normal.
        !           184:                                 */
        !           185:                                while (exp > 0 && (m0 & 0x80000000) == 0) {
        !           186:                                        exp--;
        !           187:                                        m0 = (m0 << 1) | (m1 >> 31);
        !           188:                                        m1 = m1 << 1;
        !           189:                                }
        !           190:                                if ((m0 & 0x80000000) == 0) {
        !           191:                                        fpsr |= FPSR_UNFL;
        !           192:                                }
        !           193:                        } /* exp in range and mantissa normalized */
        !           194:                } else if (exp == 0 && m0 == 0 && m1 == 0) {
        !           195:                        /* dst is Zero */
        !           196:                        fpsr |= FPSR_ZERO;
        !           197:                } /* else we know exp == 0x7fff */
        !           198:                else if ((m0 | m1) == 0) {
        !           199:                        fpsr |= FPSR_INF;
        !           200:                } else if ((m0 & 0x40000000) == 0) {
        !           201:                        /* a signaling NaN */
        !           202:                        fpsr |= FPSR_NAN | FPSR_SNAN;
        !           203:                } else {
        !           204:                        /* a quiet NaN */
        !           205:                        fpsr |= FPSR_NAN;
        !           206:                }
        !           207:                break;
        !           208:        case FPC_INF:
        !           209:                /* dst = NaN */
        !           210:                exp = 0x7fff;
        !           211:                m0 = m1 = 0xffffffff;
        !           212:                fpsr |= FPSR_OPERR | FPSR_NAN;
        !           213:                break;
        !           214:        default:
        !           215: #ifdef DEBUG
        !           216:                panic("fpu_emul_fscale: invalid fp class");
        !           217: #endif
        !           218:                break;
        !           219:        }
        !           220: 
        !           221:        /* store the result */
        !           222:        fpregs[regnum * 3] = sign | (exp << 16);
        !           223:        fpregs[regnum * 3 + 1] = m0;
        !           224:        fpregs[regnum * 3 + 2] = m1;
        !           225: 
        !           226:        if (sign) {
        !           227:                fpsr |= FPSR_NEG;
        !           228:        }
        !           229: 
        !           230:        /* update fpsr according to the result of operation */
        !           231:        fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr;
        !           232: 
        !           233: #if DEBUG_FPE
        !           234:        printf("fpu_emul_fscale: FPSR = %08x, FPCR = %08x\n",
        !           235:            fe->fe_fpsr, fe->fe_fpcr);
        !           236: #endif
        !           237: 
        !           238:        return 0;
        !           239: }

unix.superglobalmegacorp.com

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