Enable the raising of exception in long double soft float and support for rounding mode.

2012-09-06  Marcus Shawcroft  <marcus.shawcr...@arm.com>

        * config/aarch64/sfp-machine.h (FP_EX_INVALID, FP_EX_DIVZERO)
        (FP_EX_OVERFLOW, FP_EX_UNDERFLOW, FP_EX_INEXACT)
        (FP_HANDLE_EXCEPTIONS, FP_RND_NEAREST, FP_RND_ZERO, FP_RND_PINF)
        (FP_RND_MINF, _FP_DECL_EX, FP_INIT_FOUNDMODE, FP_ROUNDMODE):New.
diff --git a/libgcc/config/aarch64/sfp-machine.h b/libgcc/config/aarch64/sfp-machine.h
index a697348..3a09ae7 100644
--- a/libgcc/config/aarch64/sfp-machine.h
+++ b/libgcc/config/aarch64/sfp-machine.h
@@ -64,6 +64,79 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
     R##_c = FP_CLS_NAN;						\
   } while (0)
 
+#define FP_EX_INVALID	0x01
+#define FP_EX_DIVZERO	0x02
+#define FP_EX_OVERFLOW	0x04
+#define FP_EX_UNDERFLOW	0x08
+#define FP_EX_INEXACT	0x10
+
+#define FP_HANDLE_EXCEPTIONS						\
+  do {									\
+    const float fp_max = __FLT_MAX__;					\
+    const float fp_min = __FLT_MIN__;					\
+    const float fp_1e32 = 1.0e32f;					\
+    const float fp_zero = 0.0;						\
+    const float fp_one = 1.0;						\
+    unsigned fpsr;							\
+    if (_fex & FP_EX_INVALID)						\
+      {									\
+        __asm__ __volatile__ ("fdiv\ts0, %s0, %s0"			\
+			      :						\
+			      : "w" (fp_zero)				\
+			      : "s0");					\
+	__asm__ __volatile__ ("mrs\t%0, fpsr" : "=r" (fpsr));		\
+      }									\
+    if (_fex & FP_EX_DIVZERO)						\
+      {									\
+	__asm__ __volatile__ ("fdiv\ts0, %s0, %s1"			\
+			      :						\
+			      : "w" (fp_one), "w" (fp_zero)		\
+			      : "s0");					\
+	__asm__ __volatile__ ("mrs\t%0, fpsr" : "=r" (fpsr));		\
+      }									\
+    if (_fex & FP_EX_OVERFLOW)						\
+      {									\
+        __asm__ __volatile__ ("fadd\ts0, %s0, %s1"			\
+			      :						\
+			      : "w" (fp_max), "w" (fp_1e32)		\
+			      : "s0");					\
+        __asm__ __volatile__ ("mrs\t%0, fpsr" : "=r" (fpsr));		\
+      }									\
+    if (_fex & FP_EX_UNDERFLOW)						\
+      {									\
+	__asm__ __volatile__ ("fmul\ts0, %s0, %s0"			\
+			      :						\
+			      : "w" (fp_min)				\
+			      : "s0");					\
+	__asm__ __volatile__ ("mrs\t%0, fpsr" : "=r" (fpsr));		\
+      }									\
+    if (_fex & FP_EX_INEXACT)						\
+      {									\
+	__asm__ __volatile__ ("fsub\ts0, %s0, %s1"			\
+			      :						\
+			      : "w" (fp_max), "w" (fp_one)		\
+			      : "s0");					\
+	__asm__ __volatile__ ("mrs\t%0, fpsr" : "=r" (fpsr));		\
+      }									\
+  } while (0)
+
+
+#define FP_RND_NEAREST		0
+#define FP_RND_ZERO		0xc00000
+#define FP_RND_PINF		0x400000
+#define FP_RND_MINF		0x800000
+
+#define _FP_DECL_EX \
+  unsigned long int _fpcr __attribute__ ((unused)) = FP_RND_NEAREST
+
+#define FP_INIT_ROUNDMODE			\
+  do {						\
+    __asm__ __volatile__ ("mrs	%0, fpcr"	\
+			  : "=r" (_fpcr));	\
+  } while (0)
+
+#define FP_ROUNDMODE (_fpcr & 0xc00000)
+
 #define	__LITTLE_ENDIAN	1234
 #define	__BIG_ENDIAN	4321
 

Reply via email to