summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclyon <clyon@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-27 12:17:05 +0000
committerclyon <clyon@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-27 12:17:05 +0000
commitb214253d2f5e10aef0ffd0204f07770496ac0984 (patch)
tree2bce9a61019a73e1ac15aec945ce47ae5c2c3b72
parentcb06ace2241e2aa8a65ccbac3cb54c1e6a263cc7 (diff)
downloadppe42-gcc-b214253d2f5e10aef0ffd0204f07770496ac0984.tar.gz
ppe42-gcc-b214253d2f5e10aef0ffd0204f07770496ac0984.zip
2013-11-27 Kugan Vivekanandarajah <kuganv@linaro.org>
gcc/ * doc/tm.texi.in (TARGET_HAS_NO_HW_DIVIDE): Define. * doc/tm.texi (TARGET_HAS_NO_HW_DIVIDE): Regenerate. libgcc/ * libgcc2.c (__udivmoddi4): Define new implementation when TARGET_HAS_NO_HW_DIVIDE is defined, for processors without any divide instructions. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@205444 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/doc/tm.texi8
-rw-r--r--gcc/doc/tm.texi.in8
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/libgcc2.c69
5 files changed, 96 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 31e9670fa89..15ce5e698f2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2013-11-27 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * doc/tm.texi.in (TARGET_HAS_NO_HW_DIVIDE): Define.
+ * doc/tm.texi (TARGET_HAS_NO_HW_DIVIDE): Regenerate.
+
2013-11-27 Marek Polacek <polacek@redhat.com>
PR sanitizer/59306
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 966576fe721..68b59b9975b 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5365,6 +5365,14 @@ If this macro evaluates to @code{false} the comparison functions return
in @file{libgcc.a}, you do not need to define this macro.
@end defmac
+@defmac TARGET_HAS_NO_HW_DIVIDE
+This macro should be defined if the target has no hardware divide
+instructions. If this macro is defined, GCC will use an algorithm which
+make use of simple logical and arithmetic operations for 64-bit
+division. If the macro is not defined, GCC will use an algorithm which
+make use of a 64-bit by 32-bit divide primitive.
+@end defmac
+
@cindex @code{EDOM}, implicit usage
@findex matherr
@defmac TARGET_EDOM
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 63f4edb3a43..1bb3806c5df 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -4205,6 +4205,14 @@ If this macro evaluates to @code{false} the comparison functions return
in @file{libgcc.a}, you do not need to define this macro.
@end defmac
+@defmac TARGET_HAS_NO_HW_DIVIDE
+This macro should be defined if the target has no hardware divide
+instructions. If this macro is defined, GCC will use an algorithm which
+make use of simple logical and arithmetic operations for 64-bit
+division. If the macro is not defined, GCC will use an algorithm which
+make use of a 64-bit by 32-bit divide primitive.
+@end defmac
+
@cindex @code{EDOM}, implicit usage
@findex matherr
@defmac TARGET_EDOM
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index a1f84555826..7e7aa4a40d1 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,9 @@
+2013-11-27 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * libgcc2.c (__udivmoddi4): Define new implementation when
+ TARGET_HAS_NO_HW_DIVIDE is defined, for processors without any
+ divide instructions.
+
2013-11-25 Oleg Endo <olegendo@gcc.gnu.org>
* config/sh/crt1.S (start): Don't do VBR_SETUP for SH2E.
diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c
index bec411be0b5..8c4cc6a316c 100644
--- a/libgcc/libgcc2.c
+++ b/libgcc/libgcc2.c
@@ -934,6 +934,74 @@ __parityDI2 (UDWtype x)
#endif
#ifdef L_udivmoddi4
+#ifdef TARGET_HAS_NO_HW_DIVIDE
+
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
+UDWtype
+__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
+{
+ UDWtype q = 0, r = n, y = d;
+ UWtype lz1, lz2, i, k;
+
+ /* Implements align divisor shift dividend method. This algorithm
+ aligns the divisor under the dividend and then perform number of
+ test-subtract iterations which shift the dividend left. Number of
+ iterations is k + 1 where k is the number of bit positions the
+ divisor must be shifted left to align it under the dividend.
+ quotient bits can be saved in the rightmost positions of the dividend
+ as it shifts left on each test-subtract iteration. */
+
+ if (y <= r)
+ {
+ lz1 = __builtin_clzll (d);
+ lz2 = __builtin_clzll (n);
+
+ k = lz1 - lz2;
+ y = (y << k);
+
+ /* Dividend can exceed 2 ^ (width − 1) − 1 but still be less than the
+ aligned divisor. Normal iteration can drops the high order bit
+ of the dividend. Therefore, first test-subtract iteration is a
+ special case, saving its quotient bit in a separate location and
+ not shifting the dividend. */
+ if (r >= y)
+ {
+ r = r - y;
+ q = (1ULL << k);
+ }
+
+ if (k > 0)
+ {
+ y = y >> 1;
+
+ /* k additional iterations where k regular test subtract shift
+ dividend iterations are done. */
+ i = k;
+ do
+ {
+ if (r >= y)
+ r = ((r - y) << 1) + 1;
+ else
+ r = (r << 1);
+ i = i - 1;
+ } while (i != 0);
+
+ /* First quotient bit is combined with the quotient bits resulting
+ from the k regular iterations. */
+ q = q + r;
+ r = r >> k;
+ q = q - (r << k);
+ }
+ }
+
+ if (rp)
+ *rp = r;
+ return q;
+}
+#else
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
@@ -1152,6 +1220,7 @@ __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
return ww.ll;
}
#endif
+#endif
#ifdef L_divdi3
DWtype
OpenPOWER on IntegriCloud