Annotation of sys/arch/m68k/fpe/fpu_rem.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: fpu_rem.c,v 1.5 2006/06/11 20:43:28 miod Exp $ */
2: /* $NetBSD: fpu_rem.c,v 1.5 2003/07/15 02:43:10 lukem Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Ken Nakata
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the author nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * @(#)fpu_rem.c 10/24/95
33: */
34:
35: #include <sys/types.h>
36: #include <sys/signal.h>
37: #include <machine/frame.h>
38:
39: #include <m68k/fpe/fpu_emulate.h>
40:
41: /*
42: * ALGORITHM
43: *
44: * Step 1. Save and strip signs of X and Y: signX := sign(X),
45: * signY := sign(Y), X := *X*, Y := *Y*,
46: * signQ := signX EOR signY. Record whether MOD or REM
47: * is requested.
48: *
49: * Step 2. Set L := expo(X)-expo(Y), k := 0, Q := 0.
50: * If (L < 0) then
51: * R := X, go to Step 4.
52: * else
53: * R := 2^(-L)X, j := L.
54: * endif
55: *
56: * Step 3. Perform MOD(X,Y)
57: * 3.1 If R = Y, go to Step 9.
58: * 3.2 If R > Y, then { R := R - Y, Q := Q + 1}
59: * 3.3 If j = 0, go to Step 4.
60: * 3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to
61: * Step 3.1.
62: *
63: * Step 4. At this point, R = X - QY = MOD(X,Y). Set
64: * Last_Subtract := false (used in Step 7 below). If
65: * MOD is requested, go to Step 6.
66: *
67: * Step 5. R = MOD(X,Y), but REM(X,Y) is requested.
68: * 5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to
69: * Step 6.
70: * 5.2 If R > Y/2, then { set Last_Subtract := true,
71: * Q := Q + 1, Y := signY*Y }. Go to Step 6.
72: * 5.3 This is the tricky case of R = Y/2. If Q is odd,
73: * then { Q := Q + 1, signX := -signX }.
74: *
75: * Step 6. R := signX*R.
76: *
77: * Step 7. If Last_Subtract = true, R := R - Y.
78: *
79: * Step 8. Return signQ, last 7 bits of Q, and R as required.
80: *
81: * Step 9. At this point, R = 2^(-j)*X - Q Y = Y. Thus,
82: * X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),
83: * R := 0. Return signQ, last 7 bits of Q, and R.
84: */
85:
86: struct fpn *__fpu_modrem(struct fpemu *fe, int modrem);
87:
88: struct fpn *
89: __fpu_modrem(fe, modrem)
90: struct fpemu *fe;
91: int modrem;
92: {
93: static struct fpn X, Y;
94: struct fpn *x, *y, *r;
95: u_int signX, signY, signQ;
96: int j, k, l, q;
97: int Last_Subtract;
98:
99: CPYFPN(&X, &fe->fe_f1);
100: CPYFPN(&Y, &fe->fe_f2);
101: x = &X;
102: y = &Y;
103: r = &fe->fe_f2;
104:
105: /*
106: * Step 1
107: */
108: signX = x->fp_sign;
109: signY = y->fp_sign;
110: signQ = (signX ^ signY);
111: x->fp_sign = y->fp_sign = 0;
112:
113: /*
114: * Step 2
115: */
116: l = x->fp_exp - y->fp_exp;
117: k = 0;
118: q = 0;
119: if (l >= 0) {
120: CPYFPN(r, x);
121: r->fp_exp -= l;
122: j = l;
123:
124: /*
125: * Step 3
126: */
127: while (y->fp_exp != r->fp_exp || y->fp_mant[0] != r->fp_mant[0] ||
128: y->fp_mant[1] != r->fp_mant[1] ||
129: y->fp_mant[2] != r->fp_mant[2]) {
130:
131: /* Step 3.2 */
132: if (y->fp_exp < r->fp_exp || y->fp_mant[0] < r->fp_mant[0] ||
133: y->fp_mant[1] < r->fp_mant[1] ||
134: y->fp_mant[2] < r->fp_mant[2]) {
135: CPYFPN(&fe->fe_f1, r);
136: CPYFPN(&fe->fe_f2, y);
137: fe->fe_f2.fp_sign = 1;
138: r = fpu_add(fe);
139: q++;
140: }
141:
142: /* Step 3.3 */
143: if (j == 0)
144: goto Step4;
145:
146: /* Step 3.4 */
147: k++;
148: j--;
149: q += q;
150: r->fp_exp++;
151: }
152: /* Step 9 */
153: goto Step9;
154: }
155: Step4:
156: Last_Subtract = 0;
157: if (modrem == 0)
158: goto Step6;
159:
160: /*
161: * Step 5
162: */
163: /* Step 5.1 */
164: if (r->fp_exp + 1 < y->fp_exp ||
165: (r->fp_exp + 1 == y->fp_exp &&
166: (r->fp_mant[0] < y->fp_mant[0] || r->fp_mant[1] < y->fp_mant[1] ||
167: r->fp_mant[2] < y->fp_mant[2])))
168: /* if r < y/2 */
169: goto Step6;
170: /* Step 5.2 */
171: if (r->fp_exp + 1 != y->fp_exp ||
172: r->fp_mant[0] != y->fp_mant[0] || r->fp_mant[1] != y->fp_mant[1] ||
173: r->fp_mant[2] != y->fp_mant[2]) {
174: /* if (!(r < y/2) && !(r == y/2)) */
175: Last_Subtract = 1;
176: q++;
177: y->fp_sign = signY;
178: } else {
179: /* Step 5.3 */
180: /* r == y/2 */
181: if (q % 2) {
182: q++;
183: signX = !signX;
184: }
185: }
186:
187: Step6:
188: r->fp_sign = signX;
189:
190: /*
191: * Step 7
192: */
193: if (Last_Subtract) {
194: CPYFPN(&fe->fe_f1, r);
195: CPYFPN(&fe->fe_f2, y);
196: fe->fe_f2.fp_sign = !y->fp_sign;
197: r = fpu_add(fe);
198: }
199: /*
200: * Step 8
201: */
202: q &= 0x7f;
203: q |= (signQ << 7);
204: fe->fe_fpframe->fpf_fpsr =
205: fe->fe_fpsr =
206: (fe->fe_fpsr & ~FPSR_QTT) | (q << 16);
207: return r;
208:
209: Step9:
210: fe->fe_f1.fp_class = FPC_ZERO;
211: q++;
212: q &= 0x7f;
213: q |= (signQ << 7);
214: fe->fe_fpframe->fpf_fpsr =
215: fe->fe_fpsr =
216: (fe->fe_fpsr & ~FPSR_QTT) | (q << 16);
217: return &fe->fe_f1;
218: }
219:
220: struct fpn *
221: fpu_rem(fe)
222: struct fpemu *fe;
223: {
224: return __fpu_modrem(fe, 1);
225: }
226:
227: struct fpn *
228: fpu_mod(fe)
229: struct fpemu *fe;
230: {
231: return __fpu_modrem(fe, 0);
232: }
CVSweb