diff mbox

[AArch64] support long double exceptions and rounding mode

Message ID 5048B48B.6040208@arm.com
State New
Headers show

Commit Message

Marcus Shawcroft Sept. 6, 2012, 2:34 p.m. UTC
Enable the raising of exception in long double soft float and support 
for rounding mode.

2012-09-06  Marcus Shawcroft  <marcus.shawcroft@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.

Comments

Marcus Shawcroft Sept. 10, 2012, 7:37 a.m. UTC | #1
On 06/09/12 15:34, Marcus Shawcroft wrote:
> Enable the raising of exception in long double soft float and support
> for rounding mode.
>
> 2012-09-06  Marcus Shawcroft<marcus.shawcroft@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.
>

I've just committed this patch to the aarch64 branch.
/Marcus
diff mbox

Patch

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