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

Kumar Gala galak at kernel.crashing.org
Fri Jan 12 17:40:53 EST 2007


On Jan 11, 2007, at 11:31 PM, ebony.zhu at freescale.com wrote:

> Add the general support for Embedded Floating-Point instructions
> to fully comply with IEEE-754.
>
> Signed-off-by:Ebony Zhu <ebony.zhu at freescale.com>
> ---
>  arch/powerpc/Makefile                |    5 +
>  arch/powerpc/kernel/entry_32.S       |   50 ++++++
>  arch/powerpc/kernel/head_booke.h     |    4
>  arch/powerpc/kernel/head_fsl_booke.S |   22 ++-
>  arch/powerpc/kernel/traps.c          |   17 ++
>  arch/powerpc/math-emu/Makefile       |   29 ++-
>  arch/powerpc/math-emu/sfp-machine.h  |    4
>  arch/powerpc/sysdev/sigfpe_handler.c |  298 +++++++++++++++++++++++ 
> +++++++++++
>  arch/powerpc/sysdev/Makefile         |    1
>  9 files changed, 421 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
> index a00fe72..dd0b4b8 100644
> --- a/arch/powerpc/Makefile
> +++ b/arch/powerpc/Makefile
> @@ -134,6 +134,11 @@ core-y				+= arch/powerpc/kernel/ \
>  				   arch/powerpc/lib/ \
>  				   arch/powerpc/sysdev/ \
>  				   arch/powerpc/platforms/
> +ifeq ($(CONFIG_SPE),y)
> +ifneq ($(CONFIG_MATH_EMULATION),y)
> +core-y				+= arch/powerpc/math-emu/
> +endif
> +endif
>  core-$(CONFIG_MATH_EMULATION)	+= arch/powerpc/math-emu/
>  core-$(CONFIG_XMON)		+= arch/powerpc/xmon/
>
> diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/ 
> entry_32.S
> index c03e829..a3d4ece 100644
> --- a/arch/powerpc/kernel/entry_32.S
> +++ b/arch/powerpc/kernel/entry_32.S
> @@ -616,6 +616,56 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
>  	.long	ret_from_except
>  #endif
>
> +#ifdef CONFIG_SPE
> +	.globl  ret_from_except_spe_full
> +ret_from_except_spe_full:
> +	REST_NVGPRS(r1)
> +	/* fall through */
> +	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
> +	SYNC			/* Some chip revs have problems here... */
> +	MTMSRD(r10)		/* disable interrupts */
> +
> +	lwz     r0,THREAD+THREAD_SPEFSCR(r2)
> +	mtspr   SPRN_SPEFSCR,r0		/* restore SPEFSCR reg */
> +
> +	lwz     r0,GPR0(r1)
> +	lwz     r2,GPR2(r1)
> +	REST_4GPRS(3, r1)
> +	REST_2GPRS(7, r1)
> +	
> +	lwz     r10,_XER(r1)
> +	lwz     r11,_CTR(r1)
> +	mtspr   SPRN_XER,r10
> +	mtctr   r11
> +
> +	stwcx.  r0,0,r1                 /* to clear the reservation */
> +
> +	lwz     r11,_LINK(r1)
> +	mtlr    r11
> +	lwz     r10,_CCR(r1)
> +	mtcrf   0xff,r10
> +	REST_2GPRS(9, r1)
> +
> +	mtspr   SPRN_SPRG0,r11
> +	mtspr   SPRN_SPRG1,r12
> +	mfmsr   r11
> +	oris  r11, r11, MSR_SPE at h
> +	mtmsr   r11
> +	mfspr   r12,SPRN_SPRG3
> +	REST_32EVRS(0, r11,r12)
> +	mfspr   r11,SPRN_SPRG0
> +	mfspr   r12,SPRN_SPRG1
> +
> +	lwz     r11,_NIP(r1)
> +	lwz     r12,_MSR(r1)
> +	mtspr   SPRN_SRR0,r11
> +	mtspr   SPRN_SRR1,r12
> +	REST_2GPRS(11, r1)
> +	lwz     r1,GPR1(r1)
> +
> +	rfi
> +	b	.		/* prevent prefetch past rfi */

