From patchwork Mon Oct 14 16:23:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jones X-Patchwork-Id: 3037681 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1E109BF924 for ; Mon, 14 Oct 2013 16:24:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2648B2020E for ; Mon, 14 Oct 2013 16:24:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 45A3E20212 for ; Mon, 14 Oct 2013 16:24:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757088Ab3JNQYL (ORCPT ); Mon, 14 Oct 2013 12:24:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:1957 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755633Ab3JNQYK (ORCPT ); Mon, 14 Oct 2013 12:24:10 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r9EGNrrg019691 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 14 Oct 2013 12:23:53 -0400 Received: from hawk.usersys.redhat.com.com (vpn1-6-144.ams2.redhat.com [10.36.6.144]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r9EGNbv1017054; Mon, 14 Oct 2013 12:23:51 -0400 From: Andrew Jones To: kvm@vger.kernel.org Cc: kvmarm@lists.cs.columbia.edu, gleb@redhat.com, christoffer.dall@linaro.org Subject: [PATCH 7/9] arm: replace arbitrary divisions Date: Mon, 14 Oct 2013 18:23:33 +0200 Message-Id: <1381767815-12510-8-git-send-email-drjones@redhat.com> In-Reply-To: <1381767815-12510-1-git-send-email-drjones@redhat.com> References: <1381767815-12510-1-git-send-email-drjones@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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. Signed-off-by: Andrew Jones --- 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 *));