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

1.1.1.2 ! root        1: /*     $NetBSD: fpu_fscale.c,v 1.17 2025/01/06 07:34:24 isaki Exp $    */
1.1       root        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.