I was attempting to port software which relies on SIGFPE to macppc when I discovered that that floating point exceptions don't appear to work at all there.
After researching powerpc a bit and digging around in the kernel, I found that the two MSR bits which enable floating point exceptions, FE0 and FE1, appear to be explicitly disabled during exec and never enabled anywhere else. I made a crude attempt to turn those bits on and deliver SIGFPE to userland when appropriate, however all of userland appears to hang when the first floating point exception occurs. Is there a more fundamental, trickier reason that floating point exceptions aren't enabled on any powerpc platform, or have I just made some trivial mistake? Any advice or pointers for where to dig around more carefully are appreciated, thanks. Index: arch/powerpc/powerpc/fpu.c =================================================================== RCS file: /ruby/cvs/openbsd/src/sys/arch/powerpc/powerpc/fpu.c,v retrieving revision 1.12 diff -u arch/powerpc/powerpc/fpu.c --- arch/powerpc/powerpc/fpu.c 10 Dec 2009 16:46:09 -0000 1.12 +++ arch/powerpc/powerpc/fpu.c 12 May 2010 02:01:00 -0000 @@ -94,7 +94,7 @@ "lfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); ci->ci_fpuproc = p; pcb->pcb_fpcpu = ci; - tf->srr1 |= PSL_FP; + tf->srr1 |= PSL_FP | PSL_FE_PREC; ppc_mtmsr(msr); __asm volatile("isync"); } Index: arch/powerpc/powerpc/trap.c =================================================================== RCS file: /ruby/cvs/openbsd/src/sys/arch/powerpc/powerpc/trap.c,v retrieving revision 1.83 diff -u arch/powerpc/powerpc/trap.c --- arch/powerpc/powerpc/trap.c 14 Jun 2008 10:55:20 -0000 1.83 +++ arch/powerpc/powerpc/trap.c 12 May 2010 01:35:56 -0000 @@ -593,12 +593,38 @@ #if 0 char *errstr[8]; int errnum = 0; +#endif if (frame->srr1 & (1<<(31-11))) { + u_int64_t fpscr; + int fpe; + +#if 0 /* floating point enabled program exception */ errstr[errnum] = "floating point"; errnum++; +#endif + + save_fpu(); + fpscr = *(u_int64_t *)&p->p_addr->u_pcb.pcb_fpu.fpcsr; + fpe = 0; + if ((fpscr & (FPCSR_VX|FPCSR_VE)) == (FPCSR_VX|FPCSR_VE)) + fpe = FPE_FLTINV; + else if ((fpscr & (FPCSR_ZX|FPCSR_ZE)) == (FPCSR_ZX|FPCSR_ZE)) + fpe = FPE_FLTDIV; + else if ((fpscr & (FPCSR_OX|FPCSR_OE)) == (FPCSR_OX|FPCSR_OE)) + fpe = FPE_FLTOVF; + else if ((fpscr & (FPCSR_UX|FPCSR_UE)) == (FPCSR_UX|FPCSR_UE)) + fpe = FPE_FLTUND; + else if ((fpscr & (FPCSR_XX|FPCSR_XE)) == (FPCSR_XX|FPCSR_XE)) + fpe = FPE_FLTRES; + sv.sival_int = frame->srr0; + KERNEL_PROC_LOCK(p); + trapsignal(p, SIGFPE, type, fpe, sv); + KERNEL_PROC_UNLOCK(p); + break; } +#if 0 if (frame->srr1 & (1<<(31-12))) { /* illegal instruction program exception */ errstr[errnum] = "illegal instruction";