Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/powerpc/powerpc When trying to figure out which cod...
details: https://anonhg.NetBSD.org/src/rev/6c0af1fa7237
branches: trunk
changeset: 565350:6c0af1fa7237
user: matt <matt%NetBSD.org@localhost>
date: Sun Apr 04 22:20:44 2004 +0000
description:
When trying to figure out which code to return, use the exception enable
bits to mask out the undesired exceptions. (Thanks to Todd Whitesel for
the idea).
diffstat:
sys/arch/powerpc/powerpc/fpu.c | 48 +++++++++++++++++++++--------------------
1 files changed, 25 insertions(+), 23 deletions(-)
diffs (103 lines):
diff -r 6cc6bd69d05c -r 6c0af1fa7237 sys/arch/powerpc/powerpc/fpu.c
--- a/sys/arch/powerpc/powerpc/fpu.c Sun Apr 04 20:17:27 2004 +0000
+++ b/sys/arch/powerpc/powerpc/fpu.c Sun Apr 04 22:20:44 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu.c,v 1.13 2004/04/04 19:21:36 matt Exp $ */
+/* $NetBSD: fpu.c,v 1.14 2004/04/04 22:20:44 matt Exp $ */
/*
* Copyright (C) 1996 Wolfgang Solfrank.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.13 2004/04/04 19:21:36 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.14 2004/04/04 22:20:44 matt Exp $");
#include "opt_multiprocessor.h"
@@ -226,9 +226,9 @@
}
#define STICKYBITS (FPSCR_VX|FPSCR_OX|FPSCR_UX|FPSCR_ZX|FPSCR_XX)
-#if STICKYBITS & (PCB_FE0|PCB_FE1|PCB_VEC|PCB_FPU)
-#error PCB flags overlap FPSCR STICKYBITS
-#endif
+#define STICKYSHIFT 25
+#define MASKBITS (FPSCR_VE|FPSCR_OE|FPSCR_UE|FPSCR_ZE|FPSCR_XE)
+#define MASKSHIFT 3
int
get_fpu_fault_code(void)
@@ -236,21 +236,22 @@
#ifdef DIAGNOSTIC
struct cpu_info *ci = curcpu();
#endif
- struct lwp *l = curlwp;
- struct pcb *pcb = &l->l_addr->u_pcb;
+ struct pcb *pcb = curpcb;
register_t msr;
- uint64_t tmp;
- uint32_t fpscr;
+ uint64_t tmp, fpscr64;
+ uint32_t fpscr, ofpscr;
int code;
KASSERT(pcb->pcb_fpcpu == ci);
KASSERT(pcb->pcb_flags & PCB_FPU);
- KASSERT(ci->ci_fpulwp == l);
+ KASSERT(ci->ci_fpulwp == curlwp);
msr = mfmsr();
mtmsr((msr & ~PSL_EE) | PSL_FP);
__asm __volatile ("isync");
__asm __volatile (
"stfd 0,0(%0)\n" /* save f0 */
+ "mffs 0\n" /* get FPSCR */
+ "stfd 0,0(%2)\n" /* store a temp copy */
"mtfsb0 0\n" /* clear FPSCR_FX */
"mtfsb0 24\n" /* clear FPSCR_VE */
"mtfsb0 25\n" /* clear FPSCR_OE */
@@ -260,29 +261,30 @@
"mffs 0\n" /* get FPSCR */
"stfd 0,0(%1)\n" /* store it */
"lfd 0,0(%0)\n" /* restore f0 */
- :: "b"(&tmp), "b"(&pcb->pcb_fpu.fpscr));
+ :: "b"(&tmp), "b"(&pcb->pcb_fpu.fpscr), "b"(&fpscr64));
mtmsr(msr);
__asm __volatile ("isync");
/*
- * Now determine the fault type. First we see if any of the sticky
- * bits have changed since the FP exception. If so, we only want
- * to return the code for the new exception. If not, we look at all
- * the bits.
+ * Now determine the fault type. First we test to see if any of sticky
+ * bits correspond to the enabled exceptions. If so, we only test
+ * those bits. If not, we look at all the bits. (In reality, we only
+ * could get an exception if FPSCR_FEX changed state. So we should
+ * have at least one bit that corresponds).
*/
+ ofpscr = (uint32_t)fpscr64;
+ ofpscr &= ofpscr << (STICKYSHIFT - MASKSHIFT);
fpscr = (uint32_t)(*(uint64_t *)&pcb->pcb_fpu.fpscr);
- if ((fpscr & ~pcb->pcb_flags) & STICKYBITS)
- fpscr &= ~pcb->pcb_flags;
+ if (fpscr & ofpscr & STICKYBITS)
+ fpscr &= ofpscr;
+
+ /*
+ * Let's determine what the appropriate code is.
+ */
if (fpscr & FPSCR_VX) code = FPE_FLTINV;
else if (fpscr & FPSCR_OX) code = FPE_FLTOVF;
else if (fpscr & FPSCR_UX) code = FPE_FLTUND;
else if (fpscr & FPSCR_ZX) code = FPE_FLTDIV;
else if (fpscr & FPSCR_XX) code = FPE_FLTRES;
else code = 0;
- /*
- * Now we save the latest set of sticky bits. This is so we can see
- * what's changed on the next SIGFPE.
- */
- pcb->pcb_flags &= ~STICKYBITS;
- pcb->pcb_flags |= fpscr & STICKYBITS;
return code;
}
Home |
Main Index |
Thread Index |
Old Index