On Mon, Oct 14, 2013 at 06:23:33PM +0200, Andrew Jones wrote: > arm can't do arbitrary divisions without software support. Usually > libgcc would jump in here, but depending on the toolchain used that may > or may not work. Luckily, we only care about two types of divisions. > Divide by 10 and divide by 16. Divide by 16 is already covered by gcc > since it's a power of two. Divide by 10 can be hacked up using a > multiplication and shift. Isn't this just a matter of supplying a few libc implementations to handle div_by_0 and that sort? I'm pretty sure we had that working in the kvm-selftest for ARM thingy that allowed you to use the standard '/' operator in C code.... I suspect there will be more users of this eventually. Or wait, do you mean 'long long' operations by arbitrary? In that case, I'm less sure... A library implementation to support the operator would still be preferred IMHO. > > Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx> > --- > lib/divmod.h | 20 ++++++++++++++++++++ > lib/printf.c | 27 ++++++++++++++------------- > 2 files changed, 34 insertions(+), 13 deletions(-) > create mode 100644 lib/divmod.h > > diff --git a/lib/divmod.h b/lib/divmod.h > new file mode 100644 > index 0000000000000..c0f04d7d8386d > --- /dev/null > +++ b/lib/divmod.h > @@ -0,0 +1,20 @@ > +#ifndef _DIVMOD_H_ > +#define _DIVMOD_H_ > +#ifdef __arm__ > +static inline long long div10(long long n) > +{ > + /* > + * multiply n by 2^32/10 and the result of n/10 > + * will be in the upper word > + */ > + return (n * 0x1999999aU) >> 32; > +} > +static inline int mod10(long long n) > +{ > + return n - div10(n) * 10; > +} > +#else > +#define div10(n) ((n) / 10) > +#define mod10(n) ((n) % 10) > +#endif > +#endif > diff --git a/lib/printf.c b/lib/printf.c > index 867eb1926f742..9fb8133868c7a 100644 > --- a/lib/printf.c > +++ b/lib/printf.c > @@ -1,4 +1,5 @@ > #include "libcflat.h" > +#include "divmod.h" > > typedef struct pstream { > char *buffer; > @@ -23,7 +24,7 @@ void print_str(pstream_t *p, const char *s) > > static char digits[16] = "0123456789abcdef"; > > -void print_int(pstream_t *ps, long long n, int base) > +void print_int(pstream_t *ps, long long n) > { > char buf[sizeof(long) * 3 + 2], *p = buf; > int s = 0, i; > @@ -34,8 +35,8 @@ void print_int(pstream_t *ps, long long n, int base) > } > > while (n) { > - *p++ = digits[n % base]; > - n /= base; > + *p++ = digits[mod10(n)]; > + n = div10(n); > } > > if (s) > @@ -57,14 +58,14 @@ void print_int(pstream_t *ps, long long n, int base) > print_str(ps, buf); > } > > -void print_unsigned(pstream_t *ps, unsigned long long n, int base) > +void print_unsigned(pstream_t *ps, unsigned long long n) > { > char buf[sizeof(long) * 3 + 1], *p = buf; > int i; > > while (n) { > - *p++ = digits[n % base]; > - n /= base; > + *p++ = digits[n % 16]; > + n /= 16; > } > > if (p == buf) > @@ -116,32 +117,32 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) > case 'd': > switch (nlong) { > case 0: > - print_int(&s, va_arg(va, int), 10); > + print_int(&s, va_arg(va, int)); > break; > case 1: > - print_int(&s, va_arg(va, long), 10); > + print_int(&s, va_arg(va, long)); > break; > default: > - print_int(&s, va_arg(va, long long), 10); > + print_int(&s, va_arg(va, long long)); > break; > } > break; > case 'x': > switch (nlong) { > case 0: > - print_unsigned(&s, va_arg(va, unsigned), 16); > + print_unsigned(&s, va_arg(va, unsigned)); > break; > case 1: > - print_unsigned(&s, va_arg(va, unsigned long), 16); > + print_unsigned(&s, va_arg(va, unsigned long)); > break; > default: > - print_unsigned(&s, va_arg(va, unsigned long long), 16); > + print_unsigned(&s, va_arg(va, unsigned long long)); > break; > } > break; > case 'p': > print_str(&s, "0x"); > - print_unsigned(&s, (unsigned long)va_arg(va, void *), 16); > + print_unsigned(&s, (unsigned long)va_arg(va, void *)); > break; > case 's': > print_str(&s, va_arg(va, const char *)); > -- > 1.8.1.4 > -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html