summaryrefslogtreecommitdiffstats
path: root/kernel/arch/mips/math-emu/sp_sqrt.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/arch/mips/math-emu/sp_sqrt.c')
-rw-r--r--kernel/arch/mips/math-emu/sp_sqrt.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/kernel/arch/mips/math-emu/sp_sqrt.c b/kernel/arch/mips/math-emu/sp_sqrt.c
new file mode 100644
index 000000000..67059c33a
--- /dev/null
+++ b/kernel/arch/mips/math-emu/sp_sqrt.c
@@ -0,0 +1,114 @@
+/* IEEE754 floating point arithmetic
+ * single precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "ieee754sp.h"
+
+union ieee754sp ieee754sp_sqrt(union ieee754sp x)
+{
+ int ix, s, q, m, t, i;
+ unsigned int r;
+ COMPXSP;
+
+ /* take care of Inf and NaN */
+
+ EXPLODEXSP;
+ ieee754_clearcx();
+ FLUSHXSP;
+
+ /* x == INF or NAN? */
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754sp_nanxcpt(x);
+
+ case IEEE754_CLASS_QNAN:
+ /* sqrt(Nan) = Nan */
+ return x;
+
+ case IEEE754_CLASS_ZERO:
+ /* sqrt(0) = 0 */
+ return x;
+
+ case IEEE754_CLASS_INF:
+ if (xs) {
+ /* sqrt(-Inf) = Nan */
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
+ }
+ /* sqrt(+Inf) = Inf */
+ return x;
+
+ case IEEE754_CLASS_DNORM:
+ case IEEE754_CLASS_NORM:
+ if (xs) {
+ /* sqrt(-x) = Nan */
+ ieee754_setcx(IEEE754_INVALID_OPERATION);
+ return ieee754sp_indef();
+ }
+ break;
+ }
+
+ ix = x.bits;
+
+ /* normalize x */
+ m = (ix >> 23);
+ if (m == 0) { /* subnormal x */
+ for (i = 0; (ix & 0x00800000) == 0; i++)
+ ix <<= 1;
+ m -= i - 1;
+ }
+ m -= 127; /* unbias exponent */
+ ix = (ix & 0x007fffff) | 0x00800000;
+ if (m & 1) /* odd m, double x to make it even */
+ ix += ix;
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix += ix;
+ q = s = 0; /* q = sqrt(x) */
+ r = 0x01000000; /* r = moving bit from right to left */
+
+ while (r != 0) {
+ t = s + r;
+ if (t <= ix) {
+ s = t + r;
+ ix -= t;
+ q += r;
+ }
+ ix += ix;
+ r >>= 1;
+ }
+
+ if (ix != 0) {
+ ieee754_setcx(IEEE754_INEXACT);
+ switch (ieee754_csr.rm) {
+ case FPU_CSR_RU:
+ q += 2;
+ break;
+ case FPU_CSR_RN:
+ q += (q & 1);
+ break;
+ }
+ }
+ ix = (q >> 1) + 0x3f000000;
+ ix += (m << 23);
+ x.bits = ix;
+ return x;
+}