public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] 64-bit divide tweaks
@ 2002-01-25 19:34 Momchil Velikov
  2002-01-25 19:40 ` Jeff Garzik
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Momchil Velikov @ 2002-01-25 19:34 UTC (permalink / raw)
  To: linux-kernel

Hi there,

printk, etc. are broken wrt printing 64-bit numbers (%ll, %L).

This patch fixes do_div, which did (on some archs) 32-bit divide.

Regards,
-velco

===== drivers/net/sk98lin/skproc.c 1.1 vs edited =====
--- 1.1/drivers/net/sk98lin/skproc.c	Sat Dec  8 02:14:15 2001
+++ edited/drivers/net/sk98lin/skproc.c	Fri Jan 25 21:20:06 2002
@@ -339,17 +339,6 @@
  return (Rest);
 }
 
-
-#if 0
-#define do_div(n,base) ({ \
-long long __res; \
-__res = ((unsigned long long) n) % (unsigned) base; \
-n = ((unsigned long long) n) / (unsigned) base; \
-__res; })
-
-#endif
-
-
 /*****************************************************************************
  *
  * SkNumber - Print results
===== include/asm-arm/div64.h 1.1 vs edited =====
--- 1.1/include/asm-arm/div64.h	Sat Dec  8 02:13:45 2001
+++ edited/include/asm-arm/div64.h	Fri Jan 25 21:21:56 2002
@@ -1,12 +1,11 @@
 #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 = ((unsigned long long)n) % (unsigned int)base;	\
+	n = ((unsigned long long)n) / (unsigned int)base;		\
 	__res;							\
 })
 
===== include/asm-cris/div64.h 1.1 vs edited =====
--- 1.1/include/asm-cris/div64.h	Sat Dec  8 02:13:57 2001
+++ edited/include/asm-cris/div64.h	Fri Jan 25 21:22:19 2002
@@ -3,12 +3,11 @@
 
 /* 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 = ((unsigned long long)n) % (unsigned int)base;	\
+	n = ((unsigned long long)n) / (unsigned int)base;	\
 	__res;							\
 })
 
===== include/asm-m68k/div64.h 1.1 vs edited =====
--- 1.1/include/asm-m68k/div64.h	Sat Dec  8 02:13:35 2001
+++ edited/include/asm-m68k/div64.h	Fri Jan 25 21:23:59 2002
@@ -26,8 +26,8 @@
 #else
 #define do_div(n,base) ({					\
 	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
+	__res = ((unsigned long long) n) % (unsigned) base;	\
+	n = ((unsigned long long) n) / (unsigned) base;		\
 	__res;							\
 })
 #endif
===== include/asm-ppc/div64.h 1.1 vs edited =====
--- 1.1/include/asm-ppc/div64.h	Sat Dec  8 02:13:37 2001
+++ edited/include/asm-ppc/div64.h	Fri Jan 25 21:28:49 2002
@@ -4,10 +4,9 @@
 #ifndef __PPC_DIV64
 #define __PPC_DIV64
 
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
+#define do_div(n,base) ({					\
+	int __res;						\
+	__res = ((unsigned long long) n) % (unsigned) base;	\
+	n = ((unsigned long long) n) / (unsigned) base;		\
+	__res; })
 #endif
===== include/asm-sh/div64.h 1.1 vs edited =====
--- 1.1/include/asm-sh/div64.h	Sat Dec  8 02:13:46 2001
+++ edited/include/asm-sh/div64.h	Fri Jan 25 21:29:31 2002
@@ -1,10 +1,9 @@
 #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; })
-
+#define do_div(n,base) ({					\
+	int __res;						\
+	__res = ((unsigned long long) n) % (unsigned) base;	\
+	n = ((unsigned long long) n) / (unsigned) base;		\
+	__res; })
 #endif /* __ASM_SH_DIV64 */
===== include/asm-sparc/div64.h 1.1 vs edited =====
--- 1.1/include/asm-sparc/div64.h	Sat Dec  8 02:13:36 2001
+++ edited/include/asm-sparc/div64.h	Fri Jan 25 21:25:39 2002
@@ -1,11 +1,10 @@
 #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 = ((unsigned long long) n) % (unsigned) base; \
+	n = ((unsigned long long) n) / (unsigned) base; \
 	__res; })
 
 #endif /* __SPARC_DIV64 */

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

* Re: [PATCH] 64-bit divide tweaks
  2002-01-25 19:34 [PATCH] 64-bit divide tweaks Momchil Velikov
@ 2002-01-25 19:40 ` Jeff Garzik
  2002-01-25 21:50   ` Tim Schmielau
  2002-01-27 18:04 ` Troy Benjegerdes
  2002-01-27 18:51 ` Matti Aarnio
  2 siblings, 1 reply; 7+ messages in thread
From: Jeff Garzik @ 2002-01-25 19:40 UTC (permalink / raw)
  To: Momchil Velikov; +Cc: linux-kernel

If you are gonna hack them all anyway, why not turn them into static
inlines...
-- 
Jeff Garzik      | "I went through my candy like hot oatmeal
Building 1024    |  through an internally-buttered weasel."
MandrakeSoft     |             - goats.com

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

* Re: [PATCH] 64-bit divide tweaks
  2002-01-25 19:40 ` Jeff Garzik