Why do we need a separate ret_from_except_spe_full?

> +#endif
>  	.globl	ret_from_except_full
>  ret_from_except_full:
>  	REST_NVGPRS(r1)
> diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/ 
> head_booke.h
> index 8536e76..1e14d3e 100644
> --- a/arch/powerpc/kernel/head_booke.h
> +++ b/arch/powerpc/kernel/head_booke.h
> @@ -195,6 +195,10 @@ #define EXC_XFER_EE(n, hdlr)		\
>  	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE,  
> transfer_to_handler_full, \
>  			  ret_from_except_full)
>
> +#define EXC_XFER_EE_SPE(n, hdlr)	\
> +	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE,  
> transfer_to_handler_full, \
> +			  ret_from_except_spe_full)
> +
>  #define EXC_XFER_EE_LITE(n, hdlr)	\
>  	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE,  
> transfer_to_handler, \
>  			  ret_from_except)
> diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/ 
> kernel/head_fsl_booke.S
> index 66877bd..56200b6 100644
> --- a/arch/powerpc/kernel/head_fsl_booke.S
> +++ b/arch/powerpc/kernel/head_fsl_booke.S
> @@ -699,7 +699,25 @@ #endif /* CONFIG_SPE */
>
>  	/* SPE Floating Point Data */
>  #ifdef CONFIG_SPE
> -	EXCEPTION(0x2030, SPEFloatingPointData,  
> SPEFloatingPointException, EXC_XFER_EE);
> +	START_EXCEPTION(SPEFloatingPointData)
> +	mtspr   SPRN_SPRG0,r3
> +	mtspr   SPRN_SPRG1,r4
> +	mfmsr   r3
> +	oris    r3, r3, MSR_SPE at h
> +	mtmsr   r3
> +	mfspr   r3, SPRN_SRR0
> +	lwz     r3, 0(r3)
> +	lis     r4, speinsn at ha
> +	stw     r3, speinsn at l(r4)
> +	mfspr   r4, SPRN_SPRG3
> +	mfspr   r3, SPRN_SPEFSCR
> +	stw     r3, THREAD_SPEFSCR(r4)
> +	SAVE_32EVRS(0, r3, r4)
> +	mfspr   r3, SPRN_SPRG0
> +	mfspr   r4, SPRN_SPRG1
> +	NORMAL_EXCEPTION_PROLOG
> +	addi    r3,r1,STACK_FRAME_OVERHEAD
> +	EXC_XFER_EE_SPE(0x2030, SPEFloatingPointException)

Why do we have to do any of this in the exception path?

SPEFloatingPointException can have something like:

	unsigned long pc = regs->nip;
	flush_spe_to_thread(current);

	if (get_user(insn, (u32 *)pc))
		return -EFAULT;

	...

>  #else
>  	EXCEPTION(0x2040, SPEFloatingPointData, unknown_exception,  
> EXC_XFER_EE)
>  #endif /* CONFIG_SPE */
> @@ -840,6 +858,8 @@ load_up_spe:
>  	oris	r5,r5,MSR_SPE at h
>  	mtmsr	r5			/* enable use of SPE now */
>  	isync
> +	li      r5,(SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE |  
> SPEFSCR_FOVFE)
> +	mtspr   SPRN_SPEFSCR,r5

If you want to initialize spefscr so the enables are set do it in  
INIT_THREAD.  I need to think more about if we should even be doing  
that in the kernel.

