public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] bring sanity to div64.h and do_div usage
@ 2002-02-08  5:45 Troy Benjegerdes
  2002-02-08 12:15 ` Anton Altaparmakov
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Troy Benjegerdes @ 2002-02-08  5:45 UTC (permalink / raw)
  To: wli, torvalds, linux-kernel

This patch introduced include/linux/div64.h and removes asm/div64.h from
all the architectures that don't have optimized ASM.

I also played janitor and found every file that used asm/div64.h. There 
was some mips stuff that I didn't touch, but now everything else should 
actually work on all platforms linux supports, instead of just those that 
are either 64 bit, or have optimized asm versions.

(This patch is against 2.4.17, please let me know if it does not apply to 
current 2.4 or 2.5)

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/02/08 05:32:48
@@ -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/02/08 05:32:57
@@ -43,6 +43,8 @@
  ******************************************************************************/
 
 #include <linux/proc_fs.h>
+#define USE_SLOW_64BIT_DIVIDES
+#include <linux/div64.h>
 
 #include "h/skdrv1st.h"
 #include "h/skdrv2nd.h"
@@ -296,60 +298,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 +346,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/02/08 05:33:02
@@ -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/02/08 05:33:03
@@ -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/02/08 05:33:04
@@ -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/02/08 05:33:05
@@ -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/02/08 05:33:07
@@ -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: include/asm-alpha/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvs9lkcGH	Thu Feb  7 21:33:39 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,14 +0,0 @@
-#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
Index: include/asm-arm/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvs6NHMn8	Thu Feb  7 21:33:39 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,14 +0,0 @@
-#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
-
Index: include/asm-cris/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvsA6IpzQ	Thu Feb  7 21:33:40 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,16 +0,0 @@
-#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
-
Index: include/asm-ia64/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvsKee8nJ	Thu Feb  7 21:33:40 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,20 +0,0 @@
-#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 */
Index: include/asm-mips64/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvstklJ6k	Thu Feb  7 21:33:41 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,19 +0,0 @@
-/*
- * 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 */
Index: include/asm-parisc/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvsUOPlWi	Thu Feb  7 21:33:41 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,54 +0,0 @@
-#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
-
Index: include/asm-ppc/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvs3bbXXn	Thu Feb  7 21:33:41 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,13 +0,0 @@
-/*
- * BK Id: SCCS/s.div64.h 1.5 05/17/01 18:14:24 cort
- */
-#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; })
-
-#endif
Index: include/asm-s390x/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvsxz2zsC	Thu Feb  7 21:33:42 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,10 +0,0 @@
-#ifndef __S390_DIV64
-#define __S390_DIV64
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
-#endif
Index: include/asm-sh/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvsLubD1X	Thu Feb  7 21:33:42 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,10 +0,0 @@
-#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 */
Index: include/asm-sparc/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvsdjFoKq	Thu Feb  7 21:33:42 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,11 +0,0 @@
-#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 */
Index: include/asm-sparc64/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /tmp/cvsBXaTu3	Thu Feb  7 21:33:42 2002
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,14 +0,0 @@
-#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 */
Index: include/linux/div64.h
===================================================================
RCS file: div64.h
diff -N div64.h
--- /dev/null	Tue May  5 13:32:27 1998
+++ div64.h	Thu Feb  7 21:33:12 2002
@@ -0,0 +1,81 @@
+/*
+ * 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 */
+		/*
+		 * Nasty ugly generic C 64 bit divide on 32 bit machine
+		 * No one seems to want to take credit for this
+		 */
+		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
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/02/08 05:33:15
@@ -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);

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

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

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-02-08  5:45 [PATCH] bring sanity to div64.h and do_div usage Troy Benjegerdes
2002-02-08 12:15 ` Anton Altaparmakov
2002-02-08 17:57   ` Troy Benjegerdes
2002-02-08 18:49     ` Maciej W. Rozycki
2002-02-08 19:34   ` Anton Altaparmakov
2002-02-08 21:16     ` Troy Benjegerdes
2002-02-15 18:47     ` Updated div64.h cleanup Troy Benjegerdes
2002-02-22 14:59     ` [PATCH] bring sanity to div64.h and do_div usage Jes Sorensen
2002-02-22 15:17       ` Jeff Garzik
2002-02-22 15:20         ` Jes Sorensen
2002-02-22 15:26           ` Jeff Garzik
2002-02-22 15:34             ` Jes Sorensen
2002-02-22 16:05               ` Jeff Garzik
2002-02-22 15:55             ` Andreas Schwab
2002-02-22 16:00               ` Jeff Garzik
2002-02-22 16:08           ` Nicolas Pitre
2002-02-08 12:29 ` Anton Altaparmakov
2002-02-08 19:04 ` Roman Zippel

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