[patch][5/5] powerpc: Add the general support for Embedded Floating-Point instructions
Zhu Ebony-r57400
ebony.zhu at freescale.com
Fri Jan 12 18:45:07 EST 2007
Hi Kumar
Please see my inline comments.
Ebony
> -----Original Message-----
> From: Kumar Gala [mailto:galak at kernel.crashing.org]
> Sent: 2007年1月12日 14:41
> To: Zhu Ebony-r57400
> Cc: paulus at samba.org; linuxppc-dev at ozlabs.org
> Subject: Re: [patch][5/5] powerpc: Add the general support
> for Embedded Floating-Point instructions
>
>
> 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?
I'm not sure if the kernel will return from exception in a multi-thread
way, but the truth is if restoring EVRs in exsiting ret_from_except_full,
some non-SPE exception will try to retore EVR. At that time, the
MSR[SPE] may not be enabled, which will cause error.
>
> > +#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;
>
> ...
>
Since I want to save EVRs before entering the SPEFloatingPointException. Thanks
for providing an alternative way, I can try to see if it works.
> > #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.
Ok, let's keep discussing this.
>
> > /*
> > * 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?
I tried to make the code more robust here. Currently, all the SPE instructions
that may cause execption are handled. But someday if the instruction set is extended and
not supported by software, this code can make sure we handle it with powerpc
default value, which won't make kernel crash.
>
> > + return;
> > + }
> > + } else {
> > + return;
>
> How else would we get here if not by having spefscr bit set?
As above, I want to make it more robust. If no unexpected condition would happen, we can
remove this off.
>
> > + }
> > +#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.
OK, I agree.
>
> > +#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?
Currently not. We can remove it then.
>
> > +#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 *)®s->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.
Do you mean I need to do it like this:
unsigned long spefscr;
spefscr = current->thread.spefscr;
spefscr = 0x3f;
current->spefscr = spefscr ;
I'm not really understand...
>
> > + 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