1176491Smarcel/*	$NetBSD: fpu_div.c,v 1.4 2005/12/11 12:18:42 christos Exp $ */
2176491Smarcel
3331722Seadler/*
4176491Smarcel * Copyright (c) 1992, 1993
5176491Smarcel *	The Regents of the University of California.  All rights reserved.
6176491Smarcel *
7176491Smarcel * This software was developed by the Computer Systems Engineering group
8176491Smarcel * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9176491Smarcel * contributed to Berkeley.
10176491Smarcel *
11176491Smarcel * All advertising materials mentioning features or use of this software
12176491Smarcel * must display the following acknowledgement:
13176491Smarcel *	This product includes software developed by the University of
14176491Smarcel *	California, Lawrence Berkeley Laboratory.
15176491Smarcel *
16176491Smarcel * Redistribution and use in source and binary forms, with or without
17176491Smarcel * modification, are permitted provided that the following conditions
18176491Smarcel * are met:
19176491Smarcel * 1. Redistributions of source code must retain the above copyright
20176491Smarcel *    notice, this list of conditions and the following disclaimer.
21176491Smarcel * 2. Redistributions in binary form must reproduce the above copyright
22176491Smarcel *    notice, this list of conditions and the following disclaimer in the
23176491Smarcel *    documentation and/or other materials provided with the distribution.
24176491Smarcel * 3. Neither the name of the University nor the names of its contributors
25176491Smarcel *    may be used to endorse or promote products derived from this software
26176491Smarcel *    without specific prior written permission.
27176491Smarcel *
28176491Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29176491Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30176491Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31176491Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32176491Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33176491Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34176491Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35176491Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36176491Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37176491Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38176491Smarcel * SUCH DAMAGE.
39176491Smarcel *
40176491Smarcel *	@(#)fpu_div.c	8.1 (Berkeley) 6/11/93
41176491Smarcel */
42176491Smarcel
43176491Smarcel/*
44176491Smarcel * Perform an FPU divide (return x / y).
45176491Smarcel */
46176491Smarcel
47176491Smarcel#include <sys/cdefs.h>
48176491Smarcel__FBSDID("$FreeBSD$");
49176491Smarcel
50178030Sgrehan#include <sys/types.h>
51176491Smarcel#include <sys/systm.h>
52176491Smarcel
53176491Smarcel#include <machine/fpu.h>
54176491Smarcel#include <machine/reg.h>
55176491Smarcel
56176491Smarcel#include <powerpc/fpu/fpu_arith.h>
57176491Smarcel#include <powerpc/fpu/fpu_emu.h>
58176491Smarcel
59176491Smarcel/*
60176491Smarcel * Division of normal numbers is done as follows:
61176491Smarcel *
62176491Smarcel * x and y are floating point numbers, i.e., in the form 1.bbbb * 2^e.
63176491Smarcel * If X and Y are the mantissas (1.bbbb's), the quotient is then:
64176491Smarcel *
65176491Smarcel *	q = (X / Y) * 2^((x exponent) - (y exponent))
66176491Smarcel *
67176491Smarcel * Since X and Y are both in [1.0,2.0), the quotient's mantissa (X / Y)
68176491Smarcel * will be in [0.5,2.0).  Moreover, it will be less than 1.0 if and only
69176491Smarcel * if X < Y.  In that case, it will have to be shifted left one bit to
70176491Smarcel * become a normal number, and the exponent decremented.  Thus, the
71176491Smarcel * desired exponent is:
72176491Smarcel *
73176491Smarcel *	left_shift = x->fp_mant < y->fp_mant;
74176491Smarcel *	result_exp = x->fp_exp - y->fp_exp - left_shift;
75176491Smarcel *
76176491Smarcel * The quotient mantissa X/Y can then be computed one bit at a time
77176491Smarcel * using the following algorithm:
78176491Smarcel *
79176491Smarcel *	Q = 0;			-- Initial quotient.
80176491Smarcel *	R = X;			-- Initial remainder,
81176491Smarcel *	if (left_shift)		--   but fixed up in advance.
82176491Smarcel *		R *= 2;
83176491Smarcel *	for (bit = FP_NMANT; --bit >= 0; R *= 2) {
84176491Smarcel *		if (R >= Y) {
85176491Smarcel *			Q |= 1 << bit;
86176491Smarcel *			R -= Y;
87176491Smarcel *		}
88176491Smarcel *	}
89176491Smarcel *
90176491Smarcel * The subtraction R -= Y always removes the uppermost bit from R (and
91176491Smarcel * can sometimes remove additional lower-order 1 bits); this proof is
92176491Smarcel * left to the reader.
93176491Smarcel *
94176491Smarcel * This loop correctly calculates the guard and round bits since they are
95176491Smarcel * included in the expanded internal representation.  The sticky bit
96176491Smarcel * is to be set if and only if any other bits beyond guard and round
97176491Smarcel * would be set.  From the above it is obvious that this is true if and
98176491Smarcel * only if the remainder R is nonzero when the loop terminates.
99176491Smarcel *
100176491Smarcel * Examining the loop above, we can see that the quotient Q is built
101176491Smarcel * one bit at a time ``from the top down''.  This means that we can
102176491Smarcel * dispense with the multi-word arithmetic and just build it one word
103176491Smarcel * at a time, writing each result word when it is done.
104176491Smarcel *
105176491Smarcel * Furthermore, since X and Y are both in [1.0,2.0), we know that,
106176491Smarcel * initially, R >= Y.  (Recall that, if X < Y, R is set to X * 2 and
107176491Smarcel * is therefore at in [2.0,4.0).)  Thus Q is sure to have bit FP_NMANT-1
108176491Smarcel * set, and R can be set initially to either X - Y (when X >= Y) or
109176491Smarcel * 2X - Y (when X < Y).  In addition, comparing R and Y is difficult,
110176491Smarcel * so we will simply calculate R - Y and see if that underflows.
111176491Smarcel * This leads to the following revised version of the algorithm:
112176491Smarcel *
113176491Smarcel *	R = X;
114176491Smarcel *	bit = FP_1;
115176491Smarcel *	D = R - Y;
116176491Smarcel *	if (D >= 0) {
117176491Smarcel *		result_exp = x->fp_exp - y->fp_exp;
118176491Smarcel *		R = D;
119176491Smarcel *		q = bit;
120176491Smarcel *		bit >>= 1;
121176491Smarcel *	} else {
122176491Smarcel *		result_exp = x->fp_exp - y->fp_exp - 1;
123176491Smarcel *		q = 0;
124176491Smarcel *	}
125176491Smarcel *	R <<= 1;
126176491Smarcel *	do  {
127176491Smarcel *		D = R - Y;
128176491Smarcel *		if (D >= 0) {
129176491Smarcel *			q |= bit;
130176491Smarcel *			R = D;
131176491Smarcel *		}
132176491Smarcel *		R <<= 1;
133176491Smarcel *	} while ((bit >>= 1) != 0);
134176491Smarcel *	Q[0] = q;
135176491Smarcel *	for (i = 1; i < 4; i++) {
136176491Smarcel *		q = 0, bit = 1 << 31;
137176491Smarcel *		do {
138176491Smarcel *			D = R - Y;
139176491Smarcel *			if (D >= 0) {
140176491Smarcel *				q |= bit;
141176491Smarcel *				R = D;
142176491Smarcel *			}
143176491Smarcel *			R <<= 1;
144176491Smarcel *		} while ((bit >>= 1) != 0);
145176491Smarcel *		Q[i] = q;
146176491Smarcel *	}
147176491Smarcel *
148176491Smarcel * This can be refined just a bit further by moving the `R <<= 1'
149176491Smarcel * calculations to the front of the do-loops and eliding the first one.
150176491Smarcel * The process can be terminated immediately whenever R becomes 0, but
151176491Smarcel * this is relatively rare, and we do not bother.
152176491Smarcel */
153176491Smarcel
154176491Smarcelstruct fpn *
155176491Smarcelfpu_div(struct fpemu *fe)
156176491Smarcel{
157176491Smarcel	struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
158176491Smarcel	u_int q, bit;
159176491Smarcel	u_int r0, r1, r2, r3, d0, d1, d2, d3, y0, y1, y2, y3;
160176491Smarcel	FPU_DECL_CARRY
161176491Smarcel
162176491Smarcel	/*
163176491Smarcel	 * Since divide is not commutative, we cannot just use ORDER.
164176491Smarcel	 * Check either operand for NaN first; if there is at least one,
165176491Smarcel	 * order the signalling one (if only one) onto the right, then
166176491Smarcel	 * return it.  Otherwise we have the following cases:
167176491Smarcel	 *
168176491Smarcel	 *	Inf / Inf = NaN, plus NV exception
169176491Smarcel	 *	Inf / num = Inf [i.e., return x]
170176491Smarcel	 *	Inf / 0   = Inf [i.e., return x]
171176491Smarcel	 *	0 / Inf = 0 [i.e., return x]
172176491Smarcel	 *	0 / num = 0 [i.e., return x]
173176491Smarcel	 *	0 / 0   = NaN, plus NV exception
174176491Smarcel	 *	num / Inf = 0
175176491Smarcel	 *	num / num = num (do the divide)
176176491Smarcel	 *	num / 0   = Inf, plus DZ exception
177176491Smarcel	 */
178176491Smarcel	DPRINTF(FPE_REG, ("fpu_div:\n"));
179176491Smarcel	DUMPFPN(FPE_REG, x);
180176491Smarcel	DUMPFPN(FPE_REG, y);
181176491Smarcel	DPRINTF(FPE_REG, ("=>\n"));
182176491Smarcel	if (ISNAN(x) || ISNAN(y)) {
183176491Smarcel		ORDER(x, y);
184176491Smarcel		fe->fe_cx |= FPSCR_VXSNAN;
185176491Smarcel		DUMPFPN(FPE_REG, y);
186176491Smarcel		return (y);
187176491Smarcel	}
188176491Smarcel	/*
189176491Smarcel	 * Need to split the following out cause they generate different
190176491Smarcel	 * exceptions.
191176491Smarcel	 */
192176491Smarcel	if (ISINF(x)) {
193176491Smarcel		if (x->fp_class == y->fp_class) {
194176491Smarcel			fe->fe_cx |= FPSCR_VXIDI;
195176491Smarcel			return (fpu_newnan(fe));
196176491Smarcel		}
197176491Smarcel		DUMPFPN(FPE_REG, x);
198176491Smarcel		return (x);
199176491Smarcel	}
200176491Smarcel	if (ISZERO(x)) {
201176491Smarcel		fe->fe_cx |= FPSCR_ZX;
202176491Smarcel		if (x->fp_class == y->fp_class) {
203176491Smarcel			fe->fe_cx |= FPSCR_VXZDZ;
204176491Smarcel			return (fpu_newnan(fe));
205176491Smarcel		}
206176491Smarcel		DUMPFPN(FPE_REG, x);
207176491Smarcel		return (x);
208176491Smarcel	}
209176491Smarcel
210176491Smarcel	/* all results at this point use XOR of operand signs */
211176491Smarcel	x->fp_sign ^= y->fp_sign;
212176491Smarcel	if (ISINF(y)) {
213176491Smarcel		x->fp_class = FPC_ZERO;
214176491Smarcel		DUMPFPN(FPE_REG, x);
215176491Smarcel		return (x);
216176491Smarcel	}
217176491Smarcel	if (ISZERO(y)) {
218176491Smarcel		fe->fe_cx = FPSCR_ZX;
219176491Smarcel		x->fp_class = FPC_INF;
220176491Smarcel		DUMPFPN(FPE_REG, x);
221176491Smarcel		return (x);
222176491Smarcel	}
223176491Smarcel
224176491Smarcel	/*
225176491Smarcel	 * Macros for the divide.  See comments at top for algorithm.
226176491Smarcel	 * Note that we expand R, D, and Y here.
227176491Smarcel	 */
228176491Smarcel
229176491Smarcel#define	SUBTRACT		/* D = R - Y */ \
230176491Smarcel	FPU_SUBS(d3, r3, y3); FPU_SUBCS(d2, r2, y2); \
231176491Smarcel	FPU_SUBCS(d1, r1, y1); FPU_SUBC(d0, r0, y0)
232176491Smarcel
233176491Smarcel#define	NONNEGATIVE		/* D >= 0 */ \
234176491Smarcel	((int)d0 >= 0)
235176491Smarcel
236176491Smarcel#ifdef FPU_SHL1_BY_ADD
237176491Smarcel#define	SHL1			/* R <<= 1 */ \
238176491Smarcel	FPU_ADDS(r3, r3, r3); FPU_ADDCS(r2, r2, r2); \
239176491Smarcel	FPU_ADDCS(r1, r1, r1); FPU_ADDC(r0, r0, r0)
240176491Smarcel#else
241176491Smarcel#define	SHL1 \
242176491Smarcel	r0 = (r0 << 1) | (r1 >> 31), r1 = (r1 << 1) | (r2 >> 31), \
243176491Smarcel	r2 = (r2 << 1) | (r3 >> 31), r3 <<= 1
244176491Smarcel#endif
245176491Smarcel
246176491Smarcel#define	LOOP			/* do ... while (bit >>= 1) */ \
247176491Smarcel	do { \
248176491Smarcel		SHL1; \
249176491Smarcel		SUBTRACT; \
250176491Smarcel		if (NONNEGATIVE) { \
251176491Smarcel			q |= bit; \
252176491Smarcel			r0 = d0, r1 = d1, r2 = d2, r3 = d3; \
253176491Smarcel		} \
254176491Smarcel	} while ((bit >>= 1) != 0)
255176491Smarcel
256176491Smarcel#define	WORD(r, i)			/* calculate r->fp_mant[i] */ \
257176491Smarcel	q = 0; \
258176491Smarcel	bit = 1 << 31; \
259176491Smarcel	LOOP; \
260176491Smarcel	(x)->fp_mant[i] = q
261176491Smarcel
262176491Smarcel	/* Setup.  Note that we put our result in x. */
263176491Smarcel	r0 = x->fp_mant[0];
264176491Smarcel	r1 = x->fp_mant[1];
265176491Smarcel	r2 = x->fp_mant[2];
266176491Smarcel	r3 = x->fp_mant[3];
267176491Smarcel	y0 = y->fp_mant[0];
268176491Smarcel	y1 = y->fp_mant[1];
269176491Smarcel	y2 = y->fp_mant[2];
270176491Smarcel	y3 = y->fp_mant[3];
271176491Smarcel
272176491Smarcel	bit = FP_1;
273176491Smarcel	SUBTRACT;
274176491Smarcel	if (NONNEGATIVE) {
275176491Smarcel		x->fp_exp -= y->fp_exp;
276176491Smarcel		r0 = d0, r1 = d1, r2 = d2, r3 = d3;
277176491Smarcel		q = bit;
278176491Smarcel		bit >>= 1;
279176491Smarcel	} else {
280176491Smarcel		x->fp_exp -= y->fp_exp + 1;
281176491Smarcel		q = 0;
282176491Smarcel	}
283176491Smarcel	LOOP;
284176491Smarcel	x->fp_mant[0] = q;
285176491Smarcel	WORD(x, 1);
286176491Smarcel	WORD(x, 2);
287176491Smarcel	WORD(x, 3);
288176491Smarcel	x->fp_sticky = r0 | r1 | r2 | r3;
289176491Smarcel
290176491Smarcel	DUMPFPN(FPE_REG, x);
291176491Smarcel	return (x);
292176491Smarcel}
293