or1k: Support for softfloat to emulate hw exceptions
authorStafford Horne <shorne@gmail.com>
Fri, 24 Jan 2020 12:30:31 +0000 (21:30 +0900)
committerStafford Horne <shorne@gmail.com>
Wed, 13 Jan 2021 23:45:01 +0000 (08:45 +0900)
This allows the openrisc softfloat implementation to set exceptions.
This also sets the correct tininess after rounding value to be
consistent with hardware and simulator implementations.

libgcc/ChangeLog:

* config/or1k/sfp-machine.h (FP_RND_NEAREST, FP_RND_ZERO,
FP_RND_PINF, FP_RND_MINF, FP_RND_MASK, FP_EX_OVERFLOW,
FP_EX_UNDERFLOW, FP_EX_INEXACT, FP_EX_INVALID, FP_EX_DIVZERO,
FP_EX_ALL): New constant macros.
(_FP_DECL_EX, FP_ROUNDMODE, FP_INIT_ROUNDMODE,
FP_HANDLE_EXCEPTIONS): New macros.
(_FP_TININESS_AFTER_ROUNDING): Change to 1.

libgcc/config/or1k/sfp-machine.h

index 5da9e84990d6dc495ad1858ad0a3bfd2124903c5..eebe5b0578edaceaedc48ecce5cdda76fe788855 100644 (file)
     R##_c = FP_CLS_NAN;                                                \
   } while (0)
 
+/* Handle getting and setting rounding mode for soft fp operations.  */
+
+#define FP_RND_NEAREST         (0x0 << 1)
+#define FP_RND_ZERO            (0x1 << 1)
+#define FP_RND_PINF            (0x2 << 1)
+#define FP_RND_MINF            (0x3 << 1)
+#define FP_RND_MASK            (0x3 << 1)
+
+#define FP_EX_OVERFLOW         1 << 3
+#define FP_EX_UNDERFLOW                1 << 4
+#define FP_EX_INEXACT          1 << 8
+#define FP_EX_INVALID          1 << 9
+#define FP_EX_DIVZERO          1 << 11
+#define FP_EX_ALL \
+       (FP_EX_INVALID | FP_EX_DIVZERO | FP_EX_OVERFLOW | FP_EX_UNDERFLOW \
+        | FP_EX_INEXACT)
+
+#define _FP_DECL_EX \
+  unsigned int _fpcsr __attribute__ ((unused)) = FP_RND_NEAREST
+
+#define FP_ROUNDMODE (_fpcsr & FP_RND_MASK)
+
+#ifdef __or1k_hard_float__
+#define FP_INIT_ROUNDMODE                                      \
+do {                                                           \
+  __asm__ volatile ("l.mfspr %0,r0,20" : "=r" (_fpcsr));       \
+} while (0)
+
+#define FP_HANDLE_EXCEPTIONS                                   \
+do {                                                           \
+  if (__builtin_expect (_fex, 0))                              \
+    {                                                          \
+      _fpcsr &= ~FP_EX_ALL;                                    \
+      _fpcsr |= _fex;                                          \
+      __asm__ volatile ("l.mtspr r0,%0,20" : : "r" (_fpcsr));  \
+    }                                                          \
+} while (0)
+#endif
+
 #define        __LITTLE_ENDIAN 1234
 #define        __BIG_ENDIAN    4321
 
 #define __BYTE_ORDER __BIG_ENDIAN
 
-#define _FP_TININESS_AFTER_ROUNDING 0
+#define _FP_TININESS_AFTER_ROUNDING 1
 
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)