All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] lib: div64: sync with Linux
@ 2017-03-28  9:05 Peng Fan
  2017-04-05 13:32 ` Tom Rini
  2017-04-07 15:51 ` [U-Boot] " Tom Rini
  0 siblings, 2 replies; 5+ messages in thread
From: Peng Fan @ 2017-03-28  9:05 UTC (permalink / raw)
  To: u-boot

Sync with Linux commit ad0376eb1483b ("Merge tag 'edac_for_4.11_2'").

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Cc: Tom Rini <trini@konsulko.com>
---
 include/linux/math64.h | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/div64.c            | 141 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 308 insertions(+), 5 deletions(-)

diff --git a/include/linux/math64.h b/include/linux/math64.h
index 6d760d7..08584c8 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -1,10 +1,15 @@
 #ifndef _LINUX_MATH64_H
 #define _LINUX_MATH64_H
 
+#include <div64.h>
+#include <linux/bitops.h>
 #include <linux/types.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 +32,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 +48,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 +73,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 +115,143 @@ 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;
+}
+
+#ifndef mul_u32_u32
+/*
+ * Many a GCC version messes this up and generates a 64x64 mult :-(
+ */
+static inline u64 mul_u32_u32(u32 a, u32 b)
+{
+	return (u64)a * b;
+}
+#endif
+
+#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 */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
+{
+	return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u64_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 = mul_u32_u32(al, mul) >> shift;
+	if (ah)
+		ret += mul_u32_u32(ah, mul) << (32 - shift);
+
+	return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
+{
+	union {
+		u64 ll;
+		struct {
+#ifdef __BIG_ENDIAN
+			u32 high, low;
+#else
+			u32 low, high;
+#endif
+		} l;
+	} rl, rm, rn, rh, a0, b0;
+	u64 c;
+
+	a0.ll = a;
+	b0.ll = b;
+
+	rl.ll = mul_u32_u32(a0.l.low, b0.l.low);
+	rm.ll = mul_u32_u32(a0.l.low, b0.l.high);
+	rn.ll = mul_u32_u32(a0.l.high, b0.l.low);
+	rh.ll = mul_u32_u32(a0.l.high, b0.l.high);
+
+	/*
+	 * Each of these lines computes a 64-bit intermediate result into "c",
+	 * starting@bits 32-95.  The low 32-bits go into the result of the
+	 * multiplication, the high 32-bits are carried into the next step.
+	 */
+	rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low;
+	rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low;
+	rh.l.high = (c >> 32) + rh.l.high;
+
+	/*
+	 * The 128-bit result of the multiplication is in rl.ll and rh.ll,
+	 * shift it right and throw away the high part of the result.
+	 */
+	if (shift == 0)
+		return rl.ll;
+	if (shift < 64)
+		return (rl.ll >> shift) | (rh.ll << (64 - shift));
+	return rh.ll >> (shift & 63);
+}
+#endif /* mul_u64_u64_shr */
+
+#endif
+
+#ifndef mul_u64_u32_div
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+	union {
+		u64 ll;
+		struct {
+#ifdef __BIG_ENDIAN
+			u32 high, low;
+#else
+			u32 low, high;
+#endif
+		} l;
+	} u, rl, rh;
+
+	u.ll = a;
+	rl.ll = mul_u32_u32(u.l.low, mul);
+	rh.ll = mul_u32_u32(u.l.high, mul) + rl.l.high;
+
+	/* Bits 32-63 of the result will be in rh.l.low. */
+	rl.l.high = do_div(rh.ll, divisor);
+
+	/* Bits 0-31 of the result will be in rl.l.low.	*/
+	do_div(rl.ll, divisor);
+
+	rl.l.high = rh.l.low;
+	return rl.ll;
+}
+#endif /* mul_u64_u32_div */
+
 #endif /* _LINUX_MATH64_H */
diff --git a/lib/div64.c b/lib/div64.c
index 319fca5..206f582 100644
--- a/lib/div64.c
+++ b/lib/div64.c
@@ -13,14 +13,19 @@
  *
  * 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
+ * or by defining a preprocessor macro in arch/include/asm/div64.h.
  */
 
-#include <div64.h>
-#include <linux/types.h>
-#include <linux/compiler.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
 
-uint32_t notrace __div64_32(uint64_t *n, uint32_t base)
+/* Not needed on 64bit architectures */
+#if BITS_PER_LONG == 32
+
+#ifndef __div64_32
+uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
 {
 	uint64_t rem = *n;
 	uint64_t b = base;
@@ -52,3 +57,129 @@ uint32_t notrace __div64_32(uint64_t *n, uint32_t base)
 	*n = res;
 	return rem;
 }
+EXPORT_SYMBOL(__div64_32);
+#endif
+
+#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;
+}
+EXPORT_SYMBOL(div_s64_rem);
+#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;
+}
+EXPORT_SYMBOL(div64_u64_rem);
+#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/hdcodetxt/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;
+}
+EXPORT_SYMBOL(div64_u64);
+#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(abs(dividend), abs(divisor));
+	t = (dividend ^ divisor) >> 63;
+
+	return (quot ^ t) - t;
+}
+EXPORT_SYMBOL(div64_s64);
+#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);
+}
+EXPORT_SYMBOL(iter_div_u64_rem);
-- 
2.6.6

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH] lib: div64: sync with Linux
  2017-03-28  9:05 [U-Boot] [PATCH] lib: div64: sync with Linux Peng Fan
