summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/math-emu/sfp-machine.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/math-emu/sfp-machine.h')
-rw-r--r--arch/sparc64/math-emu/sfp-machine.h130
1 files changed, 75 insertions, 55 deletions
diff --git a/arch/sparc64/math-emu/sfp-machine.h b/arch/sparc64/math-emu/sfp-machine.h
index f15a5ea4a..3846ac4f9 100644
--- a/arch/sparc64/math-emu/sfp-machine.h
+++ b/arch/sparc64/math-emu/sfp-machine.h
@@ -52,16 +52,6 @@
X##_s = _flo->bits.sign; \
} while (0)
-#define __FP_PACK_RAW_1(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac = X##_f; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
#define __FP_UNPACK_RAW_2(fs, X, val) \
do { \
union _FP_UNION_##fs *_flo = \
@@ -73,53 +63,80 @@
X##_s = _flo->bits.sign; \
} while (0)
-#define __FP_PACK_RAW_2(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)val; \
- \
- _flo->bits.frac0 = X##_f0; \
- _flo->bits.frac1 = X##_f1; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
-
#define __FP_UNPACK_S(X,val) \
do { \
__FP_UNPACK_RAW_1(S,X,val); \
_FP_UNPACK_CANONICAL(S,1,X); \
} while (0)
-#define __FP_PACK_S(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- __FP_PACK_RAW_1(S,val,X); \
- } while (0)
-
#define __FP_UNPACK_D(X,val) \
do { \
__FP_UNPACK_RAW_1(D,X,val); \
_FP_UNPACK_CANONICAL(D,1,X); \
} while (0)
-#define __FP_PACK_D(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,1,X); \
- __FP_PACK_RAW_1(D,val,X); \
- } while (0)
-
#define __FP_UNPACK_Q(X,val) \
do { \
__FP_UNPACK_RAW_2(Q,X,val); \
_FP_UNPACK_CANONICAL(Q,2,X); \
} while (0)
-#define __FP_PACK_Q(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,2,X); \
- __FP_PACK_RAW_2(Q,val,X); \
+#define __FP_PACK_RAW_1(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac = X##_f; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+#define __FP_PACK_RAW_2(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)val; \
+ \
+ _flo->bits.frac0 = X##_f0; \
+ _flo->bits.frac1 = X##_f1; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
} while (0)
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */
+#define __FPU_TEM \
+ (((current->tss.xfsr[0])>>23)&0x1f)
+#define __FPU_TRAP_P(bits) \
+ ((__FPU_TEM & (bits)) != 0)
+
+#define __FP_PACK_S(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(S,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(S,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_D(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(D,1,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_1(D,val,X); \
+ __exc; \
+})
+
+#define __FP_PACK_Q(val,X) \
+({ int __exc = _FP_PACK_CANONICAL(Q,2,X); \
+ if(!__exc || !__FPU_TRAP_P(__exc)) \
+ __FP_PACK_RAW_2(Q,val,X); \
+ __exc; \
+})
+
+/* Obtain the current rounding mode. */
+#define FP_ROUNDMODE ((current->tss.xfsr[0] >> 30) & 0x3)
+
#include <linux/types.h>
#include <asm/byteorder.h>
@@ -153,28 +170,24 @@
#define umul_ppmm(wh, wl, u, v) \
do { \
- long tmp1 = 0, tmp2 = 0, tmp3 = 0; \
__asm__ ("mulx %2,%3,%1
- srlx %2,32,%4
- srl %3,0,%5
- mulx %4,%5,%6
- srlx %3,32,%4
- srl %2,0,%5
- mulx %4,%5,%5
- srlx %2,32,%4
- add %5,%6,%6
- srlx %3,32,%5
- mulx %4,%5,%4
- srlx %6,32,%5
- add %4,%5,%0" \
+ srlx %2,32,%%g1
+ srl %3,0,%%g2
+ mulx %%g1,%%g2,%%g3
+ srlx %3,32,%%g1
+ srl %2,0,%%g2
+ mulx %%g1,%%g2,%%g2
+ srlx %2,32,%%g1
+ add %%g2,%%g3,%%g3
+ srlx %3,32,%%g2
+ mulx %%g1,%%g2,%%g1
+ srlx %%g3,32,%%g2
+ add %%g1,%%g2,%0" \
: "=r" ((UDItype)(wh)), \
"=&r" ((UDItype)(wl)) \
: "r" ((UDItype)(u)), \
- "r" ((UDItype)(v)), \
- "r" ((UDItype)(tmp1)), \
- "r" ((UDItype)(tmp2)), \
- "r" ((UDItype)(tmp3)) \
- : "cc"); \
+ "r" ((UDItype)(v)) \
+ : "g1", "g2", "g3", "cc"); \
} while (0)
#define udiv_qrnnd(q, r, n1, n0, d) \
@@ -223,3 +236,10 @@
#else
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif
+
+/* Exception flags. */
+#define EFLAG_INVALID (1 << 4)
+#define EFLAG_OVERFLOW (1 << 3)
+#define EFLAG_UNDERFLOW (1 << 2)
+#define EFLAG_DIVZERO (1 << 1)
+#define EFLAG_INEXACT (1 << 0)