1*78acc472SPeter Tyser /* 2*78acc472SPeter Tyser * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com> 3*78acc472SPeter Tyser * 4*78acc472SPeter Tyser * Based on former do_div() implementation from asm-parisc/div64.h: 5*78acc472SPeter Tyser * Copyright (C) 1999 Hewlett-Packard Co 6*78acc472SPeter Tyser * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com> 7*78acc472SPeter Tyser * 8*78acc472SPeter Tyser * 9*78acc472SPeter Tyser * Generic C version of 64bit/32bit division and modulo, with 10*78acc472SPeter Tyser * 64bit result and 32bit remainder. 11*78acc472SPeter Tyser * 12*78acc472SPeter Tyser * The fast case for (n>>32 == 0) is handled inline by do_div(). 13*78acc472SPeter Tyser * 14*78acc472SPeter Tyser * Code generated for this function might be very inefficient 15*78acc472SPeter Tyser * for some CPUs. __div64_32() can be overridden by linking arch-specific 16*78acc472SPeter Tyser * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S. 17*78acc472SPeter Tyser */ 18*78acc472SPeter Tyser 19*78acc472SPeter Tyser #include <linux/types.h> 20*78acc472SPeter Tyser 21*78acc472SPeter Tyser uint32_t __div64_32(uint64_t *n, uint32_t base) 22*78acc472SPeter Tyser { 23*78acc472SPeter Tyser uint64_t rem = *n; 24*78acc472SPeter Tyser uint64_t b = base; 25*78acc472SPeter Tyser uint64_t res, d = 1; 26*78acc472SPeter Tyser uint32_t high = rem >> 32; 27*78acc472SPeter Tyser 28*78acc472SPeter Tyser /* Reduce the thing a bit first */ 29*78acc472SPeter Tyser res = 0; 30*78acc472SPeter Tyser if (high >= base) { 31*78acc472SPeter Tyser high /= base; 32*78acc472SPeter Tyser res = (uint64_t) high << 32; 33*78acc472SPeter Tyser rem -= (uint64_t) (high*base) << 32; 34*78acc472SPeter Tyser } 35*78acc472SPeter Tyser 36*78acc472SPeter Tyser while ((int64_t)b > 0 && b < rem) { 37*78acc472SPeter Tyser b = b+b; 38*78acc472SPeter Tyser d = d+d; 39*78acc472SPeter Tyser } 40*78acc472SPeter Tyser 41*78acc472SPeter Tyser do { 42*78acc472SPeter Tyser if (rem >= b) { 43*78acc472SPeter Tyser rem -= b; 44*78acc472SPeter Tyser res += d; 45*78acc472SPeter Tyser } 46*78acc472SPeter Tyser b >>= 1; 47*78acc472SPeter Tyser d >>= 1; 48*78acc472SPeter Tyser } while (d); 49*78acc472SPeter Tyser 50*78acc472SPeter Tyser *n = res; 51*78acc472SPeter Tyser return rem; 52*78acc472SPeter Tyser } 53