From: Florent Kermarrec Date: Wed, 10 Jun 2020 05:47:21 +0000 (+0200) Subject: libase/progress: move __div64_32, do_div to div64.h/c as it was in Barebox. X-Git-Tag: 24jan2021_ls180~202 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=99f40fecaab7599d8c9c658f1cbf41ae5f80a6a7;p=litex.git libase/progress: move __div64_32, do_div to div64.h/c as it was in Barebox. --- diff --git a/litex/soc/software/bios/boot.c b/litex/soc/software/bios/boot.c index 786039f0..20953e71 100644 --- a/litex/soc/software/bios/boot.c +++ b/litex/soc/software/bios/boot.c @@ -23,6 +23,7 @@ #include "sfl.h" #include "boot.h" +#include #include #include diff --git a/litex/soc/software/include/base/div64.h b/litex/soc/software/include/base/div64.h new file mode 100644 index 00000000..2f075474 --- /dev/null +++ b/litex/soc/software/include/base/div64.h @@ -0,0 +1,39 @@ +#ifndef _ASM_GENERIC_DIV64_H +#define _ASM_GENERIC_DIV64_H +/* + * 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! + */ + +#include + +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 (((n) >> 32) == 0) { \ + __rem = (uint32_t)(n) % __base; \ + (n) = (uint32_t)(n) / __base; \ + } else \ + __rem = __div64_32(&(n), __base); \ + __rem; \ + }) + +#endif /* _ASM_GENERIC_DIV64_H */ diff --git a/litex/soc/software/libbase/Makefile b/litex/soc/software/libbase/Makefile index 107c8736..5974e000 100755 --- a/litex/soc/software/libbase/Makefile +++ b/litex/soc/software/libbase/Makefile @@ -3,7 +3,7 @@ include $(SOC_DIRECTORY)/software/common.mak OBJECTS = exception.o libc.o errno.o crc16.o crc32.o console.o \ system.o id.o uart.o time.o qsort.o strtod.o spiflash.o strcasecmp.o i2c.o \ - progress.o + div64.o progress.o all: crt0-ctr.o crt0-xip.o libbase.a libbase-nofloat.a diff --git a/litex/soc/software/libbase/div64.c b/litex/soc/software/libbase/div64.c new file mode 100644 index 00000000..98d77480 --- /dev/null +++ b/litex/soc/software/libbase/div64.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2003 Bernardo Innocenti + * + * Based on former do_div() implementation from asm-parisc/div64.h: + * Copyright (C) 1999 Hewlett-Packard Co + * Copyright (C) 1999 David Mosberger-Tang + * + * + * 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 + +#include + +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; +} diff --git a/litex/soc/software/libbase/progress.c b/litex/soc/software/libbase/progress.c index c13b2dad..d8521fce 100644 --- a/litex/soc/software/libbase/progress.c +++ b/litex/soc/software/libbase/progress.c @@ -20,6 +20,8 @@ #include #include #include + +#include #include #define FILESIZE_MAX 100000000 @@ -29,56 +31,6 @@ static int printed; static int progress_max; static int spin; -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; -} - - -/* 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 (((n) >> 32) == 0) { \ - __rem = (uint32_t)(n) % __base; \ - (n) = (uint32_t)(n) / __base; \ - } else \ - __rem = __div64_32(&(n), __base); \ - __rem; \ - }) - - void show_progress(int now) { char spinchr[] = "\\|/-";