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