* [U-Boot] [PATCH] lib: div64: syncronize to current kernel version
@ 2015-01-29 16:25 Nishanth Menon
2015-03-06 15:43 ` [U-Boot] " Tom Rini
0 siblings, 1 reply; 3+ messages in thread
From: Nishanth Menon @ 2015-01-29 16:25 UTC (permalink / raw)
To: u-boot
Synchronize with the implementation from v3.18 tag. This allows us to
use a standardized 64 bit ops on architectures that do not natively
support 64 bit (example: 32bit ARM)
Signed-off-by: Nishanth Menon <nm@ti.com>
---
include/linux/math64.h | 81 ++++++++++++++++++++++++++++++
lib/div64.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 209 insertions(+), 4 deletions(-)
diff --git a/include/linux/math64.h b/include/linux/math64.h
index 6d760d7..a10ccbb 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -2,9 +2,13 @@
#define _LINUX_MATH64_H
#include <linux/types.h>
+#include <div64.h>
#if BITS_PER_LONG == 64
+#define div64_long(x, y) div64_s64((x), (y))
+#define div64_ul(x, y) div64_u64((x), (y))
+
/**
* div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
*
@@ -27,6 +31,15 @@ static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
}
/**
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ */
+static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+ *remainder = dividend % divisor;
+ return dividend / divisor;
+}
+
+/**
* div64_u64 - unsigned 64bit divide with 64bit divisor
*/
static inline u64 div64_u64(u64 dividend, u64 divisor)
@@ -34,8 +47,19 @@ static inline u64 div64_u64(u64 dividend, u64 divisor)
return dividend / divisor;
}
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ */
+static inline s64 div64_s64(s64 dividend, s64 divisor)
+{
+ return dividend / divisor;
+}
+
#elif BITS_PER_LONG == 32
+#define div64_long(x, y) div_s64((x), (y))
+#define div64_ul(x, y) div_u64((x), (y))
+
#ifndef div_u64_rem
static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
{
@@ -48,10 +72,18 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
#endif
+#ifndef div64_u64_rem
+extern u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder);
+#endif
+
#ifndef div64_u64
extern u64 div64_u64(u64 dividend, u64 divisor);
#endif
+#ifndef div64_s64
+extern s64 div64_s64(s64 dividend, s64 divisor);
+#endif
+
#endif /* BITS_PER_LONG */
/**
@@ -82,4 +114,53 @@ static inline s64 div_s64(s64 dividend, s32 divisor)
u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder);
+static __always_inline u32
+__iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+{
+ u32 ret = 0;
+
+ while (dividend >= divisor) {
+ /* The following asm() prevents the compiler from
+ optimising this loop into a modulo operation. */
+ asm("" : "+rm"(dividend));
+
+ dividend -= divisor;
+ ret++;
+ }
+
+ *remainder = dividend;
+
+ return ret;
+}
+
+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+ return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u32_shr */
+
+#else
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+ u32 ah, al;
+ u64 ret;
+
+ al = a;
+ ah = a >> 32;
+
+ ret = ((u64)al * mul) >> shift;
+ if (ah)
+ ret += ((u64)ah * mul) << (32 - shift);
+
+ return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#endif
+
#endif /* _LINUX_MATH64_H */
diff --git a/lib/div64.c b/lib/div64.c
index 795ef0e..9b53faf 100644
--- a/lib/div64.c
+++ b/lib/div64.c
@@ -9,17 +9,21 @@
* Generic C version of 64bit/32bit division and modulo, with
* 64bit result and 32bit remainder.
*
- * The fast case for (n>>32 == 0) is handled inline by do_div().
+ * The fast case for (n>>32 == 0) is handled inline by do_div().
*
* Code generated for this function might be very inefficient
* for some CPUs. __div64_32() can be overridden by linking arch-specific
- * assembly versions such as arch/powerpc/lib/div64.S and arch/sh/lib/div64.S.
+ * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
*/
+#include <common.h>
#include <div64.h>
-#include <linux/types.h>
+#include <linux/math64.h>
-uint32_t __div64_32(uint64_t *n, uint32_t base)
+/* Not needed on 64bit architectures */
+#if BITS_PER_LONG == 32
+
+uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
{
uint64_t rem = *n;
uint64_t b = base;
@@ -51,3 +55,123 @@ uint32_t __div64_32(uint64_t *n, uint32_t base)
*n = res;
return rem;
}
+
+
+#ifndef div_s64_rem
+s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
+{
+ u64 quotient;
+
+ if (dividend < 0) {
+ quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
+ *remainder = -*remainder;
+ if (divisor > 0)
+ quotient = -quotient;
+ } else {
+ quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
+ if (divisor < 0)
+ quotient = -quotient;
+ }
+ return quotient;
+}
+#endif
+
+/**
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ * @dividend: 64bit dividend
+ * @divisor: 64bit divisor
+ * @remainder: 64bit remainder
+ *
+ * This implementation is a comparable to algorithm used by div64_u64.
+ * But this operation, which includes math for calculating the remainder,
+ * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
+ * systems.
+ */
+#ifndef div64_u64_rem
+u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+ u32 high = divisor >> 32;
+ u64 quot;
+
+ if (high == 0) {
+ u32 rem32;
+ quot = div_u64_rem(dividend, divisor, &rem32);
+ *remainder = rem32;
+ } else {
+ int n = 1 + fls(high);
+ quot = div_u64(dividend >> n, divisor >> n);
+
+ if (quot != 0)
+ quot--;
+
+ *remainder = dividend - quot * divisor;
+ if (*remainder >= divisor) {
+ quot++;
+ *remainder -= divisor;
+ }
+ }
+
+ return quot;
+}
+#endif
+
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend: 64bit dividend
+ * @divisor: 64bit divisor
+ *
+ * This implementation is a modified version of the algorithm proposed
+ * by the book 'Hacker's Delight'. The original source and full proof
+ * can be found here and is available for use without restriction.
+ *
+ * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c.txt'
+ */
+#ifndef div64_u64
+u64 div64_u64(u64 dividend, u64 divisor)
+{
+ u32 high = divisor >> 32;
+ u64 quot;
+
+ if (high == 0) {
+ quot = div_u64(dividend, divisor);
+ } else {
+ int n = 1 + fls(high);
+ quot = div_u64(dividend >> n, divisor >> n);
+
+ if (quot != 0)
+ quot--;
+ if ((dividend - quot * divisor) >= divisor)
+ quot++;
+ }
+
+ return quot;
+}
+#endif
+
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend: 64bit dividend
+ * @divisor: 64bit divisor
+ */
+#ifndef div64_s64
+s64 div64_s64(s64 dividend, s64 divisor)
+{
+ s64 quot, t;
+
+ quot = div64_u64(abs64(dividend), abs64(divisor));
+ t = (dividend ^ divisor) >> 63;
+
+ return (quot ^ t) - t;
+}
+#endif
+
+#endif /* BITS_PER_LONG == 32 */
+
+/*
+ * Iterative div/mod for use when dividend is not expected to be much
+ * bigger than divisor.
+ */
+u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+{
+ return __iter_div_u64_rem(dividend, divisor, remainder);
+}
--
1.9.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [U-Boot] lib: div64: syncronize to current kernel version
2015-01-29 16:25 [U-Boot] [PATCH] lib: div64: syncronize to current kernel version Nishanth Menon
@ 2015-03-06 15:43 ` Tom Rini
2015-03-06 16:49 ` Nishanth Menon
0 siblings, 1 reply; 3+ messages in thread
From: Tom Rini @ 2015-03-06 15:43 UTC (permalink / raw)
To: u-boot
On Thu, Jan 29, 2015 at 10:25:20AM -0600, Nishanth Menon wrote:
> Synchronize with the implementation from v3.18 tag. This allows us to
> use a standardized 64 bit ops on architectures that do not natively
> support 64 bit (example: 32bit ARM)
>
> Signed-off-by: Nishanth Menon <nm@ti.com>
This breaks building on 64bit platforms (mips64, aarch64). Thanks!
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20150306/0912f8fc/attachment.sig>
^ permalink raw reply [flat|nested] 3+ messages in thread
* [U-Boot] lib: div64: syncronize to current kernel version
2015-03-06 15:43 ` [U-Boot] " Tom Rini
@ 2015-03-06 16:49 ` Nishanth Menon
0 siblings, 0 replies; 3+ messages in thread
From: Nishanth Menon @ 2015-03-06 16:49 UTC (permalink / raw)
To: u-boot
On 03/06/2015 09:43 AM, Tom Rini wrote:
> On Thu, Jan 29, 2015 at 10:25:20AM -0600, Nishanth Menon wrote:
>
>> Synchronize with the implementation from v3.18 tag. This allows us to
>> use a standardized 64 bit ops on architectures that do not natively
>> support 64 bit (example: 32bit ARM)
>>
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>
> This breaks building on 64bit platforms (mips64, aarch64). Thanks!
>
Uggh.. dropping this. Sorry for the noise.
--
Regards,
Nishanth Menon
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-03-06 16:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-29 16:25 [U-Boot] [PATCH] lib: div64: syncronize to current kernel version Nishanth Menon
2015-03-06 15:43 ` [U-Boot] " Tom Rini
2015-03-06 16:49 ` Nishanth Menon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox