* [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