@ 2002-01-25 21:50   ` Tim Schmielau
  0 siblings, 0 replies; 7+ messages in thread
From: Tim Schmielau @ 2002-01-25 21:50 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Momchil Velikov, linux-kernel

On Fri, 25 Jan 2002, Jeff Garzik wrote:

> If you are gonna hack them all anyway, why not turn them into static
> inlines...

Probably a good idea, but then all user need some change like
  do_div(n,base)  --> do_div(&n,base)
as do_div currently is not valid C semantics.

Tim


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

* Re: [PATCH] 64-bit divide tweaks
  2002-01-25 19:34 [PATCH] 64-bit divide tweaks Momchil Velikov
  2002-01-25 19:40 ` Jeff Garzik
@ 2002-01-27 18:04 ` Troy Benjegerdes
  2002-01-27 18:51 ` Matti Aarnio
  2 siblings, 0 replies; 7+ messages in thread
From: Troy Benjegerdes @ 2002-01-27 18:04 UTC (permalink / raw)
  To: Momchil Velikov; +Cc: linux-kernel

On Fri, Jan 25, 2002 at 09:34:43PM +0200, Momchil Velikov wrote:
> Hi there,
> 
> printk, etc. are broken wrt printing 64-bit numbers (%ll, %L).
> 
> This patch fixes do_div, which did (on some archs) 32-bit divide.

Have you tried compiling any of these arches? 

Anything that doesn't include libgcc will die a link missing symbols for 
__udivdi3 and __umoddi3.

> 
> Regards,
> -velco
> 
> ===== drivers/net/sk98lin/skproc.c 1.1 vs edited =====
> --- 1.1/drivers/net/sk98lin/skproc.c	Sat Dec  8 02:14:15 2001
> +++ edited/drivers/net/sk98lin/skproc.c	Fri Jan 25 21:20:06 2002
> @@ -339,17 +339,6 @@
>   return (Rest);
>  }
>  
> -
> -#if 0
> -#define do_div(n,base) ({ \
> -long long __res; \
> -__res = ((unsigned long long) n) % (unsigned) base; \
> -n = ((unsigned long long) n) / (unsigned) base; \
> -__res; })
> -
> -#endif
> -
> -
>  /*****************************************************************************
>   *
>   * SkNumber - Print results
> ===== include/asm-arm/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-arm/div64.h	Sat Dec  8 02:13:45 2001
> +++ edited/include/asm-arm/div64.h	Fri Jan 25 21:21:56 2002
> @@ -1,12 +1,11 @@
>  #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 = ((unsigned long long)n) % (unsigned int)base;	\
> +	n = ((unsigned long long)n) / (unsigned int)base;		\
>  	__res;							\
>  })
>  
> ===== include/asm-cris/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-cris/div64.h	Sat Dec  8 02:13:57 2001
> +++ edited/include/asm-cris/div64.h	Fri Jan 25 21:22:19 2002
> @@ -3,12 +3,11 @@
>  
>  /* 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 = ((unsigned long long)n) % (unsigned int)base;	\
> +	n = ((unsigned long long)n) / (unsigned int)base;	\
>  	__res;							\
>  })
>  
> ===== include/asm-m68k/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-m68k/div64.h	Sat Dec  8 02:13:35 2001
> +++ edited/include/asm-m68k/div64.h	Fri Jan 25 21:23:59 2002
> @@ -26,8 +26,8 @@
>  #else
>  #define do_div(n,base) ({					\
>  	int __res;						\
> -	__res = ((unsigned long) n) % (unsigned) base;		\
> -	n = ((unsigned long) n) / (unsigned) base;		\
> +	__res = ((unsigned long long) n) % (unsigned) base;	\
> +	n = ((unsigned long long) n) / (unsigned) base;		\
>  	__res;							\
>  })
>  #endif
> ===== include/asm-ppc/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-ppc/div64.h	Sat Dec  8 02:13:37 2001
> +++ edited/include/asm-ppc/div64.h	Fri Jan 25 21:28:49 2002
> @@ -4,10 +4,9 @@
>  #ifndef __PPC_DIV64
>  #define __PPC_DIV64
>  
> -#define do_div(n,base) ({ \
> -int __res; \
> -__res = ((unsigned long) n) % (unsigned) base; \
> -n = ((unsigned long) n) / (unsigned) base; \
> -__res; })
> -
> +#define do_div(n,base) ({					\
> +	int __res;						\
> +	__res = ((unsigned long long) n) % (unsigned) base;	\
> +	n = ((unsigned long long) n) / (unsigned) base;		\
> +	__res; })
>  #endif
> ===== include/asm-sh/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-sh/div64.h	Sat Dec  8 02:13:46 2001
> +++ edited/include/asm-sh/div64.h	Fri Jan 25 21:29:31 2002
> @@ -1,10 +1,9 @@
>  #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; })
> -
> +#define do_div(n,base) ({					\
> +	int __res;						\
> +	__res = ((unsigned long long) n) % (unsigned) base;	\
> +	n = ((unsigned long long) n) / (unsigned) base;		\
> +	__res; })
>  #endif /* __ASM_SH_DIV64 */
> ===== include/asm-sparc/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-sparc/div64.h	Sat Dec  8 02:13:36 2001
> +++ edited/include/asm-sparc/div64.h	Fri Jan 25 21:25:39 2002
> @@ -1,11 +1,10 @@
>  #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 = ((unsigned long long) n) % (unsigned) base; \
> +	n = ((unsigned long long) n) / (unsigned) base; \
>  	__res; })
>  
>  #endif /* __SPARC_DIV64 */
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

