1/* IEEE754 floating point arithmetic
2 * single precision square root
3 */
4/*
5 * MIPS floating point support
6 * Copyright (C) 1994-2000 Algorithmics Ltd.
7 *
8 *  This program is free software; you can distribute it and/or modify it
9 *  under the terms of the GNU General Public License (Version 2) as
10 *  published by the Free Software Foundation.
11 *
12 *  This program is distributed in the hope it will be useful, but WITHOUT
13 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 *  for more details.
16 *
17 *  You should have received a copy of the GNU General Public License along
18 *  with this program; if not, write to the Free Software Foundation, Inc.,
19 *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
20 */
21
22#include "ieee754sp.h"
23
24union ieee754sp ieee754sp_sqrt(union ieee754sp x)
25{
26	int ix, s, q, m, t, i;
27	unsigned int r;
28	COMPXSP;
29
30	/* take care of Inf and NaN */
31
32	EXPLODEXSP;
33	ieee754_clearcx();
34	FLUSHXSP;
35
36	/* x == INF or NAN? */
37	switch (xc) {
38	case IEEE754_CLASS_SNAN:
39		return ieee754sp_nanxcpt(x);
40
41	case IEEE754_CLASS_QNAN:
42		/* sqrt(Nan) = Nan */
43		return x;
44
45	case IEEE754_CLASS_ZERO:
46		/* sqrt(0) = 0 */
47		return x;
48
49	case IEEE754_CLASS_INF:
50		if (xs) {
51			/* sqrt(-Inf) = Nan */
52			ieee754_setcx(IEEE754_INVALID_OPERATION);
53			return ieee754sp_indef();
54		}
55		/* sqrt(+Inf) = Inf */
56		return x;
57
58	case IEEE754_CLASS_DNORM:
59	case IEEE754_CLASS_NORM:
60		if (xs) {
61			/* sqrt(-x) = Nan */
62			ieee754_setcx(IEEE754_INVALID_OPERATION);
63			return ieee754sp_indef();
64		}
65		break;
66	}
67
68	ix = x.bits;
69
70	/* normalize x */
71	m = (ix >> 23);
72	if (m == 0) {		/* subnormal x */
73		for (i = 0; (ix & 0x00800000) == 0; i++)
74			ix <<= 1;
75		m -= i - 1;
76	}
77	m -= 127;		/* unbias exponent */
78	ix = (ix & 0x007fffff) | 0x00800000;
79	if (m & 1)		/* odd m, double x to make it even */
80		ix += ix;
81	m >>= 1;		/* m = [m/2] */
82
83	/* generate sqrt(x) bit by bit */
84	ix += ix;
85	q = s = 0;		/* q = sqrt(x) */
86	r = 0x01000000;		/* r = moving bit from right to left */
87
88	while (r != 0) {
89		t = s + r;
90		if (t <= ix) {
91			s = t + r;
92			ix -= t;
93			q += r;
94		}
95		ix += ix;
96		r >>= 1;
97	}
98
99	if (ix != 0) {
100		ieee754_setcx(IEEE754_INEXACT);
101		switch (ieee754_csr.rm) {
102		case FPU_CSR_RU:
103			q += 2;
104			break;
105		case FPU_CSR_RN:
106			q += (q & 1);
107			break;
108		}
109	}
110	ix = (q >> 1) + 0x3f000000;
111	ix += (m << 23);
112	x.bits = ix;
113	return x;
114}
115