static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs) { int si_code = 0; pr_debug("VFP: raising exceptions %08x\n", exceptions); if (exceptions == VFP_EXCEPTION_ERROR) { vfp_panic("unhandled bounce", inst); vfp_raise_sigfpe(0, regs); return; } if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); fpscr |= exceptions; fmxr(FPSCR, fpscr); #define RAISE(stat,en,sig) \ if (exceptions & stat && fpscr & en) \ si_code = sig; RAISE(FPSCR_DZC, FPSCR_DZE, FPE_FLTDIV); RAISE(FPSCR_IXC, FPSCR_IXE, FPE_FLTRES); RAISE(FPSCR_UFC, FPSCR_UFE, FPE_FLTUND); RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF); RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV); if (si_code) vfp_raise_sigfpe(si_code, regs); }
/* * Process bitmask of exception conditions. */ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs) { int si_code = 0; pr_debug("VFP: raising exceptions %08x\n", exceptions); if (exceptions == VFP_EXCEPTION_ERROR) { vfp_panic("unhandled bounce", inst); vfp_raise_sigfpe(0, regs); return; } /* * If any of the status flags are set, update the FPSCR. * Comparison instructions always return at least one of * these flags set. */ /* ARM spec does not define that H/W have to clear all condition flags when bouncing a floating-point compare instruction. The new support code only ORR the result flags on top of the original flags without clearing any flags. This does not make any sense to me, because clearing flags is also part of the compare result. So we clear these bits here to make it PASS */ if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); fpscr |= exceptions; fmxr(FPSCR, fpscr); #define RAISE(stat,en,sig) \ if (exceptions & stat && fpscr & en) \ si_code = sig; /* * These are arranged in priority order, least to highest. */ RAISE(FPSCR_DZC, FPSCR_DZE, FPE_FLTDIV); RAISE(FPSCR_IXC, FPSCR_IXE, FPE_FLTRES); RAISE(FPSCR_UFC, FPSCR_UFE, FPE_FLTUND); RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF); RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV); RAISE(FPSCR_IDC, FPSCR_IDE, FPE_FLTISN); if (si_code) vfp_raise_sigfpe(si_code, regs); }
/* * Process bitmask of exception conditions. */ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs) { int si_code = 0; pr_debug("VFP: raising exceptions %08x\n", exceptions); if (exceptions == VFP_EXCEPTION_ERROR) { vfp_panic("unhandled bounce", inst); vfp_raise_sigfpe(0, regs); return; } /* * If any of the status flags are set, update the FPSCR. * Comparison instructions always return at least one of * these flags set. */ if (exceptions & (FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V)) fpscr &= ~(FPSCR_N|FPSCR_Z|FPSCR_C|FPSCR_V); fpscr |= exceptions; fmxr(FPSCR, fpscr); #define RAISE(stat,en,sig) \ if (exceptions & stat && fpscr & en) \ si_code = sig; /* * These are arranged in priority order, least to highest. */ RAISE(FPSCR_DZC, FPSCR_DZE, FPE_FLTDIV); RAISE(FPSCR_IXC, FPSCR_IXE, FPE_FLTRES); RAISE(FPSCR_UFC, FPSCR_UFE, FPE_FLTUND); RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF); RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV); RAISE(FPSCR_IDC, FPSCR_IDE, FPE_FLTISN); if (si_code) vfp_raise_sigfpe(si_code, regs); }