-- 
Troy Benjegerdes | master of mispeeling | 'da hozer' |  hozer@drgw.net
-----"If this message isn't misspelled, I didn't write it" -- Me -----
"Why do musicians compose symphonies and poets write poems? They do it
because life wouldn't have any meaning for them if they didn't. That's 
why I draw cartoons. It's my life." -- Charles Schulz

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

* Re: [PATCH] 64-bit divide tweaks
  2002-01-25 19:34 [PATCH] 64-bit divide tweaks Momchil Velikov
  2002-01-25 19:40 ` Jeff Garzik
  2002-01-27 18:04 ` Troy Benjegerdes
@ 2002-01-27 18:51 ` Matti Aarnio
  2002-01-29  0:00   ` 64-bit divide cleanup (tested on ppc) Troy Benjegerdes
  2 siblings, 1 reply; 7+ messages in thread
From: Matti Aarnio @ 2002-01-27 18:51 UTC (permalink / raw)
  To: Momchil Velikov; +Cc: linux-kernel

On Fri, Jan 25, 2002 at 09:34:43PM +0200, Momchil Velikov wrote:
> Hi there,
>   printk, etc. are broken wrt printing 64-bit numbers (%ll, %L).
>   This patch fixes do_div, which did (on some archs) 32-bit divide.

  Wrong.

  Correct one is to supply each arch with their native way to handle
  the division.  Remember, the base (divisor) is SMALLISH (2 to 16).

  Where you are unable to do it, the C code that is still present in
  include/asm-parisc/div64.h   alternate code branch will do it.

  This code is needed because the Linux kernel DOES NOT WANT TO
  use gcc builtin functions normally available via  libgcc.
  This is primarily to detect when 32-bit machine does arbitrary
  (and expensive) divisions on 64-bit values.  E.g. stupid code
  slipped into fast-paths.

> Regards,
> -velco

/Matti Aarnio  (who originally created this %Ld printing code,
                and which others have mutated since then..)

 
