[patch][2/5] powerpc V2: Add the implementations to handle DPFP instruction exceptions
ebony.zhu at freescale.com
ebony.zhu at freescale.com
Thu Feb 8 14:52:42 EST 2007
Add the implementations to handle DPFP instruction exceptions
complying with IEEE-754.
Signed-off-by:Ebony Zhu <ebony.zhu at freescale.com>
---
arch/powerpc/math-emu/efdadd.c | 36 ++++++++++++++++++++++++++++++
arch/powerpc/math-emu/efdcfs.c | 31 +++++++++++++++++++++++++
arch/powerpc/math-emu/efdcmpeq.c | 45 +++++++++++++++++++++++++++++++++++++
arch/powerpc/math-emu/efdcmpgt.c | 45 +++++++++++++++++++++++++++++++++++++
arch/powerpc/math-emu/efdcmplt.c | 45 +++++++++++++++++++++++++++++++++++++
arch/powerpc/math-emu/efdctsf.c | 30 +++++++++++++++++++++++++
arch/powerpc/math-emu/efdctsi.c | 27 ++++++++++++++++++++++
arch/powerpc/math-emu/efdctsidz.c | 29 ++++++++++++++++++++++++
arch/powerpc/math-emu/efdctsiz.c | 27 ++++++++++++++++++++++
arch/powerpc/math-emu/efdctuf.c | 29 ++++++++++++++++++++++++
arch/powerpc/math-emu/efdctui.c | 27 ++++++++++++++++++++++
arch/powerpc/math-emu/efdctuidz.c | 28 +++++++++++++++++++++++
arch/powerpc/math-emu/efdctuiz.c | 27 ++++++++++++++++++++++
arch/powerpc/math-emu/efddiv.c | 36 ++++++++++++++++++++++++++++++
arch/powerpc/math-emu/efdmul.c | 39 ++++++++++++++++++++++++++++++++
arch/powerpc/math-emu/efdnabs.c | 18 +++++++++++++++
arch/powerpc/math-emu/efdsub.c | 39 ++++++++++++++++++++++++++++++++
17 files changed, 558 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/math-emu/efdadd.c b/arch/powerpc/math-emu/efdadd.c
new file mode 100644
index 0000000..e7b7f77
--- /dev/null
+++ b/arch/powerpc/math-emu/efdadd.c
@@ -0,0 +1,36 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdadd(void *rD, void *rA, void *rB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, rD, rA, rB);
+#endif
+
+ __FP_UNPACK_D(A, rA);
+ __FP_UNPACK_D(B, rB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(rD, R));
+}
diff --git a/arch/powerpc/math-emu/efdcfs.c b/arch/powerpc/math-emu/efdcfs.c
new file mode 100644
index 0000000..b55dbc8
--- /dev/null
+++ b/arch/powerpc/math-emu/efdcfs.c
@@ -0,0 +1,31 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+efdcfs(void *rD, u32 *rB)
+{
+ FP_DECL_S(B);
+ FP_DECL_D(R);
+ int ret;
+ rB[0]=rB[1];
+
+ __FP_UNPACK_S(B, rB);
+
+#ifdef DEBUG
+ printk("B: %ld %lu %ld (%ld)\n", B_s, B_f, B_e, B_c);
+#endif
+
+ FP_CONV(D, S, 2, 1, R, B);
+
+#ifdef DEBUG
+ printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(rD, R));
+}
diff --git a/arch/powerpc/math-emu/efdcmpeq.c b/arch/powerpc/math-emu/efdcmpeq.c
new file mode 100644
index 0000000..01c5071
--- /dev/null
+++ b/arch/powerpc/math-emu/efdcmpeq.c
@@ -0,0 +1,45 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdcmpeq(u32 *ccr, int crD, void *rA, void *rB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ long cmp;
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crD, rA, rB);
+#endif
+
+ __FP_UNPACK_D(A, rA);
+ __FP_UNPACK_D(B, rB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ FP_CMP_D(cmp, A, B, 2);
+
+ if (cmp == 0) {
+ cmp = 0x4;
+ } else {
+ cmp = 0;
+ }
+
+ *ccr &= ~(15 << ((7 - crD) << 2));
+ *ccr |= (cmp << ((7 - crD) << 2));
+
+#ifdef DEBUG
+ printk("CR: %08x\n", *ccr);
+#endif
+
+ return ret;
+}
diff --git a/arch/powerpc/math-emu/efdcmpgt.c b/arch/powerpc/math-emu/efdcmpgt.c
new file mode 100644
index 0000000..44da1c5
--- /dev/null
+++ b/arch/powerpc/math-emu/efdcmpgt.c
@@ -0,0 +1,45 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdcmpgt(u32 *ccr, int crD, void *rA, void *rB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ long cmp;
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crD, rA, rB);
+#endif
+
+ __FP_UNPACK_D(A, rA);
+ __FP_UNPACK_D(B, rB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ FP_CMP_D(cmp, A, B, 2);
+
+ if (cmp == 1) {
+ cmp = 0x4;
+ } else {
+ cmp = 0;
+ }
+
+ *ccr &= ~(15 << ((7 - crD) << 2));
+ *ccr |= (cmp << ((7 - crD) << 2));
+
+#ifdef DEBUG
+ printk("CR: %08x\n", *ccr);
+#endif
+
+ return ret;
+}
diff --git a/arch/powerpc/math-emu/efdcmplt.c b/arch/powerpc/math-emu/efdcmplt.c
new file mode 100644
index 0000000..30cea42
--- /dev/null
+++ b/arch/powerpc/math-emu/efdcmplt.c
@@ -0,0 +1,45 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdcmplt(u32 *ccr, int crD, void *rA, void *rB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ long cmp;
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crD, rA, rB);
+#endif
+
+ __FP_UNPACK_D(A, rA);
+ __FP_UNPACK_D(B, rB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ FP_CMP_D(cmp, A, B, 2);
+
+ if (cmp == -1) {
+ cmp = 0x4;
+ } else {
+ cmp = 0;
+ }
+
+ *ccr &= ~(15 << ((7 - crD) << 2));
+ *ccr |= (cmp << ((7 - crD) << 2));
+
+#ifdef DEBUG
+ printk("CR: %08x\n", *ccr);
+#endif
+
+ return ret;
+}
diff --git a/arch/powerpc/math-emu/efdctsf.c b/arch/powerpc/math-emu/efdctsf.c
new file mode 100644
index 0000000..317c894
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctsf.c
@@ -0,0 +1,30 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "single.h"
+#include "double.h"
+
+int
+efdctsf(u32 *rD, u32 *rB)
+{
+ if (!((rB[0] >> 20) == 0x7ff && ((rB[0] & 0xfffff) > 0 || (rB[1] > 0)))) {/* Not an NaN */
+ if (((rB[0] >> 20) & 0x7ff) == 0 ) { /* rB is Denorm */
+ rD[1] = 0x0;
+ } else if ((rB[0] >> 31) == 0) { /* rB is positive normal */
+ rD[1] = 0x7fffffff;
+ } else { /* rB is negative normal */
+ rD[1] = 0x80000000;
+ }
+ } else { /* rB is NaN */
+ rD[1] = 0x0;
+ }
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdctsi.c b/arch/powerpc/math-emu/efdctsi.c
new file mode 100644
index 0000000..eaa7bf5
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctsi.c
@@ -0,0 +1,27 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdctsi(u32 *rD, void *rB)
+{
+ FP_DECL_D(B);
+ unsigned int r;
+
+ __FP_UNPACK_D(B, rB);
+ _FP_ROUND(2, B);
+ FP_TO_INT_D(r, B, 32, 1);
+ rD[1] = r;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ dump_double(rD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdctsidz.c b/arch/powerpc/math-emu/efdctsidz.c
new file mode 100644
index 0000000..4166c86
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctsidz.c
@@ -0,0 +1,29 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdctsidz(u32 *rD, void *rB)
+{
+ FP_DECL_D(B);
+ u32 spefscr;
+ u64 r;
+
+ __FP_UNPACK_D(B, rB);
+ _FP_ROUND_ZERO(2, B);
+ FP_TO_INT_D(r, B, 64, 1);
+ rD[1] = r;
+ rD[0] = r >> 32;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ dump_double(rD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdctsiz.c b/arch/powerpc/math-emu/efdctsiz.c
new file mode 100644
index 0000000..9bf5d44
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctsiz.c
@@ -0,0 +1,27 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdctsiz(u32 *rD, void *rB)
+{
+ FP_DECL_D(B);
+ unsigned int r;
+
+ __FP_UNPACK_D(B, rB);
+ _FP_ROUND_ZERO(2, B);
+ FP_TO_INT_D(r, B, 32, 1);
+ rD[1] = r;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ dump_double(rD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdctuf.c b/arch/powerpc/math-emu/efdctuf.c
new file mode 100644
index 0000000..8e54e92
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctuf.c
@@ -0,0 +1,29 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "single.h"
+#include "double.h"
+
+int
+efdctuf(u32 *rD, u32 *rB)
+{
+ if (!((rB[0] >> 20) == 0x7ff && ((rB[0] & 0xfffff) > 0 || (rB[1] > 0))) /* Not an NaN */
+ && (rB[0] >> 31) == 0) { /* rB is positive */
+ if (((rB[0] >> 20) & 0x7ff) == 0 ) { /* rB is Denorm */
+ rD[1] = 0x0;
+ } else { /* rB is normal */
+ rD[1] = 0xffffffff;
+ }
+ } else { /* rB < 0 or rB is NaN */
+ rD[1] = 0x0;
+ }
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdctui.c b/arch/powerpc/math-emu/efdctui.c
new file mode 100644
index 0000000..8779a2c
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctui.c
@@ -0,0 +1,27 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdctui(u32 *rD, void *rB)
+{
+ FP_DECL_D(B);
+ unsigned int r;
+
+ __FP_UNPACK_D(B, rB);
+ _FP_ROUND(2, B);
+ FP_TO_INT_D(r, B, 32, 0);
+ rD[1] = r;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ dump_double(rD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdctuidz.c b/arch/powerpc/math-emu/efdctuidz.c
new file mode 100644
index 0000000..7f3d4f9
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctuidz.c
@@ -0,0 +1,28 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdctuidz(u32 *rD, void *rB)
+{
+ FP_DECL_D(B);
+ u64 r;
+
+ __FP_UNPACK_D(B, rB);
+ _FP_ROUND_ZERO(2, B);
+ FP_TO_INT_D(r, B, 64, 0);
+ rD[1] = r;
+ rD[0] = r >> 32;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ dump_double(rD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdctuiz.c b/arch/powerpc/math-emu/efdctuiz.c
new file mode 100644
index 0000000..795dff0
--- /dev/null
+++ b/arch/powerpc/math-emu/efdctuiz.c
@@ -0,0 +1,27 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdctuiz(u32 *rD, void *rB)
+{
+ FP_DECL_D(B);
+ unsigned int r;
+
+ __FP_UNPACK_D(B, rB);
+ _FP_ROUND_ZERO(2, B);
+ FP_TO_INT_D(r, B, 32, 0);
+ rD[1] = r;
+
+#ifdef DEBUG
+ printk("%s: D %p, B %p: ", __FUNCTION__, rD, rB);
+ dump_double(rD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efddiv.c b/arch/powerpc/math-emu/efddiv.c
new file mode 100644
index 0000000..3d92167
--- /dev/null
+++ b/arch/powerpc/math-emu/efddiv.c
@@ -0,0 +1,36 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efddiv(void *rD, void *rA, void *rB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, rD, rA, rB);
+#endif
+
+ __FP_UNPACK_D(A, rA);
+ __FP_UNPACK_D(B, rB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ FP_DIV_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(rD, R));
+}
diff --git a/arch/powerpc/math-emu/efdmul.c b/arch/powerpc/math-emu/efdmul.c
new file mode 100644
index 0000000..2813587
--- /dev/null
+++ b/arch/powerpc/math-emu/efdmul.c
@@ -0,0 +1,39 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdmul(void *rD, void *rA, void *rB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, rD, rA, rB);
+#endif
+
+ __FP_UNPACK_D(A, rA);
+ __FP_UNPACK_D(B, rB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023);
+ printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023);
+#endif
+
+ FP_MUL_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+ R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023);
+#endif
+
+ return (ret | __FP_PACK_D(rD, R));
+}
diff --git a/arch/powerpc/math-emu/efdnabs.c b/arch/powerpc/math-emu/efdnabs.c
new file mode 100644
index 0000000..d0cdc55
--- /dev/null
+++ b/arch/powerpc/math-emu/efdnabs.c
@@ -0,0 +1,18 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+efdnabs(u32 *rD, u32 *rA)
+{
+ rD[0] = rA[0] | 0x80000000;
+ rD[1] = rA[1];
+
+#ifdef DEBUG
+ printk("%s: D %p, A %p: ", __FUNCTION__, rD, rA);
+ dump_double(rD);
+ printk("\n");
+#endif
+
+ return 0;
+}
diff --git a/arch/powerpc/math-emu/efdsub.c b/arch/powerpc/math-emu/efdsub.c
new file mode 100644
index 0000000..72f6e45
--- /dev/null
+++ b/arch/powerpc/math-emu/efdsub.c
@@ -0,0 +1,39 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "spe.h"
+#include "soft-fp.h"
+#include "double.h"
+
+int
+efdsub(void *rD, void *rA, void *rB)
+{
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(R);
+ int ret = 0;
+
+#ifdef DEBUG
+ printk("%s: %p %p %p\n", __FUNCTION__, rD, rA, rB);
+#endif
+
+ __FP_UNPACK_D(A, rA);
+ __FP_UNPACK_D(B, rB);
+
+#ifdef DEBUG
+ printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+ printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+ if (B_c != FP_CLS_NAN)
+ B_s ^= 1;
+
+ FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+ printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+ return (ret | __FP_PACK_D(rD, R));
+}
--
1.4.0
More information about the Linuxppc-dev
mailing list