From cf5c2e543c7b4a5ec49f547070c0f3f4c95e20ed Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Wed, 10 Jul 2013 09:43:42 +0800 Subject: powerpc/math-emu: Remove the dead code in math.c The math.c is only built when CONFIG_MATH_EMULATION is enabled. So we would never get into the case that CONFIG_MATH_EMULATION is not defined in this file. Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/math-emu/math.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'arch/powerpc/math-emu/math.c') diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c index 0328e66e0799..cefb4f2f4039 100644 --- a/arch/powerpc/math-emu/math.c +++ b/arch/powerpc/math-emu/math.c @@ -231,47 +231,6 @@ do_mathemu(struct pt_regs *regs) if (get_user(insn, (u32 *)pc)) return -EFAULT; -#ifndef CONFIG_MATH_EMULATION - switch (insn >> 26) { - case LFD: - idx = (insn >> 16) & 0x1f; - sdisp = (insn & 0xffff); - op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f); - op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); - lfd(op0, op1, op2, op3); - break; - case LFDU: - idx = (insn >> 16) & 0x1f; - sdisp = (insn & 0xffff); - op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f); - op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); - lfd(op0, op1, op2, op3); - regs->gpr[idx] = (unsigned long)op1; - break; - case STFD: - idx = (insn >> 16) & 0x1f; - sdisp = (insn & 0xffff); - op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f); - op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); - stfd(op0, op1, op2, op3); - break; - case STFDU: - idx = (insn >> 16) & 0x1f; - sdisp = (insn & 0xffff); - op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f); - op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); - stfd(op0, op1, op2, op3); - regs->gpr[idx] = (unsigned long)op1; - break; - case OP63: - op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f); - op1 = (void *)¤t->thread.TS_FPR((insn >> 11) & 0x1f); - fmr(op0, op1, op2, op3); - break; - default: - goto illegal; - } -#else /* CONFIG_MATH_EMULATION */ switch (insn >> 26) { case LFS: func = lfs; type = D; break; case LFSU: func = lfs; type = DU; break; @@ -485,7 +444,6 @@ do_mathemu(struct pt_regs *regs) default: break; } -#endif /* CONFIG_MATH_EMULATION */ regs->nip += 4; return 0; -- cgit From f0870c55301da7e27be53d65dc62020a0fba749a Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Wed, 10 Jul 2013 09:43:43 +0800 Subject: powerpc/math-emu: Remove the unneeded check for CONFIG_MATH_EMULATION in math.c The math.c is only built when CONFIG_MATH_EMULATION is enabled. So the #ifdef check for CONFIG_MATH_EMULATION in it seems redundant. Drop all of them. Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/math-emu/math.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/powerpc/math-emu/math.c') diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c index cefb4f2f4039..3fe8e35287a1 100644 --- a/arch/powerpc/math-emu/math.c +++ b/arch/powerpc/math-emu/math.c @@ -154,7 +154,6 @@ FLOATFUNC(fsqrts); #define XEU 15 #define XFLB 10 -#ifdef CONFIG_MATH_EMULATION static int record_exception(struct pt_regs *regs, int eflag) { @@ -212,7 +211,6 @@ record_exception(struct pt_regs *regs, int eflag) return (fpscr & FPSCR_FEX) ? 1 : 0; } -#endif /* CONFIG_MATH_EMULATION */ int do_mathemu(struct pt_regs *regs) @@ -222,11 +220,9 @@ do_mathemu(struct pt_regs *regs) signed short sdisp; u32 insn = 0; int idx = 0; -#ifdef CONFIG_MATH_EMULATION int (*func)(void *, void *, void *, void *); int type = 0; int eflag, trap; -#endif if (get_user(insn, (u32 *)pc)) return -EFAULT; -- cgit From 6761ee3d7e139ec8728e1515bfc5fdcaf3be317e Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Sun, 14 Jul 2013 16:40:06 +0800 Subject: powerpc/math-emu: Move the flush FPU state function into do_mathemu By doing this we can make sure that the FPU state is only flushed to the thread struct when it is really needed. Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/math-emu/math.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/powerpc/math-emu/math.c') diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c index 3fe8e35287a1..f9ef34746f16 100644 --- a/arch/powerpc/math-emu/math.c +++ b/arch/powerpc/math-emu/math.c @@ -420,6 +420,15 @@ do_mathemu(struct pt_regs *regs) goto illegal; } + /* + * If we support a HW FPU, we need to ensure the FP state + * is flushed into the thread_struct before attempting + * emulation + */ +#ifdef CONFIG_PPC_FPU + flush_fp_to_thread(current); +#endif + eflag = func(op0, op1, op2, op3); if (insn & 1) { -- cgit From e05c0e81b0628808a7490c35d1803644a18b0405 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Tue, 16 Jul 2013 19:57:15 +0800 Subject: powerpc: split She math emulation into two parts For some SoC (such as the FSL BookE) even though there does have a hardware FPU, but not all floating point instructions are implemented. Unfortunately some versions of gcc do use these unimplemented instructions. Then we have to enable the math emulation to workaround this issue. It seems a little redundant to have the support to emulate all the floating point instructions in this case. So split the math emulation into two parts. One is for the SoC which doesn't have FPU at all and the other for the SoC which does have the hardware FPU and only need some special floating point instructions to be emulated. Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/math-emu/math.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/math-emu/math.c') diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c index f9ef34746f16..49eb2ac08fd3 100644 --- a/arch/powerpc/math-emu/math.c +++ b/arch/powerpc/math-emu/math.c @@ -13,6 +13,20 @@ #define FLOATFUNC(x) extern int x(void *, void *, void *, void *) +/* The instructions list which may be not implemented by a hardware FPU */ +FLOATFUNC(fre); +FLOATFUNC(frsqrtes); +FLOATFUNC(fsqrt); +FLOATFUNC(fsqrts); +FLOATFUNC(mtfsf); +FLOATFUNC(mtfsfi); + +#ifdef CONFIG_MATH_EMULATION_HW_UNIMPLEMENTED +#undef FLOATFUNC(x) +#define FLOATFUNC(x) static inline int x(void *op1, void *op2, void *op3, \ + void *op4) { } +#endif + FLOATFUNC(fadd); FLOATFUNC(fadds); FLOATFUNC(fdiv); @@ -42,8 +56,6 @@ FLOATFUNC(mcrfs); FLOATFUNC(mffs); FLOATFUNC(mtfsb0); FLOATFUNC(mtfsb1); -FLOATFUNC(mtfsf); -FLOATFUNC(mtfsfi); FLOATFUNC(lfd); FLOATFUNC(lfs); @@ -58,13 +70,9 @@ FLOATFUNC(fnabs); FLOATFUNC(fneg); /* Optional */ -FLOATFUNC(fre); FLOATFUNC(fres); FLOATFUNC(frsqrte); -FLOATFUNC(frsqrtes); FLOATFUNC(fsel); -FLOATFUNC(fsqrt); -FLOATFUNC(fsqrts); #define OP31 0x1f /* 31 */ -- cgit From 037f0eed57c3f35367ac32275e45f24e297549e9 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Sun, 14 Jul 2013 17:02:05 +0800 Subject: powerpc: Make flush_fp_to_thread() nop when CONFIG_PPC_FPU is disabled In the current kernel, the function flush_fp_to_thread() is not dependent on CONFIG_PPC_FPU. So most invocations of this function is not wrapped by CONFIG_PPC_FPU. Even through we don't really save the FPRs to the thread struct if CONFIG_PPC_FPU is not enabled, but there does have some runtime overhead such as the check for tsk->thread.regs and preempt disable and enable. It really make no sense to do that. So make it a nop when CONFIG_PPC_FPU is disabled. Also remove the wrapped #ifdef CONFIG_PPC_FPU when invoking this function. Signed-off-by: Kevin Hao Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/math-emu/math.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/powerpc/math-emu/math.c') diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c index 49eb2ac08fd3..bc901623d8df 100644 --- a/arch/powerpc/math-emu/math.c +++ b/arch/powerpc/math-emu/math.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -433,9 +434,7 @@ do_mathemu(struct pt_regs *regs) * is flushed into the thread_struct before attempting * emulation */ -#ifdef CONFIG_PPC_FPU flush_fp_to_thread(current); -#endif eflag = func(op0, op1, op2, op3); -- cgit From cc7059b5ea730edde256deb94a42f8e9e732d9b8 Mon Sep 17 00:00:00 2001 From: James Yang Date: Thu, 4 Jul 2013 16:18:44 -0500 Subject: powerpc/math-emu: Fix load/store indexed emulation Load/store indexed instructions where the index register RA=R0, such as "lfdx f1,0,r3", are not illegal. Load/store indexed with update instructions where the index register RA=R0, such as "lfdux f1,0,r3", are invalid, and, to be consistent with existing math-emu behavior for other invalid instruction forms, will signal as illegal. Signed-off-by: James Yang Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/math-emu/math.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'arch/powerpc/math-emu/math.c') diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c index bc901623d8df..ab151f040502 100644 --- a/arch/powerpc/math-emu/math.c +++ b/arch/powerpc/math-emu/math.c @@ -380,21 +380,16 @@ do_mathemu(struct pt_regs *regs) case XE: idx = (insn >> 16) & 0x1f; op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f); - if (!idx) { - if (((insn >> 1) & 0x3ff) == STFIWX) - op1 = (void *)(regs->gpr[(insn >> 11) & 0x1f]); - else - goto illegal; - } else { - op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]); - } - + op1 = (void *)((idx ? regs->gpr[idx] : 0) + + regs->gpr[(insn >> 11) & 0x1f]); break; case XEU: idx = (insn >> 16) & 0x1f; + if (!idx) + goto illegal; op0 = (void *)¤t->thread.TS_FPR((insn >> 21) & 0x1f); - op1 = (void *)((idx ? regs->gpr[idx] : 0) + op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]); break; -- cgit