public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [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