Commit 205d324e authored by Alessandro Rubini's avatar Alessandro Rubini Committed by Aurelio Colosimo

lib/div64.c: new file

This is the 64-bit unsigned division and remainder from the Linux
kernel, for 32-bit host systems.

The new lib/ directory can be used by archs to pick files, and that's
already exemplified by arch-gnu-linux and arch-bare-linux.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 1ccf1d9e
......@@ -12,7 +12,8 @@ OBJ-libarch := $A/bare-startup.o \
$A/main-loop.o \
$A/bare-socket.o \
$A/bare-io.o \
$A/syscalls.o
$A/syscalls.o \
lib/div64.o
$(LIBARCH): $(OBJ-libarch)
$(AR) r $@ $^
......
......@@ -10,6 +10,7 @@ OBJ-libarch := $A/posix-startup.o \
$A/posix-socket.o \
$A/posix-io.o \
$A/posix-timer.o \
lib/div64.o
$(LIBARCH): $(OBJ-libarch)
$(AR) r $@ $^
......
......@@ -3,6 +3,7 @@
*/
#ifndef __PTP_LIB_H__
#define __PTP_LIB_H__
#include <stdint.h>
/* We base on puts and a few more functions: each arch must have it */
extern void pp_puts(const char *s);
......@@ -11,4 +12,6 @@ extern void *pp_memcpy(void *d, const void *s, int count);
extern int pp_memcmp(const void *s1, const void *s2, int count);
extern void *pp_memset(void *s, int c, int count);
extern uint32_t __div64_32(uint64_t *n, uint32_t base);
#endif /* __PTP_DEP_H__ */
/* This file in pptp is a subset of lib/div64.c in Linux source code */
/*
* 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
* assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
*/
#include <pptp/lib.h>
uint32_t __div64_32(uint64_t *n, uint32_t base)
{
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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment