|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.