summaryrefslogtreecommitdiff
path: root/longlong.h
diff options
context:
space:
mode:
authorTorbjorn Granlund <tege@gmplib.org>2011-10-12 22:29:25 +0200
committerTorbjorn Granlund <tege@gmplib.org>2011-10-12 22:29:25 +0200
commitda3af159dc5d88af9fe1f923833b2b8f17ae9533 (patch)
treeef249a094c6bddb9a0829d13d4ec036c206ee4ed /longlong.h
parente79c122e08e5ad64ded98d51927f9f947319f53a (diff)
downloadgmp-da3af159dc5d88af9fe1f923833b2b8f17ae9533.tar.gz
(s390): Improve umul_ppmm and udiv_qrnnd support.
Diffstat (limited to 'longlong.h')
-rw-r--r--longlong.h57
1 files changed, 51 insertions, 6 deletions
diff --git a/longlong.h b/longlong.h
index 939fe1205..6870d6454 100644
--- a/longlong.h
+++ b/longlong.h
@@ -657,26 +657,39 @@ extern UWtype __MPN(udiv_qrnnd) _PROTO ((UWtype *, UWtype, UWtype, UWtype));
#if defined (__zarch__)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
do { \
- if (__builtin_constant_p (bl)) \
+/* if (__builtin_constant_p (bl)) \
__asm__ ("alfi\t%1,%o5\n\talcr\t%0,%3" \
: "=r" (sh), "=&r" (sl) \
: "0" (ah), "r" (bh), "%1" (al), "n" (bl) __CLOBBER_CC);\
else \
- __asm__ ("alr\t%1,%5\n\talcr\t%0,%3" \
+*/ __asm__ ("alr\t%1,%5\n\talcr\t%0,%3" \
: "=r" (sh), "=&r" (sl) \
: "0" (ah), "r" (bh), "%1" (al), "r" (bl)__CLOBBER_CC); \
} while (0)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
do { \
- if (__builtin_constant_p (bl)) \
+/* if (__builtin_constant_p (bl)) \
__asm__ ("slfi\t%1,%o5\n\tslbr\t%0,%3" \
: "=r" (sh), "=&r" (sl) \
: "0" (ah), "r" (bh), "1" (al), "n" (bl) __CLOBBER_CC); \
else \
- __asm__ ("slr\t%1,%5\n\tslbr\t%0,%3" \
+*/ __asm__ ("slr\t%1,%5\n\tslbr\t%0,%3" \
: "=r" (sh), "=&r" (sl) \
: "0" (ah), "r" (bh), "1" (al), "r" (bl) __CLOBBER_CC); \
} while (0)
+#if __GMP_GNUC_PREREQ (4,5)
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __x; \
+ __x.__ll = (UDItype) m0 * (UDItype) m1; \
+ (xh) = __x.__i.__h; (xl) = __x.__i.__l; \
+ } while (0)
+#else
+#if 0
+/* FIXME: this fails if gcc knows about the 64-bit registers. Use only
+ with a new enough processor pretending we have 32-bit registers. */
#define umul_ppmm(xh, xl, m0, m1) \
do { \
union {UDItype __ll; \
@@ -687,6 +700,25 @@ extern UWtype __MPN(udiv_qrnnd) _PROTO ((UWtype *, UWtype, UWtype, UWtype));
: "%0" (m0), "r" (m1)); \
(xh) = __x.__i.__h; (xl) = __x.__i.__l; \
} while (0)
+#else
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ /* When we have 64-bit regs and gcc is aware of that, we cannot simply use
+ DImode for the product, since that would be allocated to a single 64-bit
+ register, whereas mlr uses the low 32-bits of an even-odd register pair.
+ */ \
+ register USItype __r0 __asm__ ("0"); \
+ register USItype __r1 __asm__ ("1") = (m0); \
+ __asm__ ("mlr\t%0,%3" \
+ : "=r" (__r0), "=r" (__r1) \
+ : "r" (__r1), "r" (m1)); \
+ (xh) = __r0; (xl) = __r1; \
+ } while (0)
+#endif /* if 0 */
+#endif
+#if 0
+/* FIXME: this fails if gcc knows about the 64-bit registers. Use only
+ with a new enough processor pretending we have 32-bit registers. */
#define udiv_qrnnd(q, r, n1, n0, d) \
do { \
union {UDItype __ll; \
@@ -699,7 +731,18 @@ extern UWtype __MPN(udiv_qrnnd) _PROTO ((UWtype *, UWtype, UWtype, UWtype));
(q) = __x.__i.__l; (r) = __x.__i.__h; \
} while (0)
#else
-#define smul_ppmm(xh, xl, m0, m1) \
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ register USItype __r0 __asm__ ("0") = (n1); \
+ register USItype __r1 __asm__ ("1") = (n0); \
+ __asm__ ("dlr\t%0,%4" \
+ : "=r" (__r0), "=r" (__r1) \
+ : "r" (__r0), "r" (__r1), "r" (d)); \
+ (q) = __r1; (r) = __r0; \
+ } while (0)
+#endif /* if 0 */
+/* FIXME: this fails if gcc knows about the 64-bit registers. */
+#define smul_ppmm(xh, xl, m0, m1) \
do { \
union {DItype __ll; \
struct {USItype __h, __l;} __i; \
@@ -709,7 +752,8 @@ extern UWtype __MPN(udiv_qrnnd) _PROTO ((UWtype *, UWtype, UWtype, UWtype));
: "%0" (m0), "r" (m1)); \
(xh) = __x.__i.__h; (xl) = __x.__i.__l; \
} while (0)
-#define sdiv_qrnnd(q, r, n1, n0, d) \
+/* FIXME: this fails if gcc knows about the 64-bit registers. */
+#define sdiv_qrnnd(q, r, n1, n0, d) \
do { \
union {DItype __ll; \
struct {USItype __h, __l;} __i; \
@@ -1757,6 +1801,7 @@ extern UWtype __MPN(udiv_qrnnd) _PROTO ((UWtype *, UWtype, UWtype, UWtype));
#endif /* NO_ASM */
+/* FIXME: "sidi" here is highly doubtful, should sometimes be "diti". */
#if !defined (umul_ppmm) && defined (__umulsidi3)
#define umul_ppmm(ph, pl, m0, m1) \
{ \