|
|
1.1.1.3 ! root 1: /* $NetBSD: fpu_rem.c,v 1.18 2023/11/19 03:58:15 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. Neither the name of the author nor the names of its contributors
16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: *
31: * @(#)fpu_rem.c 10/24/95
32: */
33:
34: #include "fpu_emulate.h"
35:
36: /*
37: * ALGORITHM
38: *
39: * Step 1. Save and strip signs of X and Y: signX := sign(X),
40: * signY := sign(Y), X := *X*, Y := *Y*,
41: * signQ := signX EOR signY. Record whether MOD or REM
42: * is requested.
43: *
1.1.1.2 root 44: * Step 2. Set L := expo(X)-expo(Y), Q := 0.
1.1 root 45: * If (L < 0) then
46: * R := X, go to Step 4.
47: * else
48: * R := 2^(-L)X, j := L.
49: * endif
50: *
51: * Step 3. Perform MOD(X,Y)
52: * 3.1 If R = Y, then
53: * Q := Q + 1, R := 0 with signX, go to Step 7.
54: * 3.2 If R > Y, then { R := R - Y, Q := Q + 1}
55: * 3.3 If j = 0, go to Step 4.
1.1.1.2 root 56: * 3.4 j := j - 1, Q := 2Q, R := 2R. Go to Step 3.1.
1.1 root 57: *
58: * Step 4. R := signX*R.
59: *
60: * Step 5. If MOD is requested, go to Step 7.
61: *
62: * Step 6. Now, R = MOD(X,Y), convert to REM(X,Y) is requested.
63: * Do banker's rounding.
64: * If abs(R) > Y/2
65: * || (abs(R) == Y/2 && Q % 2 == 1) then
66: * { Q := Q + 1, R := R - signX * Y }.
67: *
68: * Step 7. Return signQ, last 7 bits of Q, and R as required.
69: */
70:
71: static int abscmp3(const struct fpn *a, const struct fpn *b);
72:
73: /* Absolute FORTRAN Compare */
74: static int
75: abscmp3(const struct fpn *a, const struct fpn *b)
76: {
77: int i;
78:
79: if (a->fp_exp < b->fp_exp) {
80: return -1;
81: } else if (a->fp_exp > b->fp_exp) {
82: return 1;
83: } else {
84: for (i = 0; i < 3; i++) {
85: if (a->fp_mant[i] < b->fp_mant[i])
86: return -1;
87: else if (a->fp_mant[i] > b->fp_mant[i])
88: return 1;
89: }
90: }
91: return 0;
92: }
93:
94: struct fpn *
95: fpu_modrem(struct fpemu *fe, int is_mod)
96: {
97: struct fpn X, Y;
98: struct fpn *x, *y, *r;
99: uint32_t signX, signY, signQ;
1.1.1.2 root 100: int j, l, q;
1.1 root 101: int cmp;
102:
103: if (ISNAN(&fe->fe_f1))
104: return &fe->fe_f1;
105: if (ISNAN(&fe->fe_f2))
106: return &fe->fe_f2;
107: if (ISINF(&fe->fe_f1) || ISZERO(&fe->fe_f2))
108: return fpu_newnan(fe);
109:
110: CPYFPN(&X, &fe->fe_f1);
111: CPYFPN(&Y, &fe->fe_f2);
112: x = &X;
113: y = &Y;
114: q = 0;
115: r = &fe->fe_f2;
116:
117: /*
118: * Step 1
119: */
120: signX = x->fp_sign;
121: signY = y->fp_sign;
122: signQ = (signX ^ signY);
123: x->fp_sign = y->fp_sign = 0;
124:
125: /* Special treatment that just return input value but Q is necessary */
126: if (ISZERO(x) || ISINF(y)) {
127: r = &fe->fe_f1;
128: goto Step7;
129: }
130:
131: /*
132: * Step 2
133: */
134: l = x->fp_exp - y->fp_exp;
135: CPYFPN(r, x);
136: if (l >= 0) {
137: r->fp_exp -= l;
138: j = l;
139:
140: /*
141: * Step 3
142: */
143: for (;;) {
144: cmp = abscmp3(r, y);
145:
146: /* Step 3.1 */
147: if (cmp == 0) {
148: r->fp_sign = signX;
149: break;
150: }
151:
152: /* Step 3.2 */
153: if (cmp > 0) {
154: CPYFPN(&fe->fe_f1, r);
155: CPYFPN(&fe->fe_f2, y);
156: fe->fe_f2.fp_sign = 1;
157: r = fpu_add(fe);
158: q++;
159: }
160:
161: /* Step 3.3 */
162: if (j == 0)
163: goto Step4;
164:
165: /* Step 3.4 */
166: j--;
167: q += q;
168: r->fp_exp++;
169: }
170: /* R == Y */
171: q++;
172: q <<= (j > 7) ? 8 : j;
173: r->fp_class = FPC_ZERO;
174: goto Step7;
175: }
176: Step4:
177: r->fp_sign = signX;
178:
179: /*
180: * Step 5
181: */
182: if (is_mod)
183: goto Step7;
184:
185: /*
186: * Step 6
187: */
188: /* y = y / 2 */
189: y->fp_exp--;
190: /* abscmp3 ignore sign */
191: cmp = abscmp3(r, y);
192: /* revert y */
193: y->fp_exp++;
194:
195: if (cmp > 0 || (cmp == 0 && q % 2)) {
196: q++;
197: CPYFPN(&fe->fe_f1, r);
198: CPYFPN(&fe->fe_f2, y);
199: fe->fe_f2.fp_sign = !signX;
200: r = fpu_add(fe);
201: }
202:
203: /*
204: * Step 7
205: */
206: Step7:
207: q &= 0x7f;
208: q |= (signQ << 7);
209: fe->fe_fpsr = (fe->fe_fpsr & ~FPSR_QTT) | (q << 16);
210: return r;
211: }
212:
213: struct fpn *
214: fpu_rem(struct fpemu *fe)
215: {
216: struct fpn *fp;
217:
218: fp = fpu_modrem(fe, 0);
219:
220: /* Update Quotient Byte */
221: fe->fe_fpframe->fpf_fpsr &= ~FPSR_QTT;
222: fe->fe_fpframe->fpf_fpsr |= (fe->fe_fpsr & FPSR_QTT);
223:
224: return fp;
225: }
226:
227: struct fpn *
228: fpu_mod(struct fpemu *fe)
229: {
230: struct fpn *fp;
231:
232: fp = fpu_modrem(fe, 1);
233:
234: /* Update Quotient Byte */
235: fe->fe_fpframe->fpf_fpsr &= ~FPSR_QTT;
236: fe->fe_fpframe->fpf_fpsr |= (fe->fe_fpsr & FPSR_QTT);
237:
238: return fp;
239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.