Index: sys/powerpc/include/psl.h =================================================================== --- sys/powerpc/include/psl.h +++ sys/powerpc/include/psl.h @@ -46,6 +46,7 @@ #define PSL_PR 0x00004000UL /* privilege mode (1 == user) */ #define PSL_FP 0x00002000UL /* floating point enable */ #define PSL_ME 0x00001000UL /* machine check enable */ +#define PSL_FPE 0x00100000UL /* floating point enabled exception */ #define PSL_FE0 0x00000800UL /* floating point interrupt mode 0 */ #define PSL_FE1 0x00000100UL /* floating point interrupt mode 1 */ #define PSL_PMM 0x00000004UL /* performance monitor mark */ @@ -88,7 +89,7 @@ #define PSL_FE_NONREC PSL_FE1 /* imprecise non-recoverable */ #define PSL_FE_REC PSL_FE0 /* imprecise recoverable */ #define PSL_FE_PREC (PSL_FE0 | PSL_FE1) /* precise */ -#define PSL_FE_DFLT PSL_FE_DIS /* default == none */ +#define PSL_FE_DFLT PSL_FE_PREC /* default == precise */ #ifndef LOCORE extern register_t psl_kernset; /* Default MSR values for kernel */ Index: sys/powerpc/powerpc/exec_machdep.c =================================================================== --- sys/powerpc/powerpc/exec_machdep.c +++ sys/powerpc/powerpc/exec_machdep.c @@ -1158,6 +1158,11 @@ sig = fpu_emulate(frame, &pcb->pcb_fpu); if ((sig == 0 || sig == SIGFPE) && pcb->pcb_flags & PCB_FPU) enable_fpu(td); +#else + if (frame->srr1 & PSL_FPE) { + /* Floating-Point Enabled Exception type Program interrupt */ + sig = SIGFPE; + } #endif if (sig == SIGILL) { if (pcb->pcb_lastill != frame->srr0) { Index: sys/powerpc/powerpc/trap.c =================================================================== --- sys/powerpc/powerpc/trap.c +++ sys/powerpc/powerpc/trap.c @@ -398,7 +398,34 @@ else if (frame->srr1 & EXC_PGM_ILLEGAL) ucode = ILL_ILLOPC; } else if (sig == SIGFPE) - ucode = FPE_FLTINV; /* Punt for now, invalid operation. */ + { + union { + double d; + uint32_t fpscr[2]; + } u; + + int msr = mfmsr(); + mtmsr(msr | PSL_FP); + + __asm __volatile ("mffs 0; stfd 0,0(%0)" + :: "b"(&u.d)); + + mtmsr(msr); + + ucode = 0; + if (u.fpscr[1] & FPSCR_ZX) + ucode |= FPE_FLTDIV; + if (u.fpscr[1] & FPSCR_OX) + ucode |= FPE_FLTOVF; + if (u.fpscr[1] & FPSCR_UX) + ucode |= FPE_FLTUND; + if (u.fpscr[1] & FPSCR_XX) + ucode |= FPE_FLTRES; + if (u.fpscr[1] & FPSCR_VX) + ucode |= FPE_FLTINV; + + enable_fpu(td); + } } break;