@ 2017-04-05 13:32 ` Tom Rini
  2017-04-06  6:04   ` Peng Fan
  2017-04-07 15:51 ` [U-Boot] " Tom Rini
  1 sibling, 1 reply; 5+ messages in thread
From: Tom Rini @ 2017-04-05 13:32 UTC (permalink / raw)
  To: u-boot

On Tue, Mar 28, 2017 at 05:05:09PM +0800, Peng Fan wrote:

> Sync with Linux commit ad0376eb1483b ("Merge tag 'edac_for_4.11_2'").
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> Cc: Tom Rini <trini@konsulko.com>
> ---
>  include/linux/math64.h | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/div64.c            | 141 ++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 308 insertions(+), 5 deletions(-)

This seems fine.  What would help would be a link to a travis-ci job
with this particular patch applied showing everything still builds too
:)  Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170405/60a266eb/attachment.sig>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH] lib: div64: sync with Linux
  2017-04-05 13:32 ` Tom Rini
@ 2017-04-06  6:04   ` Peng Fan
  2017-04-06 12:45     ` Tom Rini
  0 siblings, 1 reply; 5+ messages in thread
From: Peng Fan @ 2017-04-06  6:04 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Wed, Apr 05, 2017 at 09:32:51AM -0400, Tom Rini wrote:
>On Tue, Mar 28, 2017 at 05:05:09PM +0800, Peng Fan wrote:
>
>> Sync with Linux commit ad0376eb1483b ("Merge tag 'edac_for_4.11_2'").
>> 
>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>> Cc: Tom Rini <trini@konsulko.com>
>> ---
>>  include/linux/math64.h | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  lib/div64.c            | 141 ++++++++++++++++++++++++++++++++++++++--
>>  2 files changed, 308 insertions(+), 5 deletions(-)
>
>This seems fine.  What would help would be a link to a travis-ci job
>with this particular patch applied showing everything still builds too
>:)  Thanks!

Do you mean I need to put a travis-ci job link in the commit log?
I just use buildman to do the build on my local PC, I do not have
travis-ci building.

Thanks,
Peng.

>
>-- 
>Tom



>_______________________________________________
>U-Boot mailing list
>U-Boot at lists.denx.de
>https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] [PATCH] lib: div64: sync with Linux
  2017-04-06  6:04   ` Peng Fan
@ 2017-04-06 12:45     ` Tom Rini
  0 siblings, 0 replies; 5+ messages in thread
From: Tom Rini @ 2017-04-06 12:45 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 06, 2017 at 02:04:44PM +0800, Peng Fan wrote:
> Hi Tom,
> 
> On Wed, Apr 05, 2017 at 09:32:51AM -0400, Tom Rini wrote:
> >On Tue, Mar 28, 2017 at 05:05:09PM +0800, Peng Fan wrote:
> >
> >> Sync with Linux commit ad0376eb1483b ("Merge tag 'edac_for_4.11_2'").
> >> 
> >> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> >> Cc: Tom Rini <trini@konsulko.com>
> >> ---
> >>  include/linux/math64.h | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
> >>  lib/div64.c            | 141 ++++++++++++++++++++++++++++++++++++++--
> >>  2 files changed, 308 insertions(+), 5 deletions(-)
> >
> >This seems fine.  What would help would be a link to a travis-ci job
> >with this particular patch applied showing everything still builds too
> >:)  Thanks!
> 
> Do you mean I need to put a travis-ci job link in the commit log?
> I just use buildman to do the build on my local PC, I do not have
> travis-ci building.

Below the '---' is better probably.  Did you buildman everything or just
arm/powerpc?  Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170406/ac117919/attachment.sig>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [U-Boot] lib: div64: sync with Linux
  2017-03-28  9:05 [U-Boot] [PATCH] lib: div64: sync with Linux Peng Fan
  2017-04-05 13:32 ` Tom Rini
@ 2017-04-07 15:51 ` Tom Rini
  1 sibling, 0 replies; 5+ messages in thread
From: Tom Rini @ 2017-04-07 15:51 UTC (permalink / raw)
  To: u-boot

On Tue, Mar 28, 2017 at 05:05:09PM +0800, Peng Fan wrote:

> Sync with Linux commit ad0376eb1483b ("Merge tag 'edac_for_4.11_2'").
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> Cc: Tom Rini <trini@konsulko.com>

   aarch64:  +   uniphier_v8       
+(uniphier_v8) cmd/built-in.o: In function `lldiv':
+(uniphier_v8) include/div64.h:45: undefined reference to
   `__div64_32'
+(uniphier_v8) drivers/mmc/built-in.o: In function `lldiv':
+(uniphier_v8) lib/built-in.o: In function `lldiv':
+(uniphier_v8) lib/built-in.o:include/div64.h:45: more undefined
   references to `__div64_32' follow
+(uniphier_v8) make[1]: *** [u-boot] Error 139
+(uniphier_v8) make: *** [sub-make] Error 2

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170407/b0de7957/attachment.sig>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-04-07 15:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-28  9:05 [U-Boot] [PATCH] lib: div64: sync with Linux Peng Fan
2017-04-05 13:32 ` Tom Rini
2017-04-06  6:04   ` Peng Fan
2017-04-06 12:45     ` Tom Rini
2017-04-07 15:51 ` [U-Boot] " Tom Rini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.