+#ifdef X86_64_SIGFPE_FIXUP
+#define MXCSR_IE (0x01) /* Invalid Operation */
+#define MXCSR_DE (0x02) /* Denormal */
+#define MXCSR_ZE (0x04) /* Devide-by-Zero */
+#define MXCSR_OE (0x08) /* Overflow */
+#define MXCSR_UE (0x10) /* Underflow */
+#define MXCSR_PE (0x20) /* Precision */
+
+static inline int
+mxcsr_to_code(unsigned int mxcsr)
+{
+ /* Extract unmasked exception bits. */
+ mxcsr &= ~(mxcsr >> 7) & 0x3F;
+
+ /* This order is defined at "Intel 64 and IA-32 Architectures
+ * Software Developerfs Manual" Volume 1: "Basic Architecture",
+ * 4.9.2 "Floating-Point Exception Priority". */
+ if (mxcsr & MXCSR_IE)
+ return FPE_FLTINV;
+ else if (mxcsr & MXCSR_ZE)
+ return FPE_FLTDIV;
+ else if (mxcsr & MXCSR_DE)
+ return FPE_FLTUND;
+ else if (mxcsr & MXCSR_OE)
+ return FPE_FLTOVF;
+ else if (mxcsr & MXCSR_UE)
+ return FPE_FLTUND;
+ else if (mxcsr & MXCSR_PE)
+ return FPE_FLTRES;
+
+ return 0;
+}
+
+static void
+sigfpe_handler(int signal, siginfo_t *siginfo, void *void_context)
+{
+ os_context_t *context = arch_os_get_context(&void_context);
+ unsigned int *mxcsr = arch_os_context_mxcsr_addr(context);
+
+ if (siginfo->si_code == 0) { /* XMM exception */
+ siginfo->si_code = mxcsr_to_code(*mxcsr);
+
+ /* Clear sticky exception flag. */
+ *mxcsr &= ~0x3F;
+ }
+
+ interrupt_handle_now(signal, siginfo, context);
+}
+#endif
+