Blame view

lib/div64.c 1.17 KB
7b64fef33   Wolfgang Denk   Add AVR32 archite...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
   *
   * Based on former do_div() implementation from asm-parisc/div64.h:
   *	Copyright (C) 1999 Hewlett-Packard Co
   *	Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
   *
   *
   * Generic C version of 64bit/32bit division and modulo, with
   * 64bit result and 32bit remainder.
   *
   * The fast case for (n>>32 == 0) is handled inline by do_div().
   *
   * Code generated for this function might be very inefficient
   * for some CPUs. __div64_32() can be overridden by linking arch-specific
a47a12bec   Stefan Roese   Move arch/ppc to ...
16
   * assembly versions such as arch/powerpc/lib/div64.S and arch/sh/lib/div64.S.
7b64fef33   Wolfgang Denk   Add AVR32 archite...
17
   */
e259d6a32   Jeroen Hofstee   lib: div64: add m...
18
  #include <div64.h>
7b64fef33   Wolfgang Denk   Add AVR32 archite...
19
  #include <linux/types.h>
83cc112e8   Simon Glass   lib: Don't instru...
20
  #include <linux/compiler.h>
7b64fef33   Wolfgang Denk   Add AVR32 archite...
21

83cc112e8   Simon Glass   lib: Don't instru...
22
  uint32_t notrace __div64_32(uint64_t *n, uint32_t base)
7b64fef33   Wolfgang Denk   Add AVR32 archite...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  {
  	uint64_t rem = *n;
  	uint64_t b = base;
  	uint64_t res, d = 1;
  	uint32_t high = rem >> 32;
  
  	/* Reduce the thing a bit first */
  	res = 0;
  	if (high >= base) {
  		high /= base;
  		res = (uint64_t) high << 32;
  		rem -= (uint64_t) (high*base) << 32;
  	}
  
  	while ((int64_t)b > 0 && b < rem) {
  		b = b+b;
  		d = d+d;
  	}
  
  	do {
  		if (rem >= b) {
  			rem -= b;
  			res += d;
  		}
  		b >>= 1;
  		d >>= 1;
  	} while (d);
  
  	*n = res;
  	return rem;
  }