> ===== drivers/net/sk98lin/skproc.c 1.1 vs edited =====
> --- 1.1/drivers/net/sk98lin/skproc.c	Sat Dec  8 02:14:15 2001
> +++ edited/drivers/net/sk98lin/skproc.c	Fri Jan 25 21:20:06 2002
> @@ -339,17 +339,6 @@
>   return (Rest);
>  }
>  
> -
> -#if 0
> -#define do_div(n,base) ({ \
> -long long __res; \
> -__res = ((unsigned long long) n) % (unsigned) base; \
> -n = ((unsigned long long) n) / (unsigned) base; \
> -__res; })
> -
> -#endif
> -
> -
>  /*****************************************************************************
>   *
>   * SkNumber - Print results
> ===== include/asm-arm/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-arm/div64.h	Sat Dec  8 02:13:45 2001
> +++ edited/include/asm-arm/div64.h	Fri Jan 25 21:21:56 2002
> @@ -1,12 +1,11 @@
>  #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 = ((unsigned long long)n) % (unsigned int)base;	\
> +	n = ((unsigned long long)n) / (unsigned int)base;		\
>  	__res;							\
>  })
>  
> ===== include/asm-cris/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-cris/div64.h	Sat Dec  8 02:13:57 2001
> +++ edited/include/asm-cris/div64.h	Fri Jan 25 21:22:19 2002
> @@ -3,12 +3,11 @@
>  
>  /* 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 = ((unsigned long long)n) % (unsigned int)base;	\
> +	n = ((unsigned long long)n) / (unsigned int)base;	\
>  	__res;							\
>  })
>  
> ===== include/asm-m68k/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-m68k/div64.h	Sat Dec  8 02:13:35 2001
> +++ edited/include/asm-m68k/div64.h	Fri Jan 25 21:23:59 2002
> @@ -26,8 +26,8 @@
>  #else
>  #define do_div(n,base) ({					\
>  	int __res;						\
> -	__res = ((unsigned long) n) % (unsigned) base;		\
> -	n = ((unsigned long) n) / (unsigned) base;		\
> +	__res = ((unsigned long long) n) % (unsigned) base;	\
> +	n = ((unsigned long long) n) / (unsigned) base;		\
>  	__res;							\
>  })
>  #endif
> ===== include/asm-ppc/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-ppc/div64.h	Sat Dec  8 02:13:37 2001
> +++ edited/include/asm-ppc/div64.h	Fri Jan 25 21:28:49 2002
> @@ -4,10 +4,9 @@
>  #ifndef __PPC_DIV64
>  #define __PPC_DIV64
>  
> -#define do_div(n,base) ({ \
> -int __res; \
> -__res = ((unsigned long) n) % (unsigned) base; \
> -n = ((unsigned long) n) / (unsigned) base; \
> -__res; })
> -
> +#define do_div(n,base) ({					\
> +	int __res;						\
> +	__res = ((unsigned long long) n) % (unsigned) base;	\
> +	n = ((unsigned long long) n) / (unsigned) base;		\
> +	__res; })
>  #endif
> ===== include/asm-sh/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-sh/div64.h	Sat Dec  8 02:13:46 2001
> +++ edited/include/asm-sh/div64.h	Fri Jan 25 21:29:31 2002
> @@ -1,10 +1,9 @@
>  #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; })
> -
> +#define do_div(n,base) ({					\
> +	int __res;						\
> +	__res = ((unsigned long long) n) % (unsigned) base;	\
> +	n = ((unsigned long long) n) / (unsigned) base;		\
> +	__res; })
>  #endif /* __ASM_SH_DIV64 */
> ===== include/asm-sparc/div64.h 1.1 vs edited =====
> --- 1.1/include/asm-sparc/div64.h	Sat Dec  8 02:13:36 2001
> +++ edited/include/asm-sparc/div64.h	Fri Jan 25 21:25:39 2002
> @@ -1,11 +1,10 @@
>  #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 = ((unsigned long long) n) % (unsigned) base; \
> +	n = ((unsigned long long) n) / (unsigned) base; \
>  	__res; })
>  
>  #endif /* __SPARC_DIV64 */
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* 64-bit divide cleanup (tested on ppc)
  2002-01-27 18:51 ` Matti Aarnio
@ 2002-01-29  0:00   ` Troy Benjegerdes
  2002-02-07 16:11     ` Gabriel Paubert
  0 siblings, 1 reply; 7+ messages in thread
From: Troy Benjegerdes @ 2002-01-29  0:00 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 199 bytes --]

Attached is a patch to get rid of asm/div64.h on arches that don't have 
optimized asm routines.

I didn't include removeing the various arch/div64.h file yet, since I want 
some comments on this.



[-- Attachment #2: div64-patch --]
[-- Type: text/plain, Size: 10133 bytes --]

Index: drivers/acpi/include/platform/aclinux.h
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/drivers/acpi/include/platform/aclinux.h,v
retrieving revision 1.1
diff -u -r1.1 aclinux.h
--- drivers/acpi/include/platform/aclinux.h	2001/11/30 22:29:16	1.1
+++ drivers/acpi/include/platform/aclinux.h	2002/01/29 00:40:01
@@ -36,9 +36,9 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
+
 #include <asm/system.h>
 #include <asm/atomic.h>
-#include <asm/div64.h>
 
 #define strtoul simple_strtoul
 
Index: drivers/net/sk98lin/skproc.c
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/drivers/net/sk98lin/skproc.c,v
retrieving revision 1.1
diff -u -r1.1 skproc.c
--- drivers/net/sk98lin/skproc.c	2001/11/30 22:29:08	1.1
+++ drivers/net/sk98lin/skproc.c	2002/01/29 00:40:08
@@ -296,60 +296,6 @@
 	return (min_t(int, buffer_length, len - offset));
 }
 
-
-
-
-
-/*****************************************************************************
- *
- * SkDoDiv - convert 64bit number
- *
- * Description:
- *	This function "converts" a long long number.
- *
- * Returns:
- *	remainder of division
- */
-static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
-{
- long   	Rest;
- long long 	Ergebnis;
- long   	Akku;
-
-
- Akku  = Dividend >> 32;
-
- Ergebnis = ((long long) (Akku / Divisor)) << 32;
- Rest = Akku % Divisor ;
-
- Akku = Rest << 16;
- Akku |= ((Dividend & 0xFFFF0000) >> 16);
-
-
- Ergebnis += ((long long) (Akku / Divisor)) << 16;
- Rest = Akku % Divisor ;
-
- Akku = Rest << 16;
- Akku |= (Dividend & 0xFFFF);
-
- Ergebnis += (Akku / Divisor);
- Rest = Akku % Divisor ;
-
- *pErg = Ergebnis;
- return (Rest);
-}
-
-
-#if 0
-#define do_div(n,base) ({ \
-long long __res; \
-__res = ((unsigned long long) n) % (unsigned) base; \
-n = ((unsigned long long) n) / (unsigned) base; \
-__res; })
-
-#endif
-
-
 /*****************************************************************************
  *
  * SkNumber - Print results
@@ -398,7 +344,7 @@
 	if (num == 0)
 		tmp[i++]='0';
 	else while (num != 0)
-		tmp[i++] = digits[SkDoDiv(num,base, &num)];
+		tmp[i++] = digits[do_div(&num,base)];
 
 	if (i > precision)
 		precision = i;
Index: drivers/video/matrox/matroxfb_maven.c
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/drivers/video/matrox/matroxfb_maven.c,v
retrieving revision 1.1
diff -u -r1.1 matroxfb_maven.c
--- drivers/video/matrox/matroxfb_maven.c	2001/11/30 22:29:14	1.1
+++ drivers/video/matrox/matroxfb_maven.c	2002/01/29 00:40:12
@@ -15,7 +15,8 @@
 #include "matroxfb_DAC1064.h"
 #include <linux/i2c.h>
 #include <linux/matroxfb.h>
-#include <asm/div64.h>
+#define USE_SLOW_64BIT_DIVIDES
+#include <linux/div64.h>
 #include <asm/uaccess.h>
 
 #define MAVEN_I2CID	(0x1B)
@@ -698,9 +699,8 @@
 			int vdec;
 			int vlen;
 
-#define MATROX_USE64BIT_DIVIDE
 			if (mt->VTotal) {
-#ifdef MATROX_USE64BIT_DIVIDE
+#ifdef USE_SLOW_64BIT_DIVIDES
 				u64 f1;
 				u32 a;
 				u32 b;
@@ -709,7 +709,7 @@
 				b = (mt->VTotal - 1) * (m->htotal + 2) + m->hcorr + 2;
 
 				f1 = ((u64)a) << 15;	/* *32768 */
-				do_div(f1, b);
+				do_div(&f1, b);
 				vdec = f1;
 #else
 				vdec = m->vlines * 32768 / mt->VTotal;
Index: fs/affs/file.c
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/fs/affs/file.c,v
retrieving revision 1.1
diff -u -r1.1 file.c
--- fs/affs/file.c	2001/11/30 22:28:58	1.1
+++ fs/affs/file.c	2002/01/29 00:40:13
@@ -12,7 +12,6 @@
  *  affs regular file handling primitives
  */
 
-#include <asm/div64.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/sched.h>
Index: fs/affs/inode.c
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/fs/affs/inode.c,v
retrieving revision 1.1
diff -u -r1.1 inode.c
--- fs/affs/inode.c	2001/11/30 22:28:58	1.1
+++ fs/affs/inode.c	2002/01/29 00:40:13
@@ -10,7 +10,6 @@
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
 
-#include <asm/div64.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
Index: fs/ntfs/util.c
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/fs/ntfs/util.c,v
retrieving revision 1.1
diff -u -r1.1 util.c
--- fs/ntfs/util.c	2001/11/30 22:28:59	1.1
+++ fs/ntfs/util.c	2002/01/29 00:40:14
@@ -13,7 +13,8 @@
 #include "util.h"
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <asm/div64.h>		/* For do_div(). */
+#define USE_SLOW_64BIT_DIVIDES
+#include <linux/div64.h>		/* For do_div(). */
 #include "support.h"
 
 /*
@@ -233,7 +234,7 @@
 {
 	/* Subtract the NTFS time offset, then convert to 1s intervals. */
 	ntfs_time64_t t = ntutc - NTFS_TIME_OFFSET;
-	do_div(t, 10000000);
+	do_div(&t, 10000000);
 	return (ntfs_time_t)t;
 }
 
Index: fs/smbfs/proc.c
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/fs/smbfs/proc.c,v
retrieving revision 1.1
diff -u -r1.1 proc.c
--- fs/smbfs/proc.c	2001/11/30 22:28:58	1.1
+++ fs/smbfs/proc.c	2002/01/29 00:40:17
@@ -18,12 +18,14 @@
 #include <linux/dirent.h>
 #include <linux/nls.h>
 
+#define USE_SLOW_64BIT_DIVIDES
+#include <linux/div64.h>
+
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
 #include <linux/smb_mount.h>
 
 #include <asm/string.h>
-#include <asm/div64.h>
 
 #include "smb_debug.h"
 #include "proto.h"
@@ -375,7 +377,7 @@
 	/* FIXME: what about the timezone difference? */
 	/* Subtract the NTFS time offset, then convert to 1s intervals. */
 	u64 t = ntutc - NTFS_TIME_OFFSET;
-	do_div(t, 10000000);
+	do_div(&t, 10000000);
 	return (time_t)t;
 }
 
Index: lib/vsprintf.c
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/lib/vsprintf.c,v
retrieving revision 1.1
diff -u -r1.1 vsprintf.c
--- lib/vsprintf.c	2001/11/30 22:28:59	1.1
+++ lib/vsprintf.c	2002/01/29 00:40:24
@@ -19,9 +19,9 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/kernel.h>
+/* #define USE_SLOW_64BIT_DIVIDE */
+#include <linux/div64.h>
 
-#include <asm/div64.h>
-
 /**
  * simple_strtoul - convert a string to an unsigned long
  * @cp: The start of the string
@@ -165,7 +165,7 @@
 	if (num == 0)
 		tmp[i++]='0';
 	else while (num != 0)
-		tmp[i++] = digits[do_div(num,base)];
+		tmp[i++] = digits[do_div(&num,base)];
 	if (i > precision)
 		precision = i;
 	size -= precision;
@@ -426,22 +426,31 @@
 				}
 				continue;
 		}
-		if (qualifier == 'L')
+
+		switch (qualifier) {
+		case 'L':
 			num = va_arg(args, long long);
-		else if (qualifier == 'l') {
-			num = va_arg(args, unsigned long);
+			break;
+		case 'l':
 			if (flags & SIGN)
-				num = (signed long) num;
-		} else if (qualifier == 'Z') {
+				num = (signed long long) va_arg(args, long);
+			else
+				num = va_arg(args, unsigned long);
+			break;
+		case 'Z':
 			num = va_arg(args, size_t);
-		} else if (qualifier == 'h') {
-			num = (unsigned short) va_arg(args, int);
+			break;
+		case 'h':
 			if (flags & SIGN)
-				num = (signed short) num;
-		} else {
-			num = va_arg(args, unsigned int);
+				num = (signed long long) va_arg(args, int);
+			else
+				num = va_arg(args, unsigned int);
+			break;
+		default:
 			if (flags & SIGN)
-				num = (signed int) num;
+				num = (signed long long) va_arg(args, int);
+			else
+				num = va_arg(args, unsigned int);
 		}
 		str = number(str, end, num, base,
 				field_width, precision, flags);
Index: include/linux/div64.h
===================================================================
RCS file: /cvsdev/hhl-2.4.17/linux/include/linux/div64.h
diff -N div64.h
--- /dev/null	Tue May  5 13:32:27 1998
+++ include/linux/div64.h	Mon Jan 28 16:59:28 2002
@@ -0,0 +1,85 @@
+/*
+ * include/linux/div64.h
+ *
+ * Primarily used by vsprintf to divide a 64 bit int N by a small integer base
+ * We really do NOT want to encourage people to do slow 64 bit divides in
+ * the kernel, so the 'default' version of this function panics if you
+ * try and divide a 64 bit number by anything other than 8 or 16.
+ *
+ * If you really *really* need this, and are prepared to be flamed by 
+ * lkml, #define USE_SLOW_64BIT_DIVIDES before including this file.
+ */
+#ifndef __DIV64
+#define __DIV64
+
+#include <linux/config.h>
+
+/* configurable  */
+#undef __USE_ASM
+
+
+#ifdef __USE_ASM
+/* yeah, this is a mess, and leaves out m68k.... */
+# if defined(CONFIG_X86) || define(CONFIG_ARCH_S390) || defined(CONFIG_MIPS)
+#  define __USE_ASM__
+# endif
+#endif
+
+#ifdef __USE_ASM__
+#include <asm/div64.h>
+#else /* __USE_ASM__ */
+static inline int do_div(unsigned long long * n, unsigned long base)
+{
+	int res = 0;
+	unsigned long long t = *n;
+	if ( t == (unsigned long)t ){ /* this should handle 64 bit platforms */
+		res = ((unsigned long) t) % base;
+		t = ((unsigned long) t) / base;
+	} else {
+#ifndef USE_SLOW_64BIT_DIVIDES 
+		switch (base) {
+			case 8:
+				res = ((unsigned long) t & 0x7);
+				t = t >> 3;
+				break;
+			case 16:
+				res = ((unsigned long) t & 0xf);
+				t = t >> 4;
+				break;
+			default:
+				panic("do_div called with 64 bit arg and unsupported base\n", base);
+		}
+#else /* USE_SLOW_64BIT_DIVIDES */
+		/* this was stolen from the old asm-parisc/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 and HPPA
+		 */
+		unsigned long low, low2, high;
+		low  = (t) & 0xffffffff;
+		high = (t) >> 32;
+		res   = high % base;
+		high  = high / base;
+		low2  = low >> 16;
+		low2 += res << 16;
+		res   = low2 % base;
+		low2  = low2 / base;
+		low   = low & 0xffff;
+		low  += res << 16;
+		res   = low  % base;
+		low   = low  / base;
+		t = low  + ((long long)low2 << 16) +
+			((long long) high << 32);
+#endif  /* USE_SLOW_64BIT_DIVIDES */
+	}
+	*n = t;
+	return res;
+}
+
+
+#endif /* __USE_ASM__ */
+
+#endif

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

* Re: 64-bit divide cleanup (tested on ppc)
  2002-01-29  0:00   ` 64-bit divide cleanup (tested on ppc) Troy Benjegerdes
