aboutsummaryrefslogtreecommitdiffstats
path: root/module/spl
diff options
context:
space:
mode:
authorChunwei Chen <[email protected]>2017-08-03 10:41:42 -0700
committerBrian Behlendorf <[email protected]>2017-08-03 10:41:42 -0700
commit6ecfd2b55333dbaf8755bcab53ae9d37b6bca7c1 (patch)
treefae8fe09a988c9f91419e1d501f1c58b4ea068e0 /module/spl
parent98cdcb8286db2dadf369a22d33a53e49b11e3288 (diff)
Add __divmoddi4 and __udivmoddi4 for 32-bit arch
gcc-7 seems to use __udivmoddi4 for 64-bit division on 32-bit arch. This patch implement them so we don't get undefined reference error. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: loli10K <[email protected]> Signed-off-by: Chunwei Chen <[email protected]> Closes zfsonlinux/zfs#6417 Closes #636
Diffstat (limited to 'module/spl')
-rw-r--r--module/spl/spl-generic.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/module/spl/spl-generic.c b/module/spl/spl-generic.c
index 10061620e..f6782dae7 100644
--- a/module/spl/spl-generic.c
+++ b/module/spl/spl-generic.c
@@ -277,6 +277,49 @@ __umoddi3(uint64_t dividend, uint64_t divisor)
}
EXPORT_SYMBOL(__umoddi3);
+/*
+ * Implementation of 64-bit unsigned division/modulo for 32-bit machines.
+ */
+uint64_t
+__udivmoddi4(uint64_t n, uint64_t d, uint64_t *r)
+{
+ uint64_t q = __udivdi3(n, d);
+ if (r)
+ *r = n - d * q;
+ return (q);
+}
+EXPORT_SYMBOL(__udivmoddi4);
+
+/*
+ * Implementation of 64-bit signed division/modulo for 32-bit machines.
+ */
+int64_t
+__divmoddi4(int64_t n, int64_t d, int64_t *r)
+{
+ int64_t q, rr;
+ boolean_t nn = B_FALSE;
+ boolean_t nd = B_FALSE;
+ if (n < 0) {
+ nn = B_TRUE;
+ n = -n;
+ }
+ if (d < 0) {
+ nd = B_TRUE;
+ d = -d;
+ }
+
+ q = __udivmoddi4(n, d, (uint64_t *)&rr);
+
+ if (nn != nd)
+ q = -q;
+ if (nn)
+ rr = -rr;
+ if (r)
+ *r = rr;
+ return (q);
+}
+EXPORT_SYMBOL(__divmoddi4);
+
#if defined(__arm) || defined(__arm__)
/*
* Implementation of 64-bit (un)signed division for 32-bit arm machines.