MIPS: math-emu: Add support for the MIPS R6 CLASS FPU instruction
authorMarkos Chandras <markos.chandras@imgtec.com>
Thu, 13 Aug 2015 07:56:34 +0000 (09:56 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 3 Sep 2015 10:08:14 +0000 (12:08 +0200)
MIPS R6 introduced the following instruction:
Stores in fd a bit mask reflecting the floating-point class of the
floating point scalar value fs.

CLASS.fmt: FPR[fd] = class(FPR[fs])

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/10959/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/math-emu/Makefile
arch/mips/math-emu/cp1emu.c
arch/mips/math-emu/dp_2008class.c [new file with mode: 0644]
arch/mips/math-emu/ieee754.h
arch/mips/math-emu/sp_2008class.c [new file with mode: 0644]

index 0037690521eebc7bf10d681a7b23f26038a762ed..ea8db2607d0760e0b994920ed2f4cdc7b95a7f07 100644 (file)
@@ -4,9 +4,9 @@
 
 obj-y  += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \
           dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \
-          dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o \
+          dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o dp_2008class.o \
           sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \
-          sp_tint.o sp_fint.o sp_maddf.o sp_msubf.o \
+          sp_tint.o sp_fint.o sp_maddf.o sp_msubf.o sp_2008class.o \
           dsemul.o
 
 lib-y  += ieee754d.o \
index a348cbefe4a8ef17e75c4f6382057ca283146a96..b65b4ea60232873d45db2b5e26f0967ad7b3122f 100644 (file)
@@ -1803,6 +1803,18 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        goto copcsr;
                }
 
+               case fclass_op: {
+                       union ieee754sp fs;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       SPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.w = ieee754sp_2008class(fs);
+                       rfmt = w_fmt;
+                       break;
+               }
+
                case fabs_op:
                        handler.u = ieee754sp_abs;
                        goto scopuop;
@@ -2061,6 +2073,18 @@ copcsr:
                        goto copcsr;
                }
 
+               case fclass_op: {
+                       union ieee754dp fs;
+
+                       if (!cpu_has_mips_r6)
+                               return SIGILL;
+
+                       DPFROMREG(fs, MIPSInst_FS(ir));
+                       rv.w = ieee754dp_2008class(fs);
+                       rfmt = w_fmt;
+                       break;
+               }
+
                case fabs_op:
                        handler.u = ieee754dp_abs;
                        goto dcopuop;
diff --git a/arch/mips/math-emu/dp_2008class.c b/arch/mips/math-emu/dp_2008class.c
new file mode 100644 (file)
index 0000000..9dc39fc
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * IEEE754 floating point arithmetic
+ * double precision: CLASS.f
+ * FPR[fd] = class(FPR[fs])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754dp.h"
+
+int ieee754dp_2008class(union ieee754dp x)
+{
+       COMPXDP;
+
+       EXPLODEXDP;
+
+       /*
+        * 10 bit mask as follows:
+        *
+        * bit0 = SNAN
+        * bit1 = QNAN
+        * bit2 = -INF
+        * bit3 = -NORM
+        * bit4 = -DNORM
+        * bit5 = -ZERO
+        * bit6 = INF
+        * bit7 = NORM
+        * bit8 = DNORM
+        * bit9 = ZERO
+        */
+
+       switch(xc) {
+       case IEEE754_CLASS_SNAN:
+               return 0x01;
+       case IEEE754_CLASS_QNAN:
+               return 0x02;
+       case IEEE754_CLASS_INF:
+               return 0x04 << (xs ? 0 : 4);
+       case IEEE754_CLASS_NORM:
+               return 0x08 << (xs ? 0 : 4);
+       case IEEE754_CLASS_DNORM:
+               return 0x10 << (xs ? 0 : 4);
+       case IEEE754_CLASS_ZERO:
+               return 0x20 << (xs ? 0 : 4);
+       default:
+               pr_err("Unknown class: %d\n", xc);
+               return 0;
+       }
+}
index 8c780190a05922b22ae9ab0416c437b829e5259e..3b833eac48f52834f20820f02242e6191f13b160 100644 (file)
@@ -79,6 +79,7 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
                                union ieee754sp y);
 union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
                                union ieee754sp y);
+int ieee754sp_2008class(union ieee754sp x);
 
 /*
  * double precision (often aka double)
@@ -108,6 +109,7 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
                                union ieee754dp y);
 union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
                                union ieee754dp y);
+int ieee754dp_2008class(union ieee754dp x);
 
 
 /* 5 types of floating point number
diff --git a/arch/mips/math-emu/sp_2008class.c b/arch/mips/math-emu/sp_2008class.c
new file mode 100644 (file)
index 0000000..ff62606
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * IEEE754 floating point arithmetic
+ * single precision: CLASS.f
+ * FPR[fd] = class(FPR[fs])
+ *
+ * MIPS floating point support
+ * Copyright (C) 2015 Imagination Technologies, Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; version 2 of the License.
+ */
+
+#include "ieee754sp.h"
+
+int ieee754sp_2008class(union ieee754sp x)
+{
+       COMPXSP;
+
+       EXPLODEXSP;
+
+       /*
+        * 10 bit mask as follows:
+        *
+        * bit0 = SNAN
+        * bit1 = QNAN
+        * bit2 = -INF
+        * bit3 = -NORM
+        * bit4 = -DNORM
+        * bit5 = -ZERO
+        * bit6 = INF
+        * bit7 = NORM
+        * bit8 = DNORM
+        * bit9 = ZERO
+        */
+
+       switch(xc) {
+       case IEEE754_CLASS_SNAN:
+               return 0x01;
+       case IEEE754_CLASS_QNAN:
+               return 0x02;
+       case IEEE754_CLASS_INF:
+               return 0x04 << (xs ? 0 : 4);
+       case IEEE754_CLASS_NORM:
+               return 0x08 << (xs ? 0 : 4);
+       case IEEE754_CLASS_DNORM:
+               return 0x10 << (xs ? 0 : 4);
+       case IEEE754_CLASS_ZERO:
+               return 0x20 << (xs ? 0 : 4);
+       default:
+               pr_err("Unknown class: %d\n", xc);
+               return 0;
+       }
+}