@ 2002-02-07 16:11     ` Gabriel Paubert
  0 siblings, 0 replies; 7+ messages in thread
From: Gabriel Paubert @ 2002-02-07 16:11 UTC (permalink / raw)
  To: Troy Benjegerdes; +Cc: linux-kernel

	Hi Troy,

sorry for the delay, I was sick :-(

Troy Benjegerdes wrote:

> Attached is a patch to get rid of asm/div64.h on arches that don't have 
> optimized asm routines.
> 
> I didn't include removeing the various arch/div64.h file yet, since I want 
> some comments on this.
> 
[snipped]
> ===================================================================
> RCS file: /cvsdev/hhl-2.4.17/linux/fs/ntfs/util.c,v
> retrieving revision 1.1
> diff -u -r1.1 util.c
> --- fs/ntfs/util.c	2001/11/30 22:28:59	1.1
> +++ fs/ntfs/util.c	2002/01/29 00:40:14
> @@ -13,7 +13,8 @@
>  #include "util.h"
>  #include <linux/string.h>
>  #include <linux/errno.h>
> -#include <asm/div64.h>		/* For do_div(). */
> +#define USE_SLOW_64BIT_DIVIDES
> +#include <linux/div64.h>		/* For do_div(). */
>  #include "support.h"
>  
>  /*
> @@ -233,7 +234,7 @@
>  {
>  	/* Subtract the NTFS time offset, then convert to 1s intervals. */
>  	ntfs_time64_t t = ntutc - NTFS_TIME_OFFSET;
> -	do_div(t, 10000000);
> +	do_div(&t, 10000000);
>  	return (ntfs_time_t)t;
>  }

>  
> Index: fs/smbfs/proc.c
> ===================================================================
> RCS file: /cvsdev/hhl-2.4.17/linux/fs/smbfs/proc.c,v
> retrieving revision 1.1
> diff -u -r1.1 proc.c
> --- fs/smbfs/proc.c	2001/11/30 22:28:58	1.1
> +++ fs/smbfs/proc.c	2002/01/29 00:40:17
> @@ -18,12 +18,14 @@
>  #include <linux/dirent.h>
>  #include <linux/nls.h>
>  
> +#define USE_SLOW_64BIT_DIVIDES
> +#include <linux/div64.h>
> +
>  #include <linux/smb_fs.h>
>  #include <linux/smbno.h>
>  #include <linux/smb_mount.h>
>  
>  #include <asm/string.h>
> -#include <asm/div64.h>
>  
>  #include "smb_debug.h"
>  #include "proto.h"
> @@ -375,7 +377,7 @@
>  	/* FIXME: what about the timezone difference? */
>  	/* Subtract the NTFS time offset, then convert to 1s intervals. */
>  	u64 t = ntutc - NTFS_TIME_OFFSET;
> -	do_div(t, 10000000);
> +	do_div(&t, 10000000);
>  	return (time_t)t;
>  }


At least for these 2, your patch is wrong. 10000000 is not especially 
small and the algorithm you propose does not work for these. It is 
limited to about 65536 actually.


>  
> Index: lib/vsprintf.c
> ===================================================================
> RCS file: /cvsdev/hhl-2.4.17/linux/lib/vsprintf.c,v
> retrieving revision 1.1
> diff -u -r1.1 vsprintf.c
> --- lib/vsprintf.c	2001/11/30 22:28:59	1.1
> +++ lib/vsprintf.c	2002/01/29 00:40:24
> @@ -19,9 +19,9 @@
>  #include <linux/string.h>
>  #include <linux/ctype.h>
>  #include <linux/kernel.h>
> +/* #define USE_SLOW_64BIT_DIVIDE */
> +#include <linux/div64.h>
>  
> -#include <asm/div64.h>
> -
>  /**
>   * simple_strtoul - convert a string to an unsigned long
>   * @cp: The start of the string
> @@ -165,7 +165,7 @@
>  	if (num == 0)
>  		tmp[i++]='0';
>  	else while (num != 0)
> -		tmp[i++] = digits[do_div(num,base)];
> +		tmp[i++] = digits[do_div(&num,base)];



Forcing to use slow do_div version even when base is 8 or 16 is not 
nice. Heck I believe that seperating it into several cases and having a 
different 2 or 3 distinct loops (one for base 10, the other or 2 others
for shifts by 3 or 4) could actually result in smaller code. On PPC and 
Alpha at lesat the compiler knows how to do a divide by 10 with a 
multiply high or however it's called instruction.

Oh, and what abour removing the if and doing a do {...} while(num!=0) 
instead ?


>  	if (i > precision)
>  		precision = i;
>  	size -= precision;
> @@ -426,22 +426,31 @@
>  				}
>  				continue;
>  		}
> -		if (qualifier == 'L')
> +
> +		switch (qualifier) {
> +		case 'L':
>  			num = va_arg(args, long long);
> -		else if (qualifier == 'l') {
> -			num = va_arg(args, unsigned long);
> +			break;
> +		case 'l':
>  			if (flags & SIGN)
> -				num = (signed long) num;
> -		} else if (qualifier == 'Z') {
> +				num = (signed long long) va_arg(args, long);
> +			else
> +				num = va_arg(args, unsigned long);
> +			break;
> +		case 'Z':
>  			num = va_arg(args, size_t);
> -		} else if (qualifier == 'h') {
> -			num = (unsigned short) va_arg(args, int);
> +			break;
> +		case 'h':
>  			if (flags & SIGN)
> -				num = (signed short) num;
> -		} else {
> -			num = va_arg(args, unsigned int);
> +				num = (signed long long) va_arg(args, int);
> +			else
> +				num = va_arg(args, unsigned int);
> +			break;
> +		default:
>  			if (flags & SIGN)
> -				num = (signed int) num;
> +				num = (signed long long) va_arg(args, int);
> +			else
> +				num = va_arg(args, unsigned int);
>  		}
>  		str = number(str, end, num, base,
>  				field_width, precision, flags);
> Index: include/linux/div64.h
> ===================================================================
> RCS file: /cvsdev/hhl-2.4.17/linux/include/linux/div64.h
> diff -N div64.h
> --- /dev/null	Tue May  5 13:32:27 1998
> +++ include/linux/div64.h	Mon Jan 28 16:59:28 2002
> @@ -0,0 +1,85 @@
> +/*
> + * include/linux/div64.h
> + *
> + * Primarily used by vsprintf to divide a 64 bit int N by a small integer base

                                                                ^^^^^
Read the comments, here goes you 10000000 factor. The modulo once 
shifted left by 16 bits can easily overflow.... Perhaps you should patch
it s/small/_small_/ to better see it.



> + * We really do NOT want to encourage people to do slow 64 bit divides in
> + * the kernel, so the 'default' version of this function panics if you
> + * try and divide a 64 bit number by anything other than 8 or 16.
> + *
> + * If you really *really* need this, and are prepared to be flamed by 
> + * lkml, #define USE_SLOW_64BIT_DIVIDES before including this file.
> + */
> +#ifndef __DIV64
> +#define __DIV64
> +
> +#include <linux/config.h>
> +
> +/* configurable  */
> +#undef __USE_ASM
> +
> +
> +#ifdef __USE_ASM
> +/* yeah, this is a mess, and leaves out m68k.... */
> +# if defined(CONFIG_X86) || define(CONFIG_ARCH_S390) || defined(CONFIG_MIPS)
> +#  define __USE_ASM__
> +# endif
> +#endif
> +
> +#ifdef __USE_ASM__
> +#include <asm/div64.h>
> +#else /* __USE_ASM__ */
> +static inline int do_div(unsigned long long * n, unsigned long base)
> +{
> +	int res = 0;
> +	unsigned long long t = *n;
> +	if ( t == (unsigned long)t ){ /* this should handle 64 bit platforms */
> +		res = ((unsigned long) t) % base;
> +		t = ((unsigned long) t) / base;
> +	} else {
> +#ifndef USE_SLOW_64BIT_DIVIDES 
> +		switch (base) {
> +			case 8:
> +				res = ((unsigned long) t & 0x7);
> +				t = t >> 3;
> +				break;
> +			case 16:
> +				res = ((unsigned long) t & 0xf);
> +				t = t >> 4;
> +				break;
> +			default:
> +				panic("do_div called with 64 bit arg and unsupported base\n", base);
> +		}
> +#else /* USE_SLOW_64BIT_DIVIDES */
> +		/* this was stolen from the old asm-parisc/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 


s/small/_small_/ just to be sure that the comment is understood.

For the 10000000 case, I believe a simple stupid looping algorithm is 
the only solution which does not result in code size explosion.

	Regards,
	Gabriel.


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

end of thread, other threads:[~2002-02-07 16:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-01-25 19:34 [PATCH] 64-bit divide tweaks Momchil Velikov
2002-01-25 19:40 ` Jeff Garzik
2002-01-25 21:50   ` Tim Schmielau
2002-01-27 18:04 ` Troy Benjegerdes
2002-01-27 18:51 ` Matti Aarnio
2002-01-29  0:00   ` 64-bit divide cleanup (tested on ppc) Troy Benjegerdes
2002-02-07 16:11     ` Gabriel Paubert

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