mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] Kill div64.h dupes, parenthesize do_div() macro params
@ 2003-07-02  0:32 Bernardo Innocenti
       [not found] ` <20030701173612.280d1296.akpm@digeo.com>
  0 siblings, 1 reply; 38+ messages in thread
From: Bernardo Innocenti @ 2003-07-02  0:32 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

Hello Linus,

sorry for coming up with this patch in a short time frame, but
it needs to be applied in order to fix real do_div() brokenness
on many architectures.

If you'd prefer me to fix just the bugs without moving
stuff around, I'd be glad to provide another patch. I'd push
this one through a mantainer, but this patch really doesn't
belong to any specific architecture or subsystem, so...

---------------------------------------------------------------------

 - move the 64/32bit do_div() macro to a new asm-generic/div64.h
   header;

 - kill multiple copies of the generic version in architecture
   specific subdirs. Most copies were either buggy or subtly
   different from each other;

 - ensure all surviving instances of do_div() have their parameters
   correctly parenthesized to avoid funny results;

Note that the arm26, cris, m68knommu, sh, sparc and v850 architectures
are silently clipping 64bit dividend to 32bit! This patch doesn't try
to fix this because I can't test on all architectures.

Patch submitted by Bernardo Innocenti <bernie@develer.com>

Applies to 2.5.73. Backporting to 2.4.21 is trivial.


FOOT NOTE: what's the point with do_div()? Isn't gcc's long long
arithmetic support good enough on all platforms? If not, why
doesn't that get fixed in libgcc instead of polluting the kernel
with silly (and sometimes bogus) implementations?


 asm-alpha/div64.h     |   15 +--------------
 asm-arm26/div64.h     |   15 +--------------
 asm-cris/div64.h      |   17 +----------------
 asm-generic/div64.h   |   13 +++++++++++++
 asm-h8300/div64.h     |   14 +-------------
 asm-ia64/div64.h      |   21 +--------------------
 asm-m68k/div64.h      |    9 ---------
 asm-m68knommu/div64.h |   14 +-------------
 asm-mips64/div64.h    |   20 +-------------------
 asm-parisc/div64.h    |   36 ++++++++++--------------------------
 asm-ppc64/div64.h     |   19 +------------------
 asm-s390/div64.h      |    8 +-------
 asm-sh/div64.h        |   11 +----------
 asm-sparc/div64.h     |   12 +-----------
 asm-sparc64/div64.h   |   15 +--------------
 asm-v850/div64.h      |   12 +-----------
 asm-x86_64/div64.h    |   15 +--------------
 17 files changed, 37 insertions(+), 229 deletions(-)

diff -Nru linux-2.5.73-uc0/include/asm-generic/div64.h linux-2.5.x/include/asm-generic/div64.h
--- linux-2.5.73-uc0/include/asm-generic/div64.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.5.x/include/asm-generic/div64.h	2003-06-26 01:26:49.000000000 +0200
@@ -0,0 +1,13 @@
+#ifndef _ASM_GENERIC_DIV64_H
+#define _ASM_GENERIC_DIV64_H
+
+/* n = n / base; return rem; */
+
+#define do_div(n,base) ({					\
+	int __res;						\
+	__res = ((unsigned long)(n)) % (unsigned)(base);	\
+	(n) = ((unsigned long)(n)) / (unsigned)(base);		\
+	__res;							\
+})
+
+#endif /* _ASM_GENERIC_DIV64_H */
diff -Nru linux-2.5.73-uc0/include/asm-alpha/div64.h linux-2.5.x/include/asm-alpha/div64.h
--- linux-2.5.73-uc0/include/asm-alpha/div64.h	2003-06-22 20:33:15.000000000 +0200
+++ linux-2.5.x/include/asm-alpha/div64.h	2003-06-26 01:21:03.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __ALPHA_DIV64
-#define __ALPHA_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-arm26/div64.h linux-2.5.x/include/asm-arm26/div64.h
--- linux-2.5.73-uc0/include/asm-arm26/div64.h	2003-06-22 20:32:35.000000000 +0200
+++ linux-2.5.x/include/asm-arm26/div64.h	2003-06-26 01:21:39.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __ASM_ARM_DIV64
-#define __ASM_ARM_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base)						\
-({								\
-	int __res;						\
-	__res = ((unsigned long)n) % (unsigned int)base;	\
-	n = ((unsigned long)n) / (unsigned int)base;		\
-	__res;							\
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-cris/div64.h linux-2.5.x/include/asm-cris/div64.h
--- linux-2.5.73-uc0/include/asm-cris/div64.h	2003-06-22 20:32:35.000000000 +0200
+++ linux-2.5.x/include/asm-cris/div64.h	2003-06-26 01:21:49.000000000 +0200
@@ -1,16 +1 @@
-#ifndef __ASM_CRIS_DIV64
-#define __ASM_CRIS_DIV64
-
-/* copy from asm-arm */
-
-/* We're not 64-bit, but... */
-#define do_div(n,base)						\
-({								\
-	int __res;						\
-	__res = ((unsigned long)n) % (unsigned int)base;	\
-	n = ((unsigned long)n) / (unsigned int)base;		\
-	__res;							\
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-h8300/div64.h linux-2.5.x/include/asm-h8300/div64.h
--- linux-2.5.73-uc0/include/asm-h8300/div64.h	2003-06-22 20:32:28.000000000 +0200
+++ linux-2.5.x/include/asm-h8300/div64.h	2003-06-26 01:22:10.000000000 +0200
@@ -1,13 +1 @@
-#ifndef H8300_DIV64_H
-#define H8300_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-
-#endif /* _H8300_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-ia64/div64.h linux-2.5.x/include/asm-ia64/div64.h
--- linux-2.5.73-uc0/include/asm-ia64/div64.h	2003-06-22 20:33:36.000000000 +0200
+++ linux-2.5.x/include/asm-ia64/div64.h	2003-06-26 01:23:05.000000000 +0200
@@ -1,20 +1 @@
-#ifndef _ASM_IA64_DIV64_H
-#define _ASM_IA64_DIV64_H
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64...
- */
-
-#define do_div(n,base)						\
-({								\
-	int _res;						\
-	_res = ((unsigned long) (n)) % (unsigned) (base);	\
-	(n) = ((unsigned long) (n)) / (unsigned) (base);	\
-	_res;							\
-})
-
-#endif /* _ASM_IA64_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-m68k/div64.h linux-2.5.x/include/asm-m68k/div64.h
--- linux-2.5.73-uc0/include/asm-m68k/div64.h	2003-06-22 20:33:17.000000000 +0200
+++ linux-2.5.x/include/asm-m68k/div64.h	2003-06-26 01:23:35.000000000 +0200
@@ -3,7 +3,6 @@
 
 /* n = n / base; return rem; */
 
-#if 1
 #define do_div(n, base) ({					\
 	union {							\
 		unsigned long n32[2];				\
@@ -23,13 +22,5 @@
 	(n) = __n.n64;						\
 	__rem;							\
 })
-#else
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-#endif
 
 #endif /* _M68K_DIV64_H */
diff -Nru linux-2.5.73-uc0/include/asm-m68knommu/div64.h linux-2.5.x/include/asm-m68knommu/div64.h
--- linux-2.5.73-uc0/include/asm-m68knommu/div64.h	2003-06-22 20:32:37.000000000 +0200
+++ linux-2.5.x/include/asm-m68knommu/div64.h	2003-06-26 01:23:54.000000000 +0200
@@ -1,13 +1 @@
-#ifndef _M68KNOMMU_DIV64_H
-#define _M68KNOMMU_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-
-#endif /* _M68K_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-mips64/div64.h linux-2.5.x/include/asm-mips64/div64.h
--- linux-2.5.73-uc0/include/asm-mips64/div64.h	2003-06-22 20:32:45.000000000 +0200
+++ linux-2.5.x/include/asm-mips64/div64.h	2003-06-26 01:24:41.000000000 +0200
@@ -1,19 +1 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef _ASM_DIV64_H
-#define _ASM_DIV64_H
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* _ASM_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-parisc/div64.h linux-2.5.x/include/asm-parisc/div64.h
--- linux-2.5.73-uc0/include/asm-parisc/div64.h	2003-06-22 20:32:55.000000000 +0200
+++ linux-2.5.x/include/asm-parisc/div64.h	2003-06-26 01:25:25.000000000 +0200
@@ -2,23 +2,7 @@
 #define __ASM_PARISC_DIV64
 
 #ifdef __LP64__
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64 and HPPA
- */
-
-#define do_div(n,base)						\
-({								\
-	int _res;						\
-	_res = ((unsigned long) (n)) % (unsigned) (base);	\
-	(n) = ((unsigned long) (n)) / (unsigned) (base);	\
-	_res;							\
-})
-
+#include <asm-generic/div64.h>
 #else
 /*
  * unsigned long long division.  Yuck Yuck!  What is Linux coming to?
@@ -30,21 +14,21 @@
 	__low  = (n) & 0xffffffff;					\
 	__high = (n) >> 32;						\
 	if (__high) {							\
-		__rem   = __high % (unsigned long)base;			\
-		__high  = __high / (unsigned long)base;			\
+		__rem   = __high % (unsigned long)(base);		\
+		__high  = __high / (unsigned long)(base);		\
 		__low2  = __low >> 16;					\
 		__low2 += __rem << 16;					\
-		__rem   = __low2 % (unsigned long)base;			\
-		__low2  = __low2 / (unsigned long)base;			\
+		__rem   = __low2 % (unsigned long)(base);		\
+		__low2  = __low2 / (unsigned long)(base);		\
 		__low   = __low & 0xffff;				\
 		__low  += __rem << 16;					\
-		__rem   = __low  % (unsigned long)base;			\
-		__low   = __low  / (unsigned long)base;			\
-		n = __low  + ((long long)__low2 << 16) +		\
+		__rem   = __low  % (unsigned long)(base);		\
+		__low   = __low  / (unsigned long)(base);		\
+		(n) = __low  + ((long long)__low2 << 16) +		\
 			((long long) __high << 32);			\
 	} else {							\
-		__rem = __low % (unsigned long)base;			\
-		n = (__low / (unsigned long)base);			\
+		__rem = __low % (unsigned long)(base);			\
+		(n) = (__low / (unsigned long)(base));			\
 	}								\
 	__rem;								\
 })
diff -Nru linux-2.5.73-uc0/include/asm-ppc64/div64.h linux-2.5.x/include/asm-ppc64/div64.h
--- linux-2.5.73-uc0/include/asm-ppc64/div64.h	2003-06-22 20:32:28.000000000 +0200
+++ linux-2.5.x/include/asm-ppc64/div64.h	2003-06-26 01:27:20.000000000 +0200
@@ -1,18 +1 @@
-#ifndef __PPC_DIV64
-#define __PPC_DIV64
-
-/* Copyright 2001 PPC64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-s390/div64.h linux-2.5.x/include/asm-s390/div64.h
--- linux-2.5.73-uc0/include/asm-s390/div64.h	2003-06-22 20:32:57.000000000 +0200
+++ linux-2.5.x/include/asm-s390/div64.h	2003-06-26 01:27:51.000000000 +0200
@@ -43,13 +43,7 @@
 })
 
 #else /* __s390x__ */
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
+#include <asm-generic/div64.h>
 #endif /* __s390x__ */
 
 #endif
diff -Nru linux-2.5.73-uc0/include/asm-sh/div64.h linux-2.5.x/include/asm-sh/div64.h
--- linux-2.5.73-uc0/include/asm-sh/div64.h	2003-06-22 20:32:28.000000000 +0200
+++ linux-2.5.x/include/asm-sh/div64.h	2003-06-26 01:28:08.000000000 +0200
@@ -1,10 +1 @@
-#ifndef __ASM_SH_DIV64
-#define __ASM_SH_DIV64
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
-#endif /* __ASM_SH_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-sparc/div64.h linux-2.5.x/include/asm-sparc/div64.h
--- linux-2.5.73-uc0/include/asm-sparc/div64.h	2003-06-22 20:32:58.000000000 +0200
+++ linux-2.5.x/include/asm-sparc/div64.h	2003-06-26 01:28:25.000000000 +0200
@@ -1,11 +1 @@
-#ifndef __SPARC_DIV64
-#define __SPARC_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __SPARC_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-sparc64/div64.h linux-2.5.x/include/asm-sparc64/div64.h
--- linux-2.5.73-uc0/include/asm-sparc64/div64.h	2003-06-22 20:32:42.000000000 +0200
+++ linux-2.5.x/include/asm-sparc64/div64.h	2003-06-26 01:28:47.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __SPARC64_DIV64
-#define __SPARC64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __SPARC64_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-v850/div64.h linux-2.5.x/include/asm-v850/div64.h
--- linux-2.5.73-uc0/include/asm-v850/div64.h	2003-06-22 20:33:08.000000000 +0200
+++ linux-2.5.x/include/asm-v850/div64.h	2003-06-26 01:29:07.000000000 +0200
@@ -1,11 +1 @@
-#ifndef __V850_DIV64_H__
-#define __V850_DIV64_H__
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __V850_DIV64_H__ */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.73-uc0/include/asm-x86_64/div64.h linux-2.5.x/include/asm-x86_64/div64.h
--- linux-2.5.73-uc0/include/asm-x86_64/div64.h	2003-06-22 20:33:12.000000000 +0200
+++ linux-2.5.x/include/asm-x86_64/div64.h	2003-06-26 01:29:16.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __X86_64_DIV64
-#define __X86_64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>

-- 
  // Bernardo Innocenti - Develer S.r.l., R&D dept.
\X/  http://www.develer.com/

Please don't send Word attachments - http://www.gnu.org/philosophy/no-word-attachments.html



^ permalink raw reply	[flat|nested] 38+ messages in thread
* [PATCH] Fix do_div() for all architectures
@ 2003-07-05 23:33 Bernardo Innocenti
  2003-07-06  7:47 ` Russell King
  2003-07-07  4:26 ` Bernardo Innocenti
  0 siblings, 2 replies; 38+ messages in thread
From: Bernardo Innocenti @ 2003-07-05 23:33 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: linux-kernel, Andrea Arcangeli, Peter Chubb, Andrew Morton, Russell King

Hello everybody,

second iteration of the div64.h cleanup + bug fixing.
Contains the following changes since the previous release:

 - add likely() to the fast path (divisor>>32 == 0);

 - add __attribute__((pure)) to __div64_32() prototype so
   the compiler knows global memory isn't clobbered;

 - export the __div64_32 symbol for modules;

The generic do_div() code is now tested on m68knommu, arm
and even i386 (by manually replacing real asm-i386/div64.h
with the generic version).

Applies to 2.5.74 and 2.5.74-bk2. I'll provide a 2.4
backport once it has been tested in 2.5.

  // Bernardo Innocenti - Develer S.r.l., R&D dept.
\X/  http://www.develer.com/

-----------------------------------------------------------------

 - add generic C implementations of the do_div() for 32bit and 64bit
   archs in asm-generic/div64.h;

 - add generic library support function __div64_32() to handle the
   full 64/32 case on 32bit archs;

 - kill multiple copies of generic do_div() in architecture
   specific subdirs. Most copies were either buggy or not doing
   what they were supposed to do;

 - ensure all surviving instances of do_div() have their parameters
   correctly parenthesized to avoid funny side-effects;

 include/asm-generic/div64.h   |   53 ++++++++++++++++++++++++++++++++++++++++
 lib/div64.c                   |   47 ++++++++++++++++++++++++++++++++++
 include/asm-alpha/div64.h     |   15 -----------
 include/asm-arm26/div64.h     |   15 -----------
 include/asm-cris/div64.h      |   17 ------------
 include/asm-h8300/div64.h     |   14 ----------
 include/asm-ia64/div64.h      |   21 ----------------
 include/asm-m68k/div64.h      |    9 ------
 include/asm-m68knommu/div64.h |   14 ----------
 include/asm-mips64/div64.h    |   19 --------------
 include/asm-parisc/div64.h    |   55 ------------------------------------------
 include/asm-ppc/div64.h       |   24 ------------------
 include/asm-ppc64/div64.h     |   19 --------------
 include/asm-s390/div64.h      |    8 ------
 include/asm-sh/div64.h        |   21 ----------------
 include/asm-sparc/div64.h     |   12 ---------
 include/asm-sparc64/div64.h   |   15 -----------
 include/asm-v850/div64.h      |   12 ---------
 include/asm-x86_64/div64.h    |   15 -----------
 lib/Makefile                  |    2 -
 20 files changed, 115 insertions(+), 290 deletions(-)

diff -Nru linux-2.5.74-uc0/include/asm-generic/div64.h linux-2.5.74-uc0-develer/include/asm-generic/div64.h
--- linux-2.5.74-uc0/include/asm-generic/div64.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.5.74-uc0-develer/include/asm-generic/div64.h	2003-07-03 09:55:04.000000000 +0200
@@ -0,0 +1,53 @@
+#ifndef _ASM_GENERIC_DIV64_H
+#define _ASM_GENERIC_DIV64_H
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
+ *
+ * The semantics of do_div() are:
+ *
+ * uint32_t do_div(uint64_t *n, uint32_t base)
+ * {
+ * 	uint32_t remainder = *n % base;
+ * 	*n = *n / base;
+ * 	return remainder;
+ * }
+ *
+ * NOTE: macro parameter n is evaluated multiple times,
+ *       beware of side effects!
+ */
+
+#include <linux/types.h>
+
+#if BITS_PER_LONG == 64
+
+# define do_div(n,base) ({					\
+	uint32_t __base = (base);				\
+	uint32_t __rem;						\
+	__rem = ((uint64_t)(n)) % __base;			\
+	(n) = ((uint64_t)(n)) / __base;				\
+	__rem;							\
+ })
+
+#elif BITS_PER_LONG == 32
+
+extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor) __attribute__((pure));
+
+# define do_div(n,base) ({				\
+	uint32_t __base = (base);			\
+	uint32_t __rem;					\
+	if (likely(((n) >> 32) == 0)) {			\
+		__rem = (uint32_t)(n) % __base;		\
+		(n) = (uint32_t)(n) / __base;		\
+	} else 						\
+		__rem = __div64_32(&(n), __base);	\
+	__rem;						\
+ })
+
+#else /* BITS_PER_LONG == ?? */
+
+# error do_div() does not yet support the C64
+
+#endif /* BITS_PER_LONG */
+
+#endif /* _ASM_GENERIC_DIV64_H */
diff -Nru linux-2.5.74-uc0/lib/div64.c linux-2.5.74-uc0-develer/lib/div64.c
--- linux-2.5.74-uc0/lib/div64.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.5.74-uc0-develer/lib/div64.c	2003-07-03 09:37:22.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ *
+ * Based on former do_div() implementation from asm-parisc/div64.h:
+ *	Copyright (C) 1999 Hewlett-Packard Co
+ *	Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ *
+ * 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(). 
+ *
+ * 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/ppc/lib/div64.S and arch/sh/lib/div64.S.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <asm/div64.h>
+
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+	uint32_t low, low2, high, rem;
+
+	low   = *n   & 0xffffffff;
+	high  = *n  >> 32;
+	rem   = high % (uint32_t)base;
+	high  = high / (uint32_t)base;
+	low2  = low >> 16;
+	low2 += rem << 16;
+	rem   = low2 % (uint32_t)base;
+	low2  = low2 / (uint32_t)base;
+	low   = low  & 0xffff;
+	low  += rem << 16;
+	rem   = low  % (uint32_t)base;
+	low   = low  / (uint32_t)base;
+
+	*n = low +
+		((uint64_t)low2 << 16) +
+		((uint64_t)high << 32);
+
+	return rem;
+}
+
+EXPORT_SYMBOL(__div64_32);
diff -Nru linux-2.5.74-uc0/include/asm-alpha/div64.h linux-2.5.74-uc0-develer/include/asm-alpha/div64.h
--- linux-2.5.74-uc0/include/asm-alpha/div64.h	2003-07-02 22:54:43.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-alpha/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __ALPHA_DIV64
-#define __ALPHA_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-arm26/div64.h linux-2.5.74-uc0-develer/include/asm-arm26/div64.h
--- linux-2.5.74-uc0/include/asm-arm26/div64.h	2003-07-02 22:42:11.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-arm26/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __ASM_ARM_DIV64
-#define __ASM_ARM_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base)						\
-({								\
-	int __res;						\
-	__res = ((unsigned long)n) % (unsigned int)base;	\
-	n = ((unsigned long)n) / (unsigned int)base;		\
-	__res;							\
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-cris/div64.h linux-2.5.74-uc0-develer/include/asm-cris/div64.h
--- linux-2.5.74-uc0/include/asm-cris/div64.h	2003-07-02 22:42:06.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-cris/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,16 +1 @@
-#ifndef __ASM_CRIS_DIV64
-#define __ASM_CRIS_DIV64
-
-/* copy from asm-arm */
-
-/* We're not 64-bit, but... */
-#define do_div(n,base)						\
-({								\
-	int __res;						\
-	__res = ((unsigned long)n) % (unsigned int)base;	\
-	n = ((unsigned long)n) / (unsigned int)base;		\
-	__res;							\
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-h8300/div64.h linux-2.5.74-uc0-develer/include/asm-h8300/div64.h
--- linux-2.5.74-uc0/include/asm-h8300/div64.h	2003-07-02 22:39:25.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-h8300/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,13 +1 @@
-#ifndef H8300_DIV64_H
-#define H8300_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-
-#endif /* _H8300_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-ia64/div64.h linux-2.5.74-uc0-develer/include/asm-ia64/div64.h
--- linux-2.5.74-uc0/include/asm-ia64/div64.h	2003-07-02 22:58:14.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-ia64/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,20 +1 @@
-#ifndef _ASM_IA64_DIV64_H
-#define _ASM_IA64_DIV64_H
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64...
- */
-
-#define do_div(n,base)						\
-({								\
-	int _res;						\
-	_res = ((unsigned long) (n)) % (unsigned) (base);	\
-	(n) = ((unsigned long) (n)) / (unsigned) (base);	\
-	_res;							\
-})
-
-#endif /* _ASM_IA64_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-m68k/div64.h linux-2.5.74-uc0-develer/include/asm-m68k/div64.h
--- linux-2.5.74-uc0/include/asm-m68k/div64.h	2003-07-02 22:55:53.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-m68k/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -3,7 +3,6 @@
 
 /* n = n / base; return rem; */
 
-#if 1
 #define do_div(n, base) ({					\
 	union {							\
 		unsigned long n32[2];				\
@@ -23,13 +22,5 @@
 	(n) = __n.n64;						\
 	__rem;							\
 })
-#else
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-#endif
 
 #endif /* _M68K_DIV64_H */
diff -Nru linux-2.5.74-uc0/include/asm-m68knommu/div64.h linux-2.5.74-uc0-develer/include/asm-m68knommu/div64.h
--- linux-2.5.74-uc0/include/asm-m68knommu/div64.h	2003-07-03 10:40:35.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-m68knommu/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,13 +1 @@
-#ifndef _M68KNOMMU_DIV64_H
-#define _M68KNOMMU_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-
-#endif /* _M68K_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-mips64/div64.h linux-2.5.74-uc0-develer/include/asm-mips64/div64.h
--- linux-2.5.74-uc0/include/asm-mips64/div64.h	2003-07-02 22:47:26.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-mips64/div64.h	2003-07-03 09:39:28.000000000 +0200
@@ -27,23 +27,6 @@
 	(res) = __quot; \
 	__mod; })
 
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n, base) ({ \
-	unsigned long __quot; \
-	unsigned int __mod; \
-	unsigned long __div; \
-	unsigned int __base; \
-	\
-	__div = (n); \
-	__base = (base); \
-	\
-	__mod = __div % __base; \
-	__quot = __div / __base; \
-	\
-	(n) = __quot; \
-	__mod; })
+#include <asm-generic.h>
 
 #endif /* _ASM_DIV64_H */
diff -Nru linux-2.5.74-uc0/include/asm-parisc/div64.h linux-2.5.74-uc0-develer/include/asm-parisc/div64.h
--- linux-2.5.74-uc0/include/asm-parisc/div64.h	2003-07-02 22:48:40.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-parisc/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,54 +1 @@
-#ifndef __ASM_PARISC_DIV64
-#define __ASM_PARISC_DIV64
-
-#ifdef __LP64__
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64 and HPPA
- */
-
-#define do_div(n,base)						\
-({								\
-	int _res;						\
-	_res = ((unsigned long) (n)) % (unsigned) (base);	\
-	(n) = ((unsigned long) (n)) / (unsigned) (base);	\
-	_res;							\
-})
-
-#else
-/*
- * unsigned long long division.  Yuck Yuck!  What is Linux coming to?
- * This is 100% disgusting
- */
-#define do_div(n,base)							\
-({									\
-	unsigned long __low, __low2, __high, __rem;			\
-	__low  = (n) & 0xffffffff;					\
-	__high = (n) >> 32;						\
-	if (__high) {							\
-		__rem   = __high % (unsigned long)base;			\
-		__high  = __high / (unsigned long)base;			\
-		__low2  = __low >> 16;					\
-		__low2 += __rem << 16;					\
-		__rem   = __low2 % (unsigned long)base;			\
-		__low2  = __low2 / (unsigned long)base;			\
-		__low   = __low & 0xffff;				\
-		__low  += __rem << 16;					\
-		__rem   = __low  % (unsigned long)base;			\
-		__low   = __low  / (unsigned long)base;			\
-		n = __low  + ((long long)__low2 << 16) +		\
-			((long long) __high << 32);			\
-	} else {							\
-		__rem = __low % (unsigned long)base;			\
-		n = (__low / (unsigned long)base);			\
-	}								\
-	__rem;								\
-})
-#endif
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-ppc/div64.h linux-2.5.74-uc0-develer/include/asm-ppc/div64.h
--- linux-2.5.74-uc0/include/asm-ppc/div64.h	2003-07-02 22:57:06.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-ppc/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,23 +1 @@
-#ifndef __PPC_DIV64
-#define __PPC_DIV64
-
-#include <linux/types.h>
-
-extern u32 __div64_32(u64 *dividend, u32 div);
-
-#define do_div(n, div)	({			\
-	u64 __n = (n);				\
-	u32 __d = (div);			\
-	u32 __q, __r;				\
-	if ((__n >> 32) == 0) {			\
-		__q = (u32)__n / __d;		\
-		__r = (u32)__n - __q * __d;	\
-		(n) = __q;			\
-	} else {				\
-		__r = __div64_32(&__n, __d);	\
-		(n) = __n;			\
-	}					\
-	__r;					\
-})
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-ppc64/div64.h linux-2.5.74-uc0-develer/include/asm-ppc64/div64.h
--- linux-2.5.74-uc0/include/asm-ppc64/div64.h	2003-07-02 22:39:34.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-ppc64/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,18 +1 @@
-#ifndef __PPC_DIV64
-#define __PPC_DIV64
-
-/* Copyright 2001 PPC64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-s390/div64.h linux-2.5.74-uc0-develer/include/asm-s390/div64.h
--- linux-2.5.74-uc0/include/asm-s390/div64.h	2003-07-02 22:50:17.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-s390/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -43,13 +43,7 @@
 })
 
 #else /* __s390x__ */
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
+#include <asm-generic/div64.h>
 #endif /* __s390x__ */
 
 #endif
diff -Nru linux-2.5.74-uc0/include/asm-sh/div64.h linux-2.5.74-uc0-develer/include/asm-sh/div64.h
--- linux-2.5.74-uc0/include/asm-sh/div64.h	2003-07-02 22:39:36.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-sh/div64.h	2003-07-03 09:38:59.000000000 +0200
@@ -1,20 +1 @@
-#ifndef __ASM_SH_DIV64
-#define __ASM_SH_DIV64
-
-extern u64 __div64_32(u64 n, u32 d);
-
-#define do_div(n,base) ({ \
-u64 __n = (n), __q; \
-u32 __base = (base); \
-u32 __res; \
-if ((__n >> 32) == 0) { \
-	__res = ((unsigned long) __n) % (unsigned) __base; \
-	(n) = ((unsigned long) __n) / (unsigned) __base; \
-} else { \
-	__q = __div64_32(__n, __base); \
-	__res = __n - __q * __base; \
-	(n) = __q; \
-} \
-__res; })
-
-#endif /* __ASM_SH_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-sparc/div64.h linux-2.5.74-uc0-develer/include/asm-sparc/div64.h
--- linux-2.5.74-uc0/include/asm-sparc/div64.h	2003-07-02 22:51:01.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-sparc/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,11 +1 @@
-#ifndef __SPARC_DIV64
-#define __SPARC_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __SPARC_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-sparc64/div64.h linux-2.5.74-uc0-develer/include/asm-sparc64/div64.h
--- linux-2.5.74-uc0/include/asm-sparc64/div64.h	2003-07-02 22:46:06.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-sparc64/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __SPARC64_DIV64
-#define __SPARC64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __SPARC64_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-v850/div64.h linux-2.5.74-uc0-develer/include/asm-v850/div64.h
--- linux-2.5.74-uc0/include/asm-v850/div64.h	2003-07-02 22:53:46.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-v850/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,11 +1 @@
-#ifndef __V850_DIV64_H__
-#define __V850_DIV64_H__
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __V850_DIV64_H__ */
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/include/asm-x86_64/div64.h linux-2.5.74-uc0-develer/include/asm-x86_64/div64.h
--- linux-2.5.74-uc0/include/asm-x86_64/div64.h	2003-07-02 22:54:30.000000000 +0200
+++ linux-2.5.74-uc0-develer/include/asm-x86_64/div64.h	2003-07-03 09:37:22.000000000 +0200
@@ -1,14 +1 @@
-#ifndef __X86_64_DIV64
-#define __X86_64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru linux-2.5.74-uc0/lib/Makefile linux-2.5.74-uc0-develer/lib/Makefile
--- linux-2.5.74-uc0/lib/Makefile	2003-07-02 22:40:29.000000000 +0200
+++ linux-2.5.74-uc0-develer/lib/Makefile	2003-07-03 09:37:22.000000000 +0200
@@ -5,7 +5,7 @@
 
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
-	 kobject.o idr.o
+	 kobject.o idr.o div64.o
 
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o




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

end of thread, other threads:[~2003-07-10 22:58 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-02  0:32 [PATCH] Kill div64.h dupes, parenthesize do_div() macro params Bernardo Innocenti
     [not found] ` <20030701173612.280d1296.akpm@digeo.com>
