@@ -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