[patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

Subsystems: linux for powerpc (32-bit and 64-bit), the rest

STALE7124d

17 messages, 4 authors, 2007-03-08 · open the first message on its own page

[patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: <hidden>
Date: 2007-02-08 03:55:33

Add the general support for Embedded Floating-Point instructions
to fully comply with IEEE-754.

Signed-off-by:Ebony Zhu [off-list ref]
---
 arch/powerpc/kernel/head_fsl_booke.S |    4 
 arch/powerpc/kernel/traps.c          |   57 +++++
 arch/powerpc/math-emu/Makefile       |   25 ++
 arch/powerpc/math-emu/sfp-machine.h  |    2 
 arch/powerpc/math-emu/spe.h          |    1 
 arch/powerpc/sysdev/Makefile         |    1 
 arch/powerpc/sysdev/sigfpe_handler.c |  361 ++++++++++++++++++++++++++++++++++
 7 files changed, 442 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */
 
 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception, EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound, SPEFloatingPointException_Round, EXC_XFER_EE)
 
 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
@@ -840,6 +840,8 @@ load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use of SPE now */
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
 /*
  * For SMP, we don't do lazy SPE switching because it just gets too
  * horrendously complex, especially when a task switches from one CPU
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6915b91..30ab0f7 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -986,9 +986,16 @@ #endif /* CONFIG_FSL_BOOKE */
 #ifdef CONFIG_SPE
 void SPEFloatingPointException(struct pt_regs *regs)
 {
+	extern int spedata_handler(struct pt_regs *regs);
 	unsigned long spefscr;
 	int fpexc_mode;
 	int code = 0;
+	int err;
+	
+	preempt_disable();
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+	preempt_enable();
 
 	spefscr = current->thread.spefscr;
 	fpexc_mode = current->thread.fpexc_mode;
@@ -1013,9 +1020,55 @@ void SPEFloatingPointException(struct pt
 		code = FPE_FLTRES;
 
 	current->thread.spefscr = spefscr;
+	err = spedata_handler(regs);
+	if (err == 0) {
+		regs->nip += 4;		/* skip emulated instruction */
+		emulate_single_step(regs);
+		return;
+	}
 
-	_exception(SIGFPE, regs, code, regs->nip);
-	return;
+	if (err == -EFAULT) {
+		/* got an error reading the instruction */
+		_exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+	} else if (err == -EINVAL) {
+		/* didn't recognize the instruction */
+		printk(KERN_ERR "unrecognized spe instruction "
+		       "in %s at %lx\n", current->comm, regs->nip);
+	} else {
+		_exception(SIGFPE, regs, code, regs->nip);
+		return;
+	}
+}
+
+void SPEFloatingPointException_Round(struct pt_regs *regs)
+{
+	extern int speround_handler(struct pt_regs *regs);
+	int err;
+
+	preempt_disable();
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+	preempt_enable();
+
+	regs->nip -= 4;
+	err = speround_handler(regs);
+	if (err == 0) {
+		regs->nip += 4;		/* skip emulated instruction */
+		emulate_single_step(regs);
+		return;
+	}
+
+	if (err == -EFAULT) {
+		/* got an error reading the instruction */
+		_exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+	} else if (err == -EINVAL) {
+		/* didn't recognize the instruction */
+		printk(KERN_ERR "unrecognized spe instruction "
+		       "in %s at %lx\n", current->comm, regs->nip);
+	} else {
+		_exception(SIGFPE, regs, 0, regs->nip);
+		return;
+	}
 }
 #endif
 
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
index 29bc912..2da11ba 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -1,16 +1,29 @@
 
-obj-y				:= math.o fmr.o lfd.o stfd.o
-
-obj-$(CONFIG_MATH_EMULATION)	+= fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \
+obj-y				:= fabs.o fneg.o types.o udivmodti4.o
+					
+obj-$(CONFIG_MATH_EMULATION)	+= math.o fmr.o lfd.o stfd.o \
+					fadd.o fadds.o fcmpo.o fcmpu.o \
 					fctiw.o fctiwz.o fdiv.o fdivs.o \
 					fmadd.o fmadds.o fmsub.o fmsubs.o \
-					fmul.o fmuls.o fnabs.o fneg.o types.o \
+					fmul.o fmuls.o fnabs.o \
 					fnmadd.o fnmadds.o fnmsub.o fnmsubs.o \
 					fres.o frsp.o frsqrte.o fsel.o lfs.o \
 					fsqrt.o	fsqrts.o fsub.o fsubs.o \
 					mcrfs.o mffs.o mtfsb0.o mtfsb1.o \
-					mtfsf.o mtfsfi.o stfiwx.o stfs.o \
-					udivmodti4.o
+					mtfsf.o mtfsfi.o stfiwx.o stfs.o
+
+obj-$(CONFIG_SPE)		+= efsabs.o efsadd.o efscfd.o efscmpeq.o \
+					efscmpgt.o efscmplt.o efsctsf.o efsctsi.o \
+					efsctsiz.o efsctuf.o efsctui.o efsctuiz.o \
+					efsdiv.o efsmul.o efsnabs.o efsneg.o efssub.o \
+					evfsabs.o evfsadd.o evfscmpeq.o evfscmpgt.o \
+					evfscmplt.o evfsctsf.o evfsctsi.o evfsctsiz.o \
+					evfsctuf.o evfsctui.o evfsctuiz.o evfsdiv.o \
+					evfsmul.o evfsnabs.o evfsneg.o evfssub.o \
+					efdadd.o efdcfs.o efdcmpeq.o efdcmpgt.o efdcmplt.o \
+					efdctsf.o efdctsi.o efdctsidz.o efdctsiz.o efdctuf.o \
+					efdctui.o efdctuidz.o efdctuiz.o efddiv.o efdmul.o \
+					efdnabs.o efdsub.o
 
 CFLAGS_fabs.o = -fno-builtin-fabs
 CFLAGS_math.o = -fno-builtin-fabs
diff --git a/arch/powerpc/math-emu/sfp-machine.h b/arch/powerpc/math-emu/sfp-machine.h
index 4b17d83..07de8ef 100644
--- a/arch/powerpc/math-emu/sfp-machine.h
+++ b/arch/powerpc/math-emu/sfp-machine.h
@@ -166,7 +166,9 @@ #define __FP_PACK_RAW_2(fs, val, X)			\
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
+#ifndef __FPU_FPSCR
 #define __FPU_FPSCR	(current->thread.fpscr.val)
+#endif
 
 /* We only actually write to the destination register
  * if exceptions signalled (if any) will not trap.
diff --git a/arch/powerpc/math-emu/spe.h b/arch/powerpc/math-emu/spe.h
new file mode 100644
index 0000000..4f63630
--- /dev/null
+++ b/arch/powerpc/math-emu/spe.h
@@ -0,0 +1 @@
+#define __FPU_FPSCR	(current->thread.spefscr)
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 2621a7e..47f88b6 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
+obj-$(CONFIG_SPE)		+= sigfpe_handler.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
diff --git a/arch/powerpc/sysdev/sigfpe_handler.c b/arch/powerpc/sysdev/sigfpe_handler.c
new file mode 100644
index 0000000..8f9cfdb
--- /dev/null
+++ b/arch/powerpc/sysdev/sigfpe_handler.c
@@ -0,0 +1,361 @@
+/*
+ * arch/powerpc/sysdev/sigfpe_handler.c
+ *
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Ebony Zhu, ebony.zhu@freescale.com
+ * 
+ * Derived from arch/powerpc/math-emu/math.c
+ * Copyright (C) 1999  Eddie C. Dost  (ecd@atecom.com)
+ *
+ * Description:
+ * This file is the exception handler to make E500 SPE instructions
+ * fully comply with IEEE-754 floating point standard.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/reg.h>
+
+#define SPEFUNC(x)	extern int x(void *, void *, void *, void *)
+#define efdabs	fabs
+#define efdneg	fneg
+
+/* Scalar SPFP functions */
+SPEFUNC(efsabs);
+SPEFUNC(efsadd);
+SPEFUNC(efscfd);
+SPEFUNC(efscmpeq);
+SPEFUNC(efscmpgt);
+SPEFUNC(efscmplt);
+SPEFUNC(efsctsf);
+SPEFUNC(efsctsi);
+SPEFUNC(efsctsiz);
+SPEFUNC(efsctuf);
+SPEFUNC(efsctui);
+SPEFUNC(efsctuiz);
+SPEFUNC(efsdiv);
+SPEFUNC(efsmul);
+SPEFUNC(efsnabs);
+SPEFUNC(efsneg);
+SPEFUNC(efssub);
+
+/* Vector Floating-Point functions */
+SPEFUNC(evfsabs);
+SPEFUNC(evfsadd);
+SPEFUNC(evfscmpeq);
+SPEFUNC(evfscmpgt);
+SPEFUNC(evfscmplt);
+SPEFUNC(evfsctsf);
+SPEFUNC(evfsctsi);
+SPEFUNC(evfsctsiz);
+SPEFUNC(evfsctuf);
+SPEFUNC(evfsctui);
+SPEFUNC(evfsctuiz);
+SPEFUNC(evfsdiv);
+SPEFUNC(evfsmul);
+SPEFUNC(evfsnabs);
+SPEFUNC(evfsneg);
+SPEFUNC(evfssub);
+
+/* Scalar DPFP functions */
+SPEFUNC(efdabs);
+SPEFUNC(efdadd);
+SPEFUNC(efdcfs);
+SPEFUNC(efdcmpeq);
+SPEFUNC(efdcmpgt);
+SPEFUNC(efdcmplt);
+SPEFUNC(efdctsf);
+SPEFUNC(efdctsi);
+SPEFUNC(efdctsidz);
+SPEFUNC(efdctsiz);
+SPEFUNC(efdctuf);
+SPEFUNC(efdctui);
+SPEFUNC(efdctuidz);
+SPEFUNC(efdctuiz);
+SPEFUNC(efddiv);
+SPEFUNC(efdmul);
+SPEFUNC(efdnabs);
+SPEFUNC(efdneg);
+SPEFUNC(efdsub);
+
+#define VCT		0x4
+#define SPFP		0x6
+#define DPFP		0x7
+#define EFAPU		0x4
+
+#define EFSADD		0x2c0
+#define EFSSUB		0x2c1
+#define EFSABS		0x2c4
+#define EFSNABS		0x2c5
+#define EFSNEG		0x2c6
+#define EFSMUL		0x2c8
+#define EFSDIV		0x2c9
+#define EFSCMPGT	0x2cc
+#define EFSCMPLT	0x2cd
+#define EFSCMPEQ	0x2ce
+#define EFSCFD		0x2cf
+#define EFSCTUI		0x2d4
+#define EFSCTSI		0x2d5
+#define EFSCTUF		0x2d6
+#define EFSCTSF		0x2d7
+#define EFSCTUIZ	0x2d8
+#define EFSCTSIZ	0x2da
+
+#define EVFSADD		0x280
+#define EVFSSUB		0x281
+#define EVFSABS		0x284
+#define EVFSNABS	0x285
+#define EVFSNEG		0x286
+#define EVFSMUL		0x288
+#define EVFSDIV		0x289
+#define EVFSCMPGT	0x28c
+#define EVFSCMPLT	0x28d
+#define EVFSCMPEQ	0x28e
+#define EVFSCTUI	0x294
+#define EVFSCTSI	0x295
+#define EVFSCTUF	0x296
+#define EVFSCTSF	0x297
+#define EVFSCTUIZ	0x298
+#define EVFSCTSIZ	0x29a
+
+#define EFDADD		0x2e0
+#define EFDSUB		0x2e1
+#define EFDABS		0x2e4
+#define EFDNABS		0x2e5
+#define EFDNEG		0x2e6
+#define EFDMUL		0x2e8
+#define EFDDIV		0x2e9
+#define EFDCTUIDZ	0x2ea
+#define EFDCTSIDZ	0x2eb
+#define EFDCMPGT	0x2ec
+#define EFDCMPLT	0x2ed
+#define EFDCMPEQ	0x2ee
+#define EFDCFS		0x2ef
+#define EFDCTUI		0x2f4
+#define EFDCTSI		0x2f5
+#define EFDCTUF		0x2f6
+#define EFDCTSF		0x2f7
+#define EFDCTUIZ	0x2f8
+#define EFDCTSIZ	0x2fa
+
+#define AB	2
+#define XA	3
+#define XB	4
+#define XCR	5	
+
+static u64 fullgprs[32];
+static u32 speinsn;
+static int insn_decode(struct pt_regs *regs);
+static int (*func)(void *, void *, void *, void *);
+static void *op0 = 0, *op1 = 0, *op2 = 0, *op3 = 0;
+static int type = 0, flag;
+
+int
+spedata_handler(struct pt_regs *regs)
+{
+	int i;
+        
+	if (get_user(speinsn, (unsigned int __user *) regs->nip))
+		return -EFAULT;
+	if ((speinsn >> 26) != 4)
+		return -EINVAL;         /* not an spe instruction */
+	switch ((speinsn >> 5) & 0x7 ) {
+	case SPFP:
+		for(i = 0; i < 32; i++) {
+			fullgprs[i] = regs->gpr[i];
+			fullgprs[i] = fullgprs[i] << 32 | current->thread.evr[i]; 
+		};
+		break;
+	default:
+		for(i = 0; i < 32; i++) {
+			fullgprs[i] = current->thread.evr[i];
+			fullgprs[i] = (fullgprs[i] << 32) | (regs->gpr[i]); 
+		};
+	}
+	
+	if (insn_decode(regs) == -ENOSYS) return -ENOSYS;
+	flag = func(op0, op1, op2, op3);
+	
+	switch ((speinsn >> 5) & 0x7 ) {
+	case SPFP:
+		for (i = 0; i < 32; i++) {
+			regs->gpr[i] = fullgprs[i] >> 32;
+		};
+		break;
+	default:
+		for (i = 0; i < 32; i++) {
+			regs->gpr[i] = fullgprs[i];
+			current->thread.evr[i] = fullgprs[i] >> 32;
+		};
+	}
+	return 0;
+}
+
+int
+speround_handler(struct pt_regs *regs)
+{
+	u32 lsb_lo, lsb_hi; 
+	int s_lo, s_hi;
+	int rD;
+	
+	if (get_user(speinsn, (unsigned int __user *) regs->nip))
+		return -EFAULT;
+	if ((speinsn >> 26) != 4)
+		return -EINVAL;         /* not an spe instruction */
+	
+	rD = (speinsn >> 21) & 0x1f;
+	flag = insn_decode(regs);
+	if (type == XCR) return -ENOSYS;
+
+	s_lo = (regs->gpr[rD] & 0x80000000) >> 31;
+	s_hi = (current->thread.evr[rD] & 0x80000000) >> 31;
+	lsb_lo = regs->gpr[rD];
+	lsb_hi = current->thread.evr[rD];
+	switch ((speinsn >> 5) & 0x7 ) {
+	/* Since SPE instructions on E500 core can handle round to nearest 
+	 * and round toward zero with IEEE-754 complied, we just need
+	 * to handle round toward +Inf and round toward -Inf by software.
+	 */
+	case SPFP:
+		if ((current->thread.spefscr & 0x3) == 0x2) { /* round to +Inf */
+			if (!s_lo) lsb_lo++; /* Z > 0, choose Z1 */
+		} else { /* round to -Inf */
+			if (s_lo) lsb_lo++; /* Z < 0, choose Z2 */
+		}
+		regs->gpr[rD] = lsb_lo;
+		break;
+	case DPFP: 
+		fullgprs[rD] = current->thread.evr[rD];
+		fullgprs[rD] = (fullgprs[rD] << 32) | (regs->gpr[rD]); 
+
+		if ((current->thread.spefscr & 0x3) == 0x2) { /* round to +Inf */
+			if (!s_hi) fullgprs[rD]++; /* Z > 0, choose Z1 */
+		} else { /* round to -Inf */
+			if (s_hi) fullgprs[rD]++; /* Z < 0, choose Z2 */
+		}
+		regs->gpr[rD] = fullgprs[rD];
+		current->thread.evr[rD] = fullgprs[rD] >> 32;
+		break;
+	case VCT:
+		if ((current->thread.spefscr & 0x3) == 0x2) { /* round to +Inf */
+			if (!s_lo) lsb_lo++; /* Z_low > 0, choose Z1 */
+			if (!s_hi) lsb_hi++; /* Z_high word > 0, choose Z1 */
+		} else { /* round to -Inf */
+			if (s_lo) lsb_lo++; /* Z_low < 0, choose Z2 */
+			if (s_hi) lsb_hi++; /* Z_high < 0, choose Z2 */
+		}
+		regs->gpr[rD] = lsb_lo;
+		current->thread.evr[rD] = lsb_hi;
+		break;
+	default:
+		return -EINVAL;
+	}	
+	return 0;
+}
+
+static int insn_decode(struct pt_regs *regs)
+{
+	switch (speinsn >> 26) {
+	
+	case EFAPU:
+		switch (speinsn & 0x7ff) {
+		case EFSABS:	func = efsabs;		type = XA;	break;
+		case EFSADD:	func = efsadd;		type = AB;      break;
+		case EFSCFD:	func = efscfd;		type = XB;	break;
+		case EFSCMPEQ:	func = efscmpeq;	type = XCR;	break;
+		case EFSCMPGT:	func = efscmpgt;	type = XCR;	break;
+		case EFSCMPLT:	func = efscmplt;	type = XCR;	break;
+		case EFSCTSF:	func = efsctsf;		type = XB;	break;
+		case EFSCTSI:	func = efsctsi;		type = XB;	break;
+		case EFSCTSIZ:	func = efsctsiz;	type = XB;	break;
+		case EFSCTUF:	func = efsctuf;		type = XB;	break;
+		case EFSCTUI:	func = efsctui;		type = XB;	break;
+		case EFSCTUIZ:	func = efsctuiz;	type = XB;	break;
+		case EFSDIV:	func = efsdiv;		type = AB;	break;
+		case EFSMUL:	func = efsmul;		type = AB;	break;
+		case EFSNABS:	func = efsnabs;		type = XA;	break;
+		case EFSNEG:	func = efsneg;		type = XA;	break;
+		case EFSSUB:	func = efssub;		type = AB;	break;
+
+		case EVFSABS:	func = evfsabs;		type = XA;	break;
+		case EVFSADD:	func = evfsadd;		type = AB;      break;
+		case EVFSCMPEQ:	func = evfscmpeq;	type = XCR;	break;
+		case EVFSCMPGT:	func = evfscmpgt;	type = XCR;	break;
+		case EVFSCMPLT:	func = evfscmplt;	type = XCR;	break;
+		case EVFSCTSF:	func = evfsctsf;	type = XB;	break;
+		case EVFSCTSI:	func = evfsctsi;	type = XB;	break;
+		case EVFSCTSIZ:	func = evfsctsiz;	type = XB;	break;
+		case EVFSCTUF:	func = evfsctuf;	type = XB;	break;
+		case EVFSCTUI:	func = evfsctui;	type = XB;	break;
+		case EVFSCTUIZ:	func = evfsctuiz;	type = XB;	break;
+		case EVFSDIV:	func = evfsdiv;		type = AB;	break;
+		case EVFSMUL:	func = evfsmul;		type = AB;	break;
+		case EVFSNABS:	func = evfsnabs;	type = XA;	break;
+		case EVFSNEG:	func = evfsneg;		type = XA;	break;
+		case EVFSSUB:	func = evfssub;		type = AB;	break;
+
+		case EFDABS:	func = efdabs;		type = XA;	break;
+		case EFDADD:	func = efdadd;		type = AB;	break;
+		case EFDCFS:	func = efdcfs;		type = XB;	break;
+		case EFDCMPEQ:	func = efdcmpeq;	type = XCR;	break;
+		case EFDCMPGT:	func = efdcmpgt;	type = XCR;	break;
+		case EFDCMPLT:	func = efdcmplt;	type = XCR;	break;
+		case EFDCTSF:	func = efdctsf;		type = XB;	break;
+		case EFDCTSI:	func = efdctsi;		type = XB;	break;
+		case EFDCTSIDZ:	func = efdctsidz;	type = XB;	break;
+		case EFDCTSIZ:	func = efdctsiz;	type = XB;	break;
+		case EFDCTUF:	func = efdctuf;		type = XB;	break;
+		case EFDCTUI:	func = efdctui;		type = XB;	break;
+		case EFDCTUIDZ:	func = efdctuidz;	type = XB;	break;
+		case EFDCTUIZ:	func = efdctuiz;	type = XB;	break;
+		case EFDDIV:	func = efddiv;		type = AB;	break;
+		case EFDMUL:	func = efdmul;		type = AB;	break;
+		case EFDNABS:	func = efdnabs;		type = XA;	break;
+		case EFDNEG:	func = efdneg;		type = XA;	break;
+		case EFDSUB:	func = efdsub;		type = AB;	break;		
+		default:
+			goto illegal; 
+		}
+		break;
+	default:
+		goto illegal;
+	}
+
+	switch (type) {
+	case AB:
+		op0 = &fullgprs[(speinsn >> 21) & 0x1f];
+		op1 = &fullgprs[(speinsn >> 16) & 0x1f];
+		op2 = &fullgprs[(speinsn >> 11) & 0x1f];
+		break;
+
+	case XA:
+		op0 = &fullgprs[(speinsn >> 21) & 0x1f];
+		op1 = &fullgprs[(speinsn >> 16) & 0x1f];
+		break;
+
+	case XB:
+		op0 = &fullgprs[(speinsn >> 21) & 0x1f];
+		op1 = &fullgprs[(speinsn >> 11) & 0x1f];
+		break;
+	
+	case XCR:
+		op0 = (void *)&regs->ccr;
+		op1 = (void *)((speinsn >> 23) & 0x7);
+		op2 = &fullgprs[(speinsn >> 16) & 0x1f];
+		op3 = &fullgprs[(speinsn >> 11) & 0x1f];
+		break;
+
+	default:
+		goto illegal;
+	}
+	return 0;
+illegal:
+	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\n");
+	return -ENOSYS;
+}
-- 
1.4.0

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Kumar Gala <hidden>
Date: 2007-02-08 07:34:00

On Feb 7, 2007, at 9:55 PM, ebony.zhu@freescale.com wrote:
Add the general support for Embedded Floating-Point instructions
to fully comply with IEEE-754.

Signed-off-by:Ebony Zhu [off-list ref]
---
 arch/powerpc/kernel/head_fsl_booke.S |    4
 arch/powerpc/kernel/traps.c          |   57 +++++
 arch/powerpc/math-emu/Makefile       |   25 ++
 arch/powerpc/math-emu/sfp-machine.h  |    2
 arch/powerpc/math-emu/spe.h          |    1
 arch/powerpc/sysdev/Makefile         |    1
 arch/powerpc/sysdev/sigfpe_handler.c |  361 +++++++++++++++++++++++ 
+++++++++++
 7 files changed, 442 insertions(+), 9 deletions(-)
I thought we were going to have some general Kconfig option to enable  
all this?  EMDEDDED_FP_IEEE or something like that
quoted hunk
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/ 
kernel/head_fsl_booke.S
index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception,  
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound,  
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor,  
performance_monitor_exception, EXC_XFER_STD)
@@ -840,6 +840,8 @@ load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use of SPE now */
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE |  
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
We should do this via INIT_THREAD, is there a reason that you want to  
set these always?
quoted hunk
 /*
  * For SMP, we don't do lazy SPE switching because it just gets too
  * horrendously complex, especially when a task switches from one CPU
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6915b91..30ab0f7 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -986,9 +986,16 @@ #endif /* CONFIG_FSL_BOOKE */
 #ifdef CONFIG_SPE
 void SPEFloatingPointException(struct pt_regs *regs)
 {
+	extern int spedata_handler(struct pt_regs *regs);
 	unsigned long spefscr;
 	int fpexc_mode;
 	int code = 0;
+	int err;
+	
+	preempt_disable();
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+	preempt_enable();
use flush_spe_to_thread(current);
quoted hunk
 	spefscr = current->thread.spefscr;
 	fpexc_mode = current->thread.fpexc_mode;
@@ -1013,9 +1020,55 @@ void SPEFloatingPointException(struct pt
 		code = FPE_FLTRES;

 	current->thread.spefscr = spefscr;
+	err = spedata_handler(regs);
+	if (err == 0) {
+		regs->nip += 4;		/* skip emulated instruction */
+		emulate_single_step(regs);
+		return;
+	}
Take a look at the path I put up that reworks the error handling from  
do_mathemu() we need to be doing something similar (in parsing  
spefscr/fpexc_mode to setup code properly)
-	_exception(SIGFPE, regs, code, regs->nip);
-	return;
+	if (err == -EFAULT) {
+		/* got an error reading the instruction */
+		_exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+	} else if (err == -EINVAL) {
+		/* didn't recognize the instruction */
+		printk(KERN_ERR "unrecognized spe instruction "
+		       "in %s at %lx\n", current->comm, regs->nip);
We should probably just SIGSEGV in this case since will never make  
forward progress once we hit this case.
+	} else {
+		_exception(SIGFPE, regs, code, regs->nip);
+		return;
+	}
+}
+
+void SPEFloatingPointException_Round(struct pt_regs *regs)
+{
+	extern int speround_handler(struct pt_regs *regs);
+	int err;
+
+	preempt_disable();
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+	preempt_enable();
use flush_spe_to_thread(current);
+
+	regs->nip -= 4;
uugh, just handle this in speround_handler()
+	err = speround_handler(regs);
+	if (err == 0) {
+		regs->nip += 4;		/* skip emulated instruction */
+		emulate_single_step(regs);
I don't think this emulate_single_step() needed since we really  
aren't changing NIP from the HW point of view.
+		return;
+	}
+
+	if (err == -EFAULT) {
+		/* got an error reading the instruction */
+		_exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+	} else if (err == -EINVAL) {
+		/* didn't recognize the instruction */
+		printk(KERN_ERR "unrecognized spe instruction "
+		       "in %s at %lx\n", current->comm, regs->nip);
similar comment as above
quoted hunk
+	} else {
+		_exception(SIGFPE, regs, 0, regs->nip);
+		return;
+	}
 }
 #endif
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/ 
Makefile
index 29bc912..2da11ba 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -1,16 +1,29 @@

-obj-y				:= math.o fmr.o lfd.o stfd.o
-
-obj-$(CONFIG_MATH_EMULATION)	+= fabs.o fadd.o fadds.o fcmpo.o  
fcmpu.o \
+obj-y				:= fabs.o fneg.o types.o udivmodti4.o
This isn't right, we don't want to always build these files.
quoted hunk
+					
+obj-$(CONFIG_MATH_EMULATION)	+= math.o fmr.o lfd.o stfd.o \
+					fadd.o fadds.o fcmpo.o fcmpu.o \
 					fctiw.o fctiwz.o fdiv.o fdivs.o \
 					fmadd.o fmadds.o fmsub.o fmsubs.o \
-					fmul.o fmuls.o fnabs.o fneg.o types.o \
+					fmul.o fmuls.o fnabs.o \
 					fnmadd.o fnmadds.o fnmsub.o fnmsubs.o \
 					fres.o frsp.o frsqrte.o fsel.o lfs.o \
 					fsqrt.o	fsqrts.o fsub.o fsubs.o \
 					mcrfs.o mffs.o mtfsb0.o mtfsb1.o \
-					mtfsf.o mtfsfi.o stfiwx.o stfs.o \
-					udivmodti4.o
+					mtfsf.o mtfsfi.o stfiwx.o stfs.o
+
+obj-$(CONFIG_SPE)		+= efsabs.o efsadd.o efscfd.o efscmpeq.o \
+					efscmpgt.o efscmplt.o efsctsf.o efsctsi.o \
+					efsctsiz.o efsctuf.o efsctui.o efsctuiz.o \
+					efsdiv.o efsmul.o efsnabs.o efsneg.o efssub.o \
+					evfsabs.o evfsadd.o evfscmpeq.o evfscmpgt.o \
+					evfscmplt.o evfsctsf.o evfsctsi.o evfsctsiz.o \
+					evfsctuf.o evfsctui.o evfsctuiz.o evfsdiv.o \
+					evfsmul.o evfsnabs.o evfsneg.o evfssub.o \
+					efdadd.o efdcfs.o efdcmpeq.o efdcmpgt.o efdcmplt.o \
+					efdctsf.o efdctsi.o efdctsidz.o efdctsiz.o efdctuf.o \
+					efdctui.o efdctuidz.o efdctuiz.o efddiv.o efdmul.o \
+					efdnabs.o efdsub.o

 CFLAGS_fabs.o = -fno-builtin-fabs
 CFLAGS_math.o = -fno-builtin-fabs
diff --git a/arch/powerpc/math-emu/sfp-machine.h b/arch/powerpc/ 
math-emu/sfp-machine.h
index 4b17d83..07de8ef 100644
--- a/arch/powerpc/math-emu/sfp-machine.h
+++ b/arch/powerpc/math-emu/sfp-machine.h
@@ -166,7 +166,9 @@ #define __FP_PACK_RAW_2(fs, val, X)			\
 #include <linux/kernel.h>
 #include <linux/sched.h>

+#ifndef __FPU_FPSCR
 #define __FPU_FPSCR	(current->thread.fpscr.val)
+#endif

 /* We only actually write to the destination register
  * if exceptions signalled (if any) will not trap.
diff --git a/arch/powerpc/math-emu/spe.h b/arch/powerpc/math-emu/spe.h
new file mode 100644
index 0000000..4f63630
--- /dev/null
+++ b/arch/powerpc/math-emu/spe.h
@@ -0,0 +1 @@
+#define __FPU_FPSCR	(current->thread.spefscr)
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/ 
Makefile
index 2621a7e..47f88b6 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
+obj-$(CONFIG_SPE)		+= sigfpe_handler.o

 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
diff --git a/arch/powerpc/sysdev/sigfpe_handler.c b/arch/powerpc/ 
sysdev/sigfpe_handler.c
new file mode 100644
index 0000000..8f9cfdb
--- /dev/null
+++ b/arch/powerpc/sysdev/sigfpe_handler.c
@@ -0,0 +1,361 @@
+/*
+ * arch/powerpc/sysdev/sigfpe_handler.c
+ *
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights  
reserved.
+ *
+ * Author: Ebony Zhu, ebony.zhu@freescale.com
+ *
+ * Derived from arch/powerpc/math-emu/math.c
+ * Copyright (C) 1999  Eddie C. Dost  (ecd@atecom.com)
+ *
+ * Description:
+ * This file is the exception handler to make E500 SPE instructions
+ * fully comply with IEEE-754 floating point standard.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/reg.h>
+
+#define SPEFUNC(x)	extern int x(void *, void *, void *, void *)
+#define efdabs	fabs
+#define efdneg	fneg
+
+/* Scalar SPFP functions */
+SPEFUNC(efsabs);
+SPEFUNC(efsadd);
+SPEFUNC(efscfd);
+SPEFUNC(efscmpeq);
+SPEFUNC(efscmpgt);
+SPEFUNC(efscmplt);
+SPEFUNC(efsctsf);
+SPEFUNC(efsctsi);
+SPEFUNC(efsctsiz);
+SPEFUNC(efsctuf);
+SPEFUNC(efsctui);
+SPEFUNC(efsctuiz);
+SPEFUNC(efsdiv);
+SPEFUNC(efsmul);
+SPEFUNC(efsnabs);
+SPEFUNC(efsneg);
+SPEFUNC(efssub);
+
+/* Vector Floating-Point functions */
+SPEFUNC(evfsabs);
+SPEFUNC(evfsadd);
+SPEFUNC(evfscmpeq);
+SPEFUNC(evfscmpgt);
+SPEFUNC(evfscmplt);
+SPEFUNC(evfsctsf);
+SPEFUNC(evfsctsi);
+SPEFUNC(evfsctsiz);
+SPEFUNC(evfsctuf);
+SPEFUNC(evfsctui);
+SPEFUNC(evfsctuiz);
+SPEFUNC(evfsdiv);
+SPEFUNC(evfsmul);
+SPEFUNC(evfsnabs);
+SPEFUNC(evfsneg);
+SPEFUNC(evfssub);
+
+/* Scalar DPFP functions */
+SPEFUNC(efdabs);
+SPEFUNC(efdadd);
+SPEFUNC(efdcfs);
+SPEFUNC(efdcmpeq);
+SPEFUNC(efdcmpgt);
+SPEFUNC(efdcmplt);
+SPEFUNC(efdctsf);
+SPEFUNC(efdctsi);
+SPEFUNC(efdctsidz);
+SPEFUNC(efdctsiz);
+SPEFUNC(efdctuf);
+SPEFUNC(efdctui);
+SPEFUNC(efdctuidz);
+SPEFUNC(efdctuiz);
+SPEFUNC(efddiv);
+SPEFUNC(efdmul);
+SPEFUNC(efdnabs);
+SPEFUNC(efdneg);
+SPEFUNC(efdsub);
+
+#define VCT		0x4
+#define SPFP		0x6
+#define DPFP		0x7
+#define EFAPU		0x4
+
+#define EFSADD		0x2c0
+#define EFSSUB		0x2c1
+#define EFSABS		0x2c4
+#define EFSNABS		0x2c5
+#define EFSNEG		0x2c6
+#define EFSMUL		0x2c8
+#define EFSDIV		0x2c9
+#define EFSCMPGT	0x2cc
+#define EFSCMPLT	0x2cd
+#define EFSCMPEQ	0x2ce
+#define EFSCFD		0x2cf
+#define EFSCTUI		0x2d4
+#define EFSCTSI		0x2d5
+#define EFSCTUF		0x2d6
+#define EFSCTSF		0x2d7
+#define EFSCTUIZ	0x2d8
+#define EFSCTSIZ	0x2da
+
+#define EVFSADD		0x280
+#define EVFSSUB		0x281
+#define EVFSABS		0x284
+#define EVFSNABS	0x285
+#define EVFSNEG		0x286
+#define EVFSMUL		0x288
+#define EVFSDIV		0x289
+#define EVFSCMPGT	0x28c
+#define EVFSCMPLT	0x28d
+#define EVFSCMPEQ	0x28e
+#define EVFSCTUI	0x294
+#define EVFSCTSI	0x295
+#define EVFSCTUF	0x296
+#define EVFSCTSF	0x297
+#define EVFSCTUIZ	0x298
+#define EVFSCTSIZ	0x29a
+
+#define EFDADD		0x2e0
+#define EFDSUB		0x2e1
+#define EFDABS		0x2e4
+#define EFDNABS		0x2e5
+#define EFDNEG		0x2e6
+#define EFDMUL		0x2e8
+#define EFDDIV		0x2e9
+#define EFDCTUIDZ	0x2ea
+#define EFDCTSIDZ	0x2eb
+#define EFDCMPGT	0x2ec
+#define EFDCMPLT	0x2ed
+#define EFDCMPEQ	0x2ee
+#define EFDCFS		0x2ef
+#define EFDCTUI		0x2f4
+#define EFDCTSI		0x2f5
+#define EFDCTUF		0x2f6
+#define EFDCTSF		0x2f7
+#define EFDCTUIZ	0x2f8
+#define EFDCTSIZ	0x2fa
+
+#define AB	2
+#define XA	3
+#define XB	4
+#define XCR	5	
+
+static u64 fullgprs[32];
+static u32 speinsn;
+static int insn_decode(struct pt_regs *regs);
+static int (*func)(void *, void *, void *, void *);
+static void *op0 = 0, *op1 = 0, *op2 = 0, *op3 = 0;
+static int type = 0, flag;
+
+int
+spedata_handler(struct pt_regs *regs)
+{
+	int i;
+
+	if (get_user(speinsn, (unsigned int __user *) regs->nip))
+		return -EFAULT;
+	if ((speinsn >> 26) != 4)
+		return -EINVAL;         /* not an spe instruction */
+	switch ((speinsn >> 5) & 0x7 ) {
+	case SPFP:
+		for(i = 0; i < 32; i++) {
+			fullgprs[i] = regs->gpr[i];
+			fullgprs[i] = fullgprs[i] << 32 | current->thread.evr[i];
+		};
+		break;
+	default:
+		for(i = 0; i < 32; i++) {
+			fullgprs[i] = current->thread.evr[i];
+			fullgprs[i] = (fullgprs[i] << 32) | (regs->gpr[i]);
+		};
+	}
+	
+	if (insn_decode(regs) == -ENOSYS) return -ENOSYS;
+	flag = func(op0, op1, op2, op3);
+	
+	switch ((speinsn >> 5) & 0x7 ) {
+	case SPFP:
+		for (i = 0; i < 32; i++) {
+			regs->gpr[i] = fullgprs[i] >> 32;
+		};
+		break;
+	default:
+		for (i = 0; i < 32; i++) {
+			regs->gpr[i] = fullgprs[i];
+			current->thread.evr[i] = fullgprs[i] >> 32;
+		};
+	}
+	return 0;
+}
+
+int
+speround_handler(struct pt_regs *regs)
+{
+	u32 lsb_lo, lsb_hi;
+	int s_lo, s_hi;
+	int rD;
+	
+	if (get_user(speinsn, (unsigned int __user *) regs->nip))
+		return -EFAULT;
+	if ((speinsn >> 26) != 4)
+		return -EINVAL;         /* not an spe instruction */
+	
+	rD = (speinsn >> 21) & 0x1f;
+	flag = insn_decode(regs);
+	if (type == XCR) return -ENOSYS;
+
+	s_lo = (regs->gpr[rD] & 0x80000000) >> 31;
+	s_hi = (current->thread.evr[rD] & 0x80000000) >> 31;
+	lsb_lo = regs->gpr[rD];
+	lsb_hi = current->thread.evr[rD];
+	switch ((speinsn >> 5) & 0x7 ) {
+	/* Since SPE instructions on E500 core can handle round to nearest
+	 * and round toward zero with IEEE-754 complied, we just need
+	 * to handle round toward +Inf and round toward -Inf by software.
+	 */
+	case SPFP:
+		if ((current->thread.spefscr & 0x3) == 0x2) { /* round to +Inf */
+			if (!s_lo) lsb_lo++; /* Z > 0, choose Z1 */
+		} else { /* round to -Inf */
+			if (s_lo) lsb_lo++; /* Z < 0, choose Z2 */
+		}
+		regs->gpr[rD] = lsb_lo;
+		break;
+	case DPFP:
+		fullgprs[rD] = current->thread.evr[rD];
+		fullgprs[rD] = (fullgprs[rD] << 32) | (regs->gpr[rD]);
+
+		if ((current->thread.spefscr & 0x3) == 0x2) { /* round to +Inf */
+			if (!s_hi) fullgprs[rD]++; /* Z > 0, choose Z1 */
+		} else { /* round to -Inf */
+			if (s_hi) fullgprs[rD]++; /* Z < 0, choose Z2 */
+		}
+		regs->gpr[rD] = fullgprs[rD];
+		current->thread.evr[rD] = fullgprs[rD] >> 32;
+		break;
+	case VCT:
+		if ((current->thread.spefscr & 0x3) == 0x2) { /* round to +Inf */
+			if (!s_lo) lsb_lo++; /* Z_low > 0, choose Z1 */
+			if (!s_hi) lsb_hi++; /* Z_high word > 0, choose Z1 */
+		} else { /* round to -Inf */
+			if (s_lo) lsb_lo++; /* Z_low < 0, choose Z2 */
+			if (s_hi) lsb_hi++; /* Z_high < 0, choose Z2 */
+		}
+		regs->gpr[rD] = lsb_lo;
+		current->thread.evr[rD] = lsb_hi;
+		break;
+	default:
+		return -EINVAL;
+	}	
+	return 0;
+}
+
+static int insn_decode(struct pt_regs *regs)
+{
+	switch (speinsn >> 26) {
+	
+	case EFAPU:
+		switch (speinsn & 0x7ff) {
+		case EFSABS:	func = efsabs;		type = XA;	break;
+		case EFSADD:	func = efsadd;		type = AB;      break;
+		case EFSCFD:	func = efscfd;		type = XB;	break;
+		case EFSCMPEQ:	func = efscmpeq;	type = XCR;	break;
+		case EFSCMPGT:	func = efscmpgt;	type = XCR;	break;
+		case EFSCMPLT:	func = efscmplt;	type = XCR;	break;
+		case EFSCTSF:	func = efsctsf;		type = XB;	break;
+		case EFSCTSI:	func = efsctsi;		type = XB;	break;
+		case EFSCTSIZ:	func = efsctsiz;	type = XB;	break;
+		case EFSCTUF:	func = efsctuf;		type = XB;	break;
+		case EFSCTUI:	func = efsctui;		type = XB;	break;
+		case EFSCTUIZ:	func = efsctuiz;	type = XB;	break;
+		case EFSDIV:	func = efsdiv;		type = AB;	break;
+		case EFSMUL:	func = efsmul;		type = AB;	break;
+		case EFSNABS:	func = efsnabs;		type = XA;	break;
+		case EFSNEG:	func = efsneg;		type = XA;	break;
+		case EFSSUB:	func = efssub;		type = AB;	break;
+
+		case EVFSABS:	func = evfsabs;		type = XA;	break;
+		case EVFSADD:	func = evfsadd;		type = AB;      break;
+		case EVFSCMPEQ:	func = evfscmpeq;	type = XCR;	break;
+		case EVFSCMPGT:	func = evfscmpgt;	type = XCR;	break;
+		case EVFSCMPLT:	func = evfscmplt;	type = XCR;	break;
+		case EVFSCTSF:	func = evfsctsf;	type = XB;	break;
+		case EVFSCTSI:	func = evfsctsi;	type = XB;	break;
+		case EVFSCTSIZ:	func = evfsctsiz;	type = XB;	break;
+		case EVFSCTUF:	func = evfsctuf;	type = XB;	break;
+		case EVFSCTUI:	func = evfsctui;	type = XB;	break;
+		case EVFSCTUIZ:	func = evfsctuiz;	type = XB;	break;
+		case EVFSDIV:	func = evfsdiv;		type = AB;	break;
+		case EVFSMUL:	func = evfsmul;		type = AB;	break;
+		case EVFSNABS:	func = evfsnabs;	type = XA;	break;
+		case EVFSNEG:	func = evfsneg;		type = XA;	break;
+		case EVFSSUB:	func = evfssub;		type = AB;	break;
+
+		case EFDABS:	func = efdabs;		type = XA;	break;
+		case EFDADD:	func = efdadd;		type = AB;	break;
+		case EFDCFS:	func = efdcfs;		type = XB;	break;
+		case EFDCMPEQ:	func = efdcmpeq;	type = XCR;	break;
+		case EFDCMPGT:	func = efdcmpgt;	type = XCR;	break;
+		case EFDCMPLT:	func = efdcmplt;	type = XCR;	break;
+		case EFDCTSF:	func = efdctsf;		type = XB;	break;
+		case EFDCTSI:	func = efdctsi;		type = XB;	break;
+		case EFDCTSIDZ:	func = efdctsidz;	type = XB;	break;
+		case EFDCTSIZ:	func = efdctsiz;	type = XB;	break;
+		case EFDCTUF:	func = efdctuf;		type = XB;	break;
+		case EFDCTUI:	func = efdctui;		type = XB;	break;
+		case EFDCTUIDZ:	func = efdctuidz;	type = XB;	break;
+		case EFDCTUIZ:	func = efdctuiz;	type = XB;	break;
+		case EFDDIV:	func = efddiv;		type = AB;	break;
+		case EFDMUL:	func = efdmul;		type = AB;	break;
+		case EFDNABS:	func = efdnabs;		type = XA;	break;
+		case EFDNEG:	func = efdneg;		type = XA;	break;
+		case EFDSUB:	func = efdsub;		type = AB;	break;		
+		default:
+			goto illegal;
+		}
+		break;
+	default:
+		goto illegal;
+	}
+
+	switch (type) {
+	case AB:
+		op0 = &fullgprs[(speinsn >> 21) & 0x1f];
+		op1 = &fullgprs[(speinsn >> 16) & 0x1f];
+		op2 = &fullgprs[(speinsn >> 11) & 0x1f];
+		break;
+
+	case XA:
+		op0 = &fullgprs[(speinsn >> 21) & 0x1f];
+		op1 = &fullgprs[(speinsn >> 16) & 0x1f];
+		break;
+
+	case XB:
+		op0 = &fullgprs[(speinsn >> 21) & 0x1f];
+		op1 = &fullgprs[(speinsn >> 11) & 0x1f];
+		break;
+	
+	case XCR:
+		op0 = (void *)&regs->ccr;
+		op1 = (void *)((speinsn >> 23) & 0x7);
+		op2 = &fullgprs[(speinsn >> 16) & 0x1f];
+		op3 = &fullgprs[(speinsn >> 11) & 0x1f];
+		break;
+
+	default:
+		goto illegal;
+	}
+	return 0;
+illegal:
+	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered  
un-supported instruction.\n");
+	return -ENOSYS;
+}
-- 
1.4.0

RE: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Zhu Ebony-r57400 <hidden>
Date: 2007-02-08 09:06:59

=20
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]=20
Sent: Thursday, February 08, 2007 3:33 PM
To: Zhu Ebony-r57400
Cc: paulus@samba.org; linuxppc-dev@ozlabs.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support=20
for Embedded Floating-Point instructions
=20
=20
On Feb 7, 2007, at 9:55 PM, ebony.zhu@freescale.com wrote:
=20
quoted
Add the general support for Embedded Floating-Point instructions to=20
fully comply with IEEE-754.

Signed-off-by:Ebony Zhu [off-list ref]
---
 arch/powerpc/kernel/head_fsl_booke.S |    4
 arch/powerpc/kernel/traps.c          |   57 +++++
 arch/powerpc/math-emu/Makefile       |   25 ++
 arch/powerpc/math-emu/sfp-machine.h  |    2
 arch/powerpc/math-emu/spe.h          |    1
 arch/powerpc/sysdev/Makefile         |    1
 arch/powerpc/sysdev/sigfpe_handler.c |  361 +++++++++++++++++++++++
+++++++++++
 7 files changed, 442 insertions(+), 9 deletions(-)
=20
I thought we were going to have some general Kconfig option=20
to enable all this?  EMDEDDED_FP_IEEE or something like that
So that users have chance to enable/disable fully IEEE compliance?
Segher
had mentioned this, and it sounds reasonable.=20
=20
quoted
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/=20
kernel/head_fsl_booke.S
index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception, =20
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound, =20
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor, =20
performance_monitor_exception, EXC_XFER_STD)
@@ -840,6 +840,8 @@ load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use of SPE now */
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | =20
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
=20
We should do this via INIT_THREAD, is there a reason that you=20
want to =20
set these always?
I just thought it's the first time that an SPE instruction is
encountered, so I
enable the exceptions here.
=20
quoted
 /*
  * For SMP, we don't do lazy SPE switching because it just gets too
  * horrendously complex, especially when a task switches=20
from one CPU
quoted
diff --git a/arch/powerpc/kernel/traps.c=20
b/arch/powerpc/kernel/traps.c
quoted
index 6915b91..30ab0f7 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -986,9 +986,16 @@ #endif /* CONFIG_FSL_BOOKE */
 #ifdef CONFIG_SPE
 void SPEFloatingPointException(struct pt_regs *regs)
 {
+	extern int spedata_handler(struct pt_regs *regs);
 	unsigned long spefscr;
 	int fpexc_mode;
 	int code =3D 0;
+	int err;
+=09
+	preempt_disable();
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+	preempt_enable();
=20
use flush_spe_to_thread(current);
OK. It works, and I'll change it.
=20
quoted
 	spefscr =3D current->thread.spefscr;
 	fpexc_mode =3D current->thread.fpexc_mode;
@@ -1013,9 +1020,55 @@ void SPEFloatingPointException(struct pt
 		code =3D FPE_FLTRES;

 	current->thread.spefscr =3D spefscr;
+	err =3D spedata_handler(regs);
+	if (err =3D=3D 0) {
+		regs->nip +=3D 4;		/* skip emulated instruction */
+		emulate_single_step(regs);
+		return;
+	}
=20
Take a look at the path I put up that reworks the error=20
handling from =20
do_mathemu() we need to be doing something similar (in parsing =20
spefscr/fpexc_mode to setup code properly)
It's new in trap.c? I'll look into it.

=20
quoted
-	_exception(SIGFPE, regs, code, regs->nip);
-	return;
+	if (err =3D=3D -EFAULT) {
+		/* got an error reading the instruction */
+		_exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+	} else if (err =3D=3D -EINVAL) {
+		/* didn't recognize the instruction */
+		printk(KERN_ERR "unrecognized spe instruction "
+		       "in %s at %lx\n", current->comm, regs->nip);
=20
We should probably just SIGSEGV in this case since will never make =20
forward progress once we hit this case.
Won't it hit the case that the instruction is not an spe instruction?

quoted
diff --git a/arch/powerpc/math-emu/Makefile=20
b/arch/powerpc/math-emu/=20
quoted
Makefile
index 29bc912..2da11ba 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -1,16 +1,29 @@

-obj-y				:=3D math.o fmr.o lfd.o stfd.o
-
-obj-$(CONFIG_MATH_EMULATION)	+=3D fabs.o fadd.o=20
fadds.o fcmpo.o =20
quoted
fcmpu.o \
+obj-y				:=3D fabs.o fneg.o=20
types.o udivmodti4.o
=20
This isn't right, we don't want to always build these files.
=20
fabs.o/fneg.o should be built in the case
that CONFIG_MATH_EMULATION or CONFIG_SPE or both are
enabled. Because I reused fabs.c and fneg.c to implement instruction
efdabs and
efdneg. Therefore, these two files should be build once we have chance
to build the files in directory math-emu. Types.c and udivmodti4.c
contain the function
that both math emulation instructions and spe instructions may call, so
they always need
to be built.

B.R
Ebony

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Kumar Gala <hidden>
Date: 2007-02-08 17:32:19

On Feb 8, 2007, at 3:06 AM, Zhu Ebony-r57400 wrote:
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Thursday, February 08, 2007 3:33 PM
To: Zhu Ebony-r57400
Cc: paulus@samba.org; linuxppc-dev@ozlabs.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support
for Embedded Floating-Point instructions


On Feb 7, 2007, at 9:55 PM, ebony.zhu@freescale.com wrote:
quoted
Add the general support for Embedded Floating-Point instructions to
fully comply with IEEE-754.

Signed-off-by:Ebony Zhu [off-list ref]
---
 arch/powerpc/kernel/head_fsl_booke.S |    4
 arch/powerpc/kernel/traps.c          |   57 +++++
 arch/powerpc/math-emu/Makefile       |   25 ++
 arch/powerpc/math-emu/sfp-machine.h  |    2
 arch/powerpc/math-emu/spe.h          |    1
 arch/powerpc/sysdev/Makefile         |    1
 arch/powerpc/sysdev/sigfpe_handler.c |  361 +++++++++++++++++++++++
+++++++++++
 7 files changed, 442 insertions(+), 9 deletions(-)
I thought we were going to have some general Kconfig option
to enable all this?  EMDEDDED_FP_IEEE or something like that
So that users have chance to enable/disable fully IEEE compliance?
Segher
had mentioned this, and it sounds reasonable.
Its alot of code to bring in if you don't care about IEEE compliance.
quoted
quoted
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/
kernel/head_fsl_booke.S
index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception,
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound,
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor,
performance_monitor_exception, EXC_XFER_STD)
@@ -840,6 +840,8 @@ load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use of SPE now */
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE |
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
We should do this via INIT_THREAD, is there a reason that you
want to
set these always?
I just thought it's the first time that an SPE instruction is
encountered, so I
enable the exceptions here.
Lets do this via INIT_THREAD instead, its cleaner. (just remember to  
add the proper ifdef protection for SPE_IEEE
quoted
quoted
 /*
  * For SMP, we don't do lazy SPE switching because it just gets too
  * horrendously complex, especially when a task switches
from one CPU
quoted
diff --git a/arch/powerpc/kernel/traps.c
b/arch/powerpc/kernel/traps.c
quoted
index 6915b91..30ab0f7 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -986,9 +986,16 @@ #endif /* CONFIG_FSL_BOOKE */
 #ifdef CONFIG_SPE
 void SPEFloatingPointException(struct pt_regs *regs)
 {
+	extern int spedata_handler(struct pt_regs *regs);
 	unsigned long spefscr;
 	int fpexc_mode;
 	int code = 0;
+	int err;
+	
+	preempt_disable();
+	if (regs->msr & MSR_SPE)
+		giveup_spe(current);
+	preempt_enable();
use flush_spe_to_thread(current);
OK. It works, and I'll change it.
quoted
quoted
 	spefscr = current->thread.spefscr;
 	fpexc_mode = current->thread.fpexc_mode;
@@ -1013,9 +1020,55 @@ void SPEFloatingPointException(struct pt
 		code = FPE_FLTRES;

 	current->thread.spefscr = spefscr;
+	err = spedata_handler(regs);
+	if (err == 0) {
+		regs->nip += 4;		/* skip emulated instruction */
+		emulate_single_step(regs);
+		return;
+	}
Take a look at the path I put up that reworks the error
handling from
do_mathemu() we need to be doing something similar (in parsing
spefscr/fpexc_mode to setup code properly)
It's new in trap.c? I'll look into it.
Pretty recent commit, in Paul's tree, not yet in linus's.

(or look at my last pull request email to paul)
quoted
quoted
-	_exception(SIGFPE, regs, code, regs->nip);
-	return;
+	if (err == -EFAULT) {
+		/* got an error reading the instruction */
+		_exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+	} else if (err == -EINVAL) {
+		/* didn't recognize the instruction */
+		printk(KERN_ERR "unrecognized spe instruction "
+		       "in %s at %lx\n", current->comm, regs->nip);
We should probably just SIGSEGV in this case since will never make
forward progress once we hit this case.
Won't it hit the case that the instruction is not an spe instruction?
No, since we will not get this exception on something that's not an  
SPE instruction.
quoted
quoted
diff --git a/arch/powerpc/math-emu/Makefile
b/arch/powerpc/math-emu/
quoted
Makefile
index 29bc912..2da11ba 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -1,16 +1,29 @@

-obj-y				:= math.o fmr.o lfd.o stfd.o
-
-obj-$(CONFIG_MATH_EMULATION)	+= fabs.o fadd.o
fadds.o fcmpo.o
quoted
fcmpu.o \
+obj-y				:= fabs.o fneg.o
types.o udivmodti4.o

This isn't right, we don't want to always build these files.
fabs.o/fneg.o should be built in the case
that CONFIG_MATH_EMULATION or CONFIG_SPE or both are
enabled. Because I reused fabs.c and fneg.c to implement instruction
efdabs and
efdneg. Therefore, these two files should be build once we have chance
to build the files in directory math-emu. Types.c and udivmodti4.c
contain the function
that both math emulation instructions and spe instructions may  
call, so
they always need
to be built.
Right, but doesn't the new rule say to always build, regardless if  
CONFIG_MATH_EMULATION or CONFIG_SPE are set?

Why not just duplicate fabs.o fneg.o ... in both lists.  I don't  
think that will cause any harm.

- k

RE: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Zhu Ebony-r57400 <hidden>
Date: 2007-02-09 05:15:27

=20
quoted
quoted
quoted
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/=20
kernel/head_fsl_booke.S index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception,
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound,
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor,=20
performance_monitor_exception, EXC_XFER_STD) @@ -840,6 +840,8 @@=20
load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use of SPE now */
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE |
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
We should do this via INIT_THREAD, is there a reason that=20
you want to=20
quoted
quoted
set these always?
I just thought it's the first time that an SPE instruction is=20
encountered, so I enable the exceptions here.
=20
Lets do this via INIT_THREAD instead, its cleaner. (just=20
remember to add the proper ifdef protection for SPE_IEEE
Talking about INIT_THREAD, I'm wondering where is the best place to
enble the exceptions? Please advice!

And also, I will put all of your other suggestions into next patches.
Thank you!

B.R.
Ebony

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Kumar Gala <hidden>
Date: 2007-02-09 05:29:26

On Feb 8, 2007, at 11:15 PM, Zhu Ebony-r57400 wrote:
quoted
quoted
quoted
quoted
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/
kernel/head_fsl_booke.S index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception,
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound,
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor,
performance_monitor_exception, EXC_XFER_STD) @@ -840,6 +840,8 @@
load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use of SPE now */
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE |
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
We should do this via INIT_THREAD, is there a reason that
you want to
quoted
quoted
set these always?
I just thought it's the first time that an SPE instruction is
encountered, so I enable the exceptions here.
Lets do this via INIT_THREAD instead, its cleaner. (just
remember to add the proper ifdef protection for SPE_IEEE
Talking about INIT_THREAD, I'm wondering where is the best place to
enble the exceptions? Please advice!
What's the issue with enabling via INIT_THREAD?  am I missing something?
And also, I will put all of your other suggestions into next patches.
Thank you!
Ok.

RE: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Zhu Ebony-r57400 <hidden>
Date: 2007-02-09 05:48:14

=20
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]=20
Sent: Friday, February 09, 2007 1:29 PM
To: Zhu Ebony-r57400
Cc: paulus@samba.org; linuxppc-dev@ozlabs.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support=20
for Embedded Floating-Point instructions
=20
=20
On Feb 8, 2007, at 11:15 PM, Zhu Ebony-r57400 wrote:
=20
quoted
quoted
quoted
quoted
quoted
diff --git a/arch/powerpc/kernel/head_fsl_booke.S=20
b/arch/powerpc/=20
quoted
quoted
quoted
quoted
quoted
kernel/head_fsl_booke.S index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound,=20
unknown_exception,
quoted
quoted
quoted
quoted
quoted
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound,
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor,=20
performance_monitor_exception, EXC_XFER_STD) @@ -840,6 +840,8 @@
load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use=20
of SPE now */
quoted
quoted
quoted
quoted
quoted
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE |=20
SPEFSCR_FUNFE |
quoted
quoted
quoted
quoted
quoted
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
We should do this via INIT_THREAD, is there a reason that
you want to
quoted
quoted
set these always?
I just thought it's the first time that an SPE instruction is=20
encountered, so I enable the exceptions here.
Lets do this via INIT_THREAD instead, its cleaner. (just=20
remember to=20
quoted
quoted
add the proper ifdef protection for SPE_IEEE
Talking about INIT_THREAD, I'm wondering where is the best place to=20
enble the exceptions? Please advice!
=20
What's the issue with enabling via INIT_THREAD?  am I missing=20
something?
Do you mean that add=20
".spefscr =3D SPEFSCR_FINV| SPEFSCR_FDBZE|SPEFSCR_FUNFE|SPEFSCR_FOVFE"
In the defination of INIT_THREAD?

I think it should work.

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Kumar Gala <hidden>
Date: 2007-02-09 06:04:28

On Feb 8, 2007, at 11:48 PM, Zhu Ebony-r57400 wrote:
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Friday, February 09, 2007 1:29 PM
To: Zhu Ebony-r57400
Cc: paulus@samba.org; linuxppc-dev@ozlabs.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support
for Embedded Floating-Point instructions


On Feb 8, 2007, at 11:15 PM, Zhu Ebony-r57400 wrote:
quoted
quoted
quoted
quoted
quoted
diff --git a/arch/powerpc/kernel/head_fsl_booke.S
b/arch/powerpc/
quoted
quoted
quoted
quoted
quoted
kernel/head_fsl_booke.S index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound,
unknown_exception,
quoted
quoted
quoted
quoted
quoted
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound,
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor,
performance_monitor_exception, EXC_XFER_STD) @@ -840,6 +840,8 @@
load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use
of SPE now */
quoted
quoted
quoted
quoted
quoted
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE |
SPEFSCR_FUNFE |
quoted
quoted
quoted
quoted
quoted
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
We should do this via INIT_THREAD, is there a reason that
you want to
quoted
quoted
set these always?
I just thought it's the first time that an SPE instruction is
encountered, so I enable the exceptions here.
Lets do this via INIT_THREAD instead, its cleaner. (just
remember to
quoted
quoted
add the proper ifdef protection for SPE_IEEE
Talking about INIT_THREAD, I'm wondering where is the best place to
enble the exceptions? Please advice!
What's the issue with enabling via INIT_THREAD?  am I missing
something?
Do you mean that add
".spefscr = SPEFSCR_FINV| SPEFSCR_FDBZE|SPEFSCR_FUNFE|SPEFSCR_FOVFE"
In the defination of INIT_THREAD?
You may want to have something like #define SPE_EXCEPTION_ENABLE  
(SPEFSCR_FINV| SPEFSCR_FDBZE|SPEFSCR_FUNFE|SPEFSCR_FOVFE)

Yep, with the proper #ifdef CONFIG_ protection.

- k

RE: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Zhu Ebony-r57400 <hidden>
Date: 2007-02-09 06:27:25

=20
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]=20
Sent: Friday, February 09, 2007 2:04 PM
To: Zhu Ebony-r57400
Cc: paulus@samba.org; linuxppc-dev@ozlabs.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support=20
for Embedded Floating-Point instructions
=20
=20
On Feb 8, 2007, at 11:48 PM, Zhu Ebony-r57400 wrote:
=20
quoted
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Friday, February 09, 2007 1:29 PM
To: Zhu Ebony-r57400
Cc: paulus@samba.org; linuxppc-dev@ozlabs.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support for=20
Embedded Floating-Point instructions


On Feb 8, 2007, at 11:15 PM, Zhu Ebony-r57400 wrote:
quoted
quoted
quoted
quoted
quoted
diff --git a/arch/powerpc/kernel/head_fsl_booke.S
b/arch/powerpc/
quoted
quoted
quoted
quoted
quoted
kernel/head_fsl_booke.S index 66877bd..0d05db0 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -705,7 +705,7 @@ #else
 #endif /* CONFIG_SPE */

 	/* SPE Floating Point Round */
-	EXCEPTION(0x2050, SPEFloatingPointRound,
unknown_exception,
quoted
quoted
quoted
quoted
quoted
EXC_XFER_EE)
+	EXCEPTION(0x2050, SPEFloatingPointRound,
SPEFloatingPointException_Round, EXC_XFER_EE)

 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor,=20
performance_monitor_exception, EXC_XFER_STD) @@=20
-840,6 +840,8 @@
quoted
quoted
quoted
quoted
quoted
quoted
quoted
load_up_spe:
 	oris	r5,r5,MSR_SPE@h
 	mtmsr	r5			/* enable use
of SPE now */
quoted
quoted
quoted
quoted
quoted
 	isync
+	li	r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE |
SPEFSCR_FUNFE |
quoted
quoted
quoted
quoted
quoted
SPEFSCR_FOVFE)
+	mtspr   SPRN_SPEFSCR,r5
We should do this via INIT_THREAD, is there a reason that
you want to
quoted
quoted
set these always?
I just thought it's the first time that an SPE instruction is=20
encountered, so I enable the exceptions here.
Lets do this via INIT_THREAD instead, its cleaner. (just
remember to
quoted
quoted
add the proper ifdef protection for SPE_IEEE
Talking about INIT_THREAD, I'm wondering where is the=20
best place to=20
quoted
quoted
quoted
enble the exceptions? Please advice!
What's the issue with enabling via INIT_THREAD?  am I missing=20
something?
Do you mean that add
".spefscr =3D SPEFSCR_FINV| =
SPEFSCR_FDBZE|SPEFSCR_FUNFE|SPEFSCR_FOVFE"
quoted
In the defination of INIT_THREAD?
=20
You may want to have something like #define=20
SPE_EXCEPTION_ENABLE (SPEFSCR_FINV|=20
SPEFSCR_FDBZE|SPEFSCR_FUNFE|SPEFSCR_FOVFE)
=20
Yep, with the proper #ifdef CONFIG_ protection.
OK, I got your point.

B.R.
Ebony

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Segher Boessenkool <hidden>
Date: 2007-02-09 14:40:21

quoted
quoted
I thought we were going to have some general Kconfig option
to enable all this?  EMDEDDED_FP_IEEE or something like that
So that users have chance to enable/disable fully IEEE compliance?
Segher
had mentioned this, and it sounds reasonable.
Its alot of code to bring in if you don't care about IEEE compliance.
Yes certainly, and that's important for embedded applications.

My point however is that this should be selectable *per process*
at runtime.  Compare to the AltiVec situation (where processes
can select (non-)IEEE behaviour by themselves); most tasks do
*not* want IEEE behaviour as it is just too expensive (and not
necessary for many applications).


Segher

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Sergei Shtylyov <hidden>
Date: 2007-02-22 12:48:38

Hello.

ebony.zhu@freescale.com wrote:
Add the general support for Embedded Floating-Point instructions
to fully comply with IEEE-754.
Signed-off-by:Ebony Zhu [off-list ref]
---
 arch/powerpc/kernel/head_fsl_booke.S |    4 
 arch/powerpc/kernel/traps.c          |   57 +++++
 arch/powerpc/math-emu/Makefile       |   25 ++
 arch/powerpc/math-emu/sfp-machine.h  |    2 
 arch/powerpc/math-emu/spe.h          |    1 
 arch/powerpc/sysdev/Makefile         |    1 
 arch/powerpc/sysdev/sigfpe_handler.c |  361 ++++++++++++++++++++++++++++++++++
    I'm sorry, but is sysdev/ really fitting place for this file? Shouldn't it 
be under kernel/ or math-emu/ instead?

WBR, Sergei

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Sergei Shtylyov <hidden>
Date: 2007-02-22 13:44:06

Hello, I wrote:
quoted
Add the general support for Embedded Floating-Point instructions
to fully comply with IEEE-754.
quoted
 arch/powerpc/sysdev/sigfpe_handler.c |  361
++++++++++++++++++++++++++++++++++
   I'm sorry, but is sysdev/ really fitting place for this file? 
Shouldn't it be under kernel/ or math-emu/ instead?
    Also, the name doesn't look fittingto me, since we're not handling 
*SIGFPE* here (which is for userland), we're handling SPE exceptions.

WBR, Sergei

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Segher Boessenkool <hidden>
Date: 2007-02-22 16:36:56

quoted
quoted
 arch/powerpc/sysdev/sigfpe_handler.c |  361
++++++++++++++++++++++++++++++++++
quoted
   I'm sorry, but is sysdev/ really fitting place for this file?
Shouldn't it be under kernel/ or math-emu/ instead?
    Also, the name doesn't look fittingto me, since we're not handling
*SIGFPE* here (which is for userland), we're handling SPE exceptions.
arch/powerpc/math-emu/spe/<whatever>.c seems like a good
place?


Segher

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Sergei Shtylyov <hidden>
Date: 2007-02-22 16:56:18

Hello.

Segher Boessenkool wrote:
quoted
quoted
quoted
 arch/powerpc/sysdev/sigfpe_handler.c |  361
++++++++++++++++++++++++++++++++++
quoted
quoted
   I'm sorry, but is sysdev/ really fitting place for this file?
Shouldn't it be under kernel/ or math-emu/ instead?
quoted
    Also, the name doesn't look fittingto me, since we're not handling
*SIGFPE* here (which is for userland), we're handling SPE exceptions.
arch/powerpc/math-emu/spe/<whatever>.c seems like a good
place?
    Yeah, certainly more like it. :-)
Segher
WBR, Sergei

Re: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Kumar Gala <hidden>
Date: 2007-02-22 18:23:40

On Feb 22, 2007, at 10:56 AM, Sergei Shtylyov wrote:
Hello.

Segher Boessenkool wrote:
quoted
quoted
quoted
quoted
 arch/powerpc/sysdev/sigfpe_handler.c |  361
++++++++++++++++++++++++++++++++++
quoted
quoted
quoted
   I'm sorry, but is sysdev/ really fitting place for this file?
Shouldn't it be under kernel/ or math-emu/ instead?
quoted
quoted
    Also, the name doesn't look fittingto me, since we're not  
handling
*SIGFPE* here (which is for userland), we're handling SPE  
exceptions.
quoted
arch/powerpc/math-emu/spe/<whatever>.c seems like a good
place?
    Yeah, certainly more like it. :-)
quoted
Segher
Agreed, this shouldn't have been in sysdev, didn't notice that :)

We should probably rename this as well, since its not just handling  
the sigfpe part, but the actual fixup/emulation.

- k

RE: [patch][5/5] powerpc V2: Add the general support for Embedded Floating-Point instructions

From: Zhu Ebony-r57400 <hidden>
Date: 2007-03-08 07:04:49

=20
-----Original Message-----
From: Segher Boessenkool [mailto:segher@kernel.crashing.org]=20
Sent: Friday, February 09, 2007 10:40 PM
To: Kumar Gala
Cc: paulus@samba.org; Zhu Ebony-r57400; linuxppc-dev@ozlabs.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support=20
for Embedded Floating-Point instructions
=20
quoted
quoted
quoted
I thought we were going to have some general Kconfig option to=20
enable all this?  EMDEDDED_FP_IEEE or something like that
So that users have chance to enable/disable fully IEEE compliance?
Segher
had mentioned this, and it sounds reasonable.
Its alot of code to bring in if you don't care about IEEE=20
compliance.
=20
Yes certainly, and that's important for embedded applications.
=20
My point however is that this should be selectable *per=20
process* at runtime.  Compare to the AltiVec situation (where=20
processes can select (non-)IEEE behaviour by themselves);=20
most tasks do
*not* want IEEE behaviour as it is just too expensive (and=20
not necessary for many applications).
=20
=20
Segher
Sorry for the delaying response since I just came back from vacation.

