From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Schwierzeck Date: Sat, 26 Dec 2015 14:09:16 +0100 Subject: [U-Boot] [PATCH v4 1/8] include: Add support for "do_div" macro In-Reply-To: References: <1451069788-6786-1-git-send-email-wills.wang@live.com> Message-ID: <567E917C.4030304@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Am 25.12.2015 um 19:56 schrieb Wills Wang: > Use the div64 header files from the kernel. > > Signed-off-by: Wills Wang > --- > > Changes in v4: None > Changes in v3: None > Changes in v2: None > > arch/mips/include/asm/div64.h | 68 +++++++++++++++++++++++++++++++++++++++++++ > include/asm-generic/div64.h | 59 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 127 insertions(+) > create mode 100644 arch/mips/include/asm/div64.h > create mode 100644 include/asm-generic/div64.h please drop this patch, we already have a generic do_div() implementation. Also we do not really need an assembly optimized implementation for MIPS. > > diff --git a/arch/mips/include/asm/div64.h b/arch/mips/include/asm/div64.h > new file mode 100644 > index 0000000..e5e6782 > --- /dev/null > +++ b/arch/mips/include/asm/div64.h > @@ -0,0 +1,68 @@ > +/* > + * Copyright (C) 2000, 2004 Maciej W. Rozycki > + * Copyright (C) 2003, 07 Ralf Baechle (ralf at linux-mips.org) > + * > + * 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 > + > +#include > + > +#if BITS_PER_LONG == 64 > + > +#include > + > +/* > + * No traps on overflows for any of these... > + */ > + > +#define __div64_32(n, base) \ > +({ \ > + unsigned long __cf, __tmp, __tmp2, __i; \ > + unsigned long __quot32, __mod32; \ > + unsigned long __high, __low; \ > + unsigned long long __n; \ > + \ > + __high = *__n >> 32; \ > + __low = __n; \ > + __asm__( \ > + " .set push\n" \ > + " .set noat\n" \ > + " .set noreorder\n" \ > + " move %2, $0\n" \ > + " move %3, $0\n" \ > + " b 1f\n" \ > + " li %4, 0x21\n" \ > + "0:\n" \ > + " sll $1, %0, 0x1\n" \ > + " srl %3, %0, 0x1f\n" \ > + " or %0, $1, %5\n" \ > + " sll %1, %1, 0x1\n" \ > + " sll %2, %2, 0x1\n" \ > + "1:\n" \ > + " bnez %3, 2f\n" \ > + " sltu %5, %0, %z6\n" \ > + " bnez %5, 3f\n" \ > + "2:\n" \ > + " addiu %4, %4, -1\n" \ > + " subu %0, %0, %z6\n" \ > + " addiu %2, %2, 1\n" \ > + "3:\n" \ > + " bnez %4, 0b\n\t" \ > + " srl %5, %1, 0x1f\n\t" \ > + " .set pop" \ > + : "=&r" (__mod32), "=&r" (__tmp), \ > + "=&r" (__quot32), "=&r" (__cf), \ > + "=&r" (__i), "=&r" (__tmp2) \ > + : "Jr" (base), "0" (__high), "1" (__low)); \ > + \ > + (__n) = __quot32; \ > + __mod32; \ > +}) > + > +#endif /* BITS_PER_LONG == 64 */ > + > +#endif /* __ASM_DIV64_H */ > diff --git a/include/asm-generic/div64.h b/include/asm-generic/div64.h > new file mode 100644 > index 0000000..d689fc4 > --- /dev/null > +++ b/include/asm-generic/div64.h > @@ -0,0 +1,59 @@ > +/* > + * Copyright (C) 2003 Bernardo Innocenti > + * 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! > + */ > + > +#ifndef _ASM_GENERIC_DIV64_H > +#define _ASM_GENERIC_DIV64_H > + > +#include > +#include > + > +#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); > + > +/* The unnecessary pointer compare is there > + * to check for type safety (n must be 64bit) > + */ > +# define do_div(n, base) ({ \ > + uint32_t __base = (base); \ > + uint32_t __rem; \ > + (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ > + 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 */ > -- - Daniel