2003-07-02  2:24   ` Bernardo Innocenti
2003-07-02  2:32     ` Andrew Morton
2003-07-02  3:15       ` Bernardo Innocenti
2003-07-02  5:12         ` Linus Torvalds
2003-07-02  7:53         ` Russell King
2003-07-02  8:14           ` Ian Molton
2003-07-02  5:09       ` Linus Torvalds
2003-07-02  7:02         ` Bernardo Innocenti
2003-07-02  7:54           ` Matti Aarnio
2003-07-02  3:36     ` Peter Chubb
2003-07-02  4:37       ` Bernardo Innocenti
2003-07-02  5:57       ` Andrea Arcangeli
2003-07-02  6:52         ` Bernardo Innocenti
2003-07-02  7:19           ` Andrea Arcangeli
2003-07-02  7:28             ` Bernardo Innocenti
2003-07-02  8:38               ` Andrea Arcangeli
2003-07-02 16:16           ` Linus Torvalds
2003-07-03 10:43             ` [PATCH] Fix do_div() for all architectures Bernardo Innocenti
2003-07-02  7:56         ` [PATCH] Kill div64.h dupes, parenthesize do_div() macro params Russell King
2003-07-02  5:06     ` Linus Torvalds
2003-07-02 14:23       ` Geert Uytterhoeven
2003-07-05 23:33 [PATCH] Fix do_div() for all architectures Bernardo Innocenti
2003-07-06  7:47 ` Russell King
2003-07-06 15:40   ` Ian Molton
2003-07-07  4:26 ` Bernardo Innocenti
2003-07-08 18:27   ` Bernardo Innocenti
2003-07-08 18:31     ` Andrew Morton
2003-07-08 20:56       ` Bernardo Innocenti
2003-07-10 15:40     ` Richard Henderson
2003-07-10 16:18       ` Andrea Arcangeli
2003-07-10 16:39         ` Richard Henderson
2003-07-10 19:31           ` Bernardo Innocenti
2003-07-10 19:53             ` Dale Johannesen
2003-07-10 20:19             ` Andrea Arcangeli
2003-07-10 22:58               ` Bernardo Innocenti
2003-07-10 22:04             ` Richard Henderson
2003-07-10 23:13       ` Bernardo Innocenti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®