>  /*
>   * 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 535f506..68407d4 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -986,6 +986,22 @@ #endif /* CONFIG_FSL_BOOKE */
>  #ifdef CONFIG_SPE
>  void SPEFloatingPointException(struct pt_regs *regs)
>  {
> +#ifdef CONFIG_E500
> +	extern int sigfpe_handler(struct pt_regs *regs);
> +	int err;
> +	if (current->thread.spefscr & ~0x3f) {
> +		err = sigfpe_handler(regs);
> +		if (err == 0) {
> +			regs->nip += 4;
> +			return;
> +		} else {
> +			current->thread.spefscr = 0x0;

Why do clear spefscr and re-execute?

> +			return;
> +		}
> +	} else {
> +		return;

How else would we get here if not by having spefscr bit set?

> +	}
> +#else
>  	unsigned long spefscr;
>  	int fpexc_mode;
>  	int code = 0;
> @@ -1016,6 +1032,7 @@ void SPEFloatingPointException(struct pt
>
>  	_exception(SIGFPE, regs, code, regs->nip);
>  	return;

Your code should supersede the handling code that's currently there.

> +#endif
>  }
>  #endif
>
> diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/ 
> Makefile
> index 29bc912..dbb3e26 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 \
> -					fctiw.o fctiwz.o fdiv.o fdivs.o \
> +obj-y				:= fabs.o fadd.o fdiv.o fmul.o \
> +					fneg.o fsub.o types.o udivmodti4.o
> +					
> +obj-$(CONFIG_MATH_EMULATION)	+= math.o fmr.o lfd.o stfd.o \
> +					fadds.o fcmpo.o fcmpu.o \
> +					fctiw.o fctiwz.o fdivs.o \
>  					fmadd.o fmadds.o fmsub.o fmsubs.o \
> -					fmul.o fmuls.o fnabs.o fneg.o types.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 \
> +					fsqrt.o	fsqrts.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 \
> +					efdcfs.o efdcmpeq.o efdcmpgt.o efdcmplt.o efdctsf.o \
> +					efdctsi.o efdctsidz.o efdctsiz.o efdctuf.o \
> +					efdctui.o efdctuidz.o efdctuiz.o efdnabs.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..313734d 100644
> --- a/arch/powerpc/math-emu/sfp-machine.h
> +++ b/arch/powerpc/math-emu/sfp-machine.h
> @@ -166,7 +166,11 @@ #define __FP_PACK_RAW_2(fs, val, X)			\
>  #include <linux/kernel.h>
>  #include <linux/sched.h>
>
> +#ifdef CONFIG_SPE
> +#define __FPU_FPSCR	(current->thread.spefscr)
> +#else
>  #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/sysdev/sigfpe_handler.c b/arch/powerpc/ 
> sysdev/sigfpe_handler.c
> new file mode 100644
> index 0000000..6e809b2
> --- /dev/null
> +++ b/arch/powerpc/sysdev/sigfpe_handler.c
> @@ -0,0 +1,298 @@
> +/*
> + * arch/powerpc/sysdev/sigfpe_handler.c
> + *
> + * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights  
> reserved.
> + *
> + * Author: Ebony Zhu, ebony.zhu at freescale.com
> + *
> + * Derived from arch/powerpc/math-emu/math.c
> + * Copyright (C) 1999  Eddie C. Dost  (ecd at 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 efdadd	fadd
> +#define efdsub	fsub
> +#define efddiv	fdiv
> +#define efdmul	fmul
> +#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

not used?

> +#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];
> +u32 speinsn;
> +
> +int
> +sigfpe_handler(struct pt_regs *regs)
> +{
> +	void *op0 = 0, *op1 = 0, *op2 = 0, *op3 = 0;
> +	int i;
> +	int (*func)(void *, void *, void *, void *);
> +	int type = 0;
> +	int flag;
> +	
> +	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]);
> +		};
> +	}
> +
> +	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;
> +	}
> +
> +	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;
> +		};
> +	}
> +	
> +	current->thread.spefscr &= 0x3f;

can't clear spefscr this way.

Need to do what the existing handler was doing here.

> +	return 0;
> +
> +illegal:
> +	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered  
> un-supported instruction.\n");
> +	return -ENOSYS;
> +}
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/ 
> Makefile
> index 04d4917..1e74e15 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -13,6 +13,7 @@ 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_MTD)		+= rom.o
> +obj-$(CONFIG_SPE)		+= sigfpe_handler.o
>
>  ifeq ($(CONFIG_PPC_MERGE),y)
>  obj-$(CONFIG_PPC_I8259)		+= i8259.o
> -- 
> 1.4.0




More information about the Linuxppc-dev mailing list