Agreed with you that the IEEE handler is expensive for processes.  Do
you
think adding a switch to the Kconfig option is not enough?  I'm
wondering how
to make it selectable *per process* at runtime.

Ebony

RE: [patch][5/5] powerpc V2: Add the general support for EmbeddedFloating-Point instructions

From: Zhu Ebony-r57400 <hidden>
Date: 2007-03-08 07:12:09

=20
-----Original Message-----
From: linuxppc-dev-bounces+ebony.zhu=3Dfreescale.com@ozlabs.org=20
[mailto:linuxppc-dev-bounces+ebony.zhu=3Dfreescale.com@ozlabs.or
g] On Behalf Of Kumar Gala
Sent: Friday, February 23, 2007 2:23 AM
To: Sergei Shtylyov
Cc: linuxppc-dev@ozlabs.org; paulus@samba.org
Subject: Re: [patch][5/5] powerpc V2: Add the general support=20
for EmbeddedFloating-Point instructions
=20
=20
On Feb 22, 2007, at 10:56 AM, Sergei Shtylyov wrote:
=20
quoted
Hello.

Segher Boessenkool wrote:
quoted
quoted
quoted
quoted
 arch/powerpc/sysdev/sigfpe_handler.c |  361
++++++++++++++++++++++++++++++++++
quoted
quoted
quoted
   I'm sorry, but is sysdev/ really fitting place for this file?
Shouldn't it be under kernel/ or math-emu/ instead?
quoted
quoted
    Also, the name doesn't look fittingto me, since we're not=20
handling
*SIGFPE* here (which is for userland), we're handling SPE=20
exceptions.
quoted
arch/powerpc/math-emu/spe/<whatever>.c seems like a good place?
    Yeah, certainly more like it. :-)
quoted
Segher
=20
Agreed, this shouldn't have been in sysdev, didn't notice that :)
=20
We should probably rename this as well, since its not just=20
handling the sigfpe part, but the actual fixup/emulation.
=20
- k
Hi All,

Base on your suggestion, how about move sigfpe_handler.c to
arch/powerpc/math-emu/spe/spe_handler.c? Or do you have any other
suggestions on file name?

B.R.
Ebony
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help