From: Paolo Bonzini <pbonzini@redhat.com>
To: kvm@vger.kernel.org
Cc: Bill Wendling <morbo@google.com>
Subject: Re: [PATCH kvm-unit-tests] libcflat: provide long division routines
Date: Wed, 5 May 2021 15:16:03 +0200 [thread overview]
Message-ID: <941e5f21-7d0b-2e67-21d1-3c425a43f489@redhat.com> (raw)
In-Reply-To: <20210505131412.654238-1-pbonzini@redhat.com>
On 05/05/21 15:14, Paolo Bonzini wrote:
> The -nostdlib flag disables the driver from adding libclang_rt.*.a
> during linking. Adding a specific library to the command line such as
> libgcc then causes the linker to report unresolved symbols, because the
> libraries that resolve those symbols aren't automatically added.
>
> libgcc however is only needed for long division (64-bit by 64-bit).
> Instead of linking the whole of it, implement the routines that are
> needed.
>
> Reported-by: Bill Wendling <morbo@google.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Oops, I didn't actually remove libgcc!
diff --git a/Makefile b/Makefile
index 24b7917..ddebcae 100644
--- a/Makefile
+++ b/Makefile
@@ -25,8 +25,6 @@ cc-option = $(shell if $(CC) -Werror $(1) -S -o /dev/null -xc /dev/null \
#make sure env CFLAGS variable is not used
CFLAGS =
-libgcc := $(shell $(CC) --print-libgcc-file-name)
-
libcflat := lib/libcflat.a
cflatobjs := \
lib/argv.o \
diff --git a/arm/Makefile.common b/arm/Makefile.common
index 55478ec..38385e0 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -58,9 +58,7 @@ OBJDIRS += lib/arm
libeabi = lib/arm/libeabi.a
eabiobjs = lib/arm/eabi_compat.o
-libgcc := $(shell $(CC) $(machine) --print-libgcc-file-name)
-
-FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libgcc) $(libeabi)
+FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libeabi)
%.elf: LDFLAGS = -nostdlib $(arch_LDFLAGS)
%.elf: %.o $(FLATLIBS) $(SRCDIR)/arm/flat.lds $(cstart.o)
$(CC) $(CFLAGS) -c -o $(@:.elf=.aux.o) $(SRCDIR)/lib/auxinfo.c \
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 55f7f28..52bb7aa 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -37,12 +37,10 @@ COMMON_CFLAGS += -O1
# stack.o relies on frame pointers.
KEEP_FRAME_POINTER := y
-libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name)
-
# We want to keep intermediate file: %.elf and %.o
.PRECIOUS: %.elf %.o
-FLATLIBS = lib/libcflat.a $(libgcc)
+FLATLIBS = lib/libcflat.a
%.elf: %.o $(FLATLIBS) $(SRCDIR)/x86/flat.lds $(cstart.o)
$(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,$(SRCDIR)/x86/flat.lds \
$(filter %.o, $^) $(FLATLIBS)
> ---
> arm/Makefile.arm | 1 +
> lib/ldiv32.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++
> x86/Makefile.i386 | 2 +-
> 3 files changed, 107 insertions(+), 1 deletion(-)
> create mode 100644 lib/ldiv32.c
>
> diff --git a/arm/Makefile.arm b/arm/Makefile.arm
> index d379a28..687a8ed 100644
> --- a/arm/Makefile.arm
> +++ b/arm/Makefile.arm
> @@ -23,6 +23,7 @@ cstart.o = $(TEST_DIR)/cstart.o
> cflatobjs += lib/arm/spinlock.o
> cflatobjs += lib/arm/processor.o
> cflatobjs += lib/arm/stack.o
> +cflatobjs += lib/ldiv32.o
>
> # arm specific tests
> tests =
> diff --git a/lib/ldiv32.c b/lib/ldiv32.c
> new file mode 100644
> index 0000000..e9d434f
> --- /dev/null
> +++ b/lib/ldiv32.c
> @@ -0,0 +1,105 @@
> +#include <inttypes.h>
> +
> +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *p_rem);
> +extern int64_t __moddi3(int64_t num, int64_t den);
> +extern int64_t __divdi3(int64_t num, int64_t den);
> +extern uint64_t __udivdi3(uint64_t num, uint64_t den);
> +extern uint64_t __umoddi3(uint64_t num, uint64_t den);
> +
> +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *p_rem)
> +{
> + uint64_t quot = 0;
> +
> + /* Trigger a division by zero at run time (trick taken from iPXE). */
> + if (den == 0)
> + return 1/((unsigned)den);
> +
> + if (num >= den) {
> + /* Align den to num to avoid wasting time on leftmost zero bits. */
> + int n = __builtin_clzll(den) - __builtin_clzll(num);
> + den <<= n;
> +
> + do {
> + quot <<= 1;
> + if (num >= den) {
> + num -= den;
> + quot |= 1;
> + }
> + den >>= 1;
> + } while (n--);
> + }
> +
> + if (p_rem)
> + *p_rem = num;
> +
> + return quot;
> +}
> +
> +int64_t __moddi3(int64_t num, int64_t den)
> +{
> + uint64_t mask = num < 0 ? -1 : 0;
> +
> + /* Compute absolute values and do an unsigned division. */
> + num = (num + mask) ^ mask;
> + if (den < 0)
> + den = -den;
> +
> + /* Copy sign of num into result. */
> + return (__umoddi3(num, den) + mask) ^ mask;
> +}
> +
> +int64_t __divdi3(int64_t num, int64_t den)
> +{
> + uint64_t mask = (num ^ den) < 0 ? -1 : 0;
> +
> + /* Compute absolute values and do an unsigned division. */
> + if (num < 0)
> + num = -num;
> + if (den < 0)
> + den = -den;
> +
> + /* Copy sign of num^den into result. */
> + return (__udivdi3(num, den) + mask) ^ mask;
> +}
> +
> +uint64_t __udivdi3(uint64_t num, uint64_t den)
> +{
> + uint64_t rem;
> + return __udivmoddi4(num, den, &rem);
> +}
> +
> +uint64_t __umoddi3(uint64_t num, uint64_t den)
> +{
> + uint64_t rem;
> + __udivmoddi4(num, den, &rem);
> + return rem;
> +}
> +
> +#ifdef TEST
> +#include <assert.h>
> +#define UTEST(a, b, q, r) assert(__udivdi3(a, b) == q && __umoddi3(a, b) == r)
> +#define STEST(a, b, q, r) assert(__divdi3(a, b) == q && __moddi3(a, b) == r)
> +int main()
> +{
> + UTEST(1, 1, 1, 0);
> + UTEST(2, 2, 1, 0);
> + UTEST(5, 3, 1, 2);
> + UTEST(10, 3, 3, 1);
> + UTEST(120, 3, 40, 0);
> + UTEST(120, 1, 120, 0);
> + UTEST(0x7FFFFFFFFFFFFFFFULL, 17, 0x787878787878787, 8);
> + UTEST(0x7FFFFFFFFFFFFFFFULL, 0x787878787878787, 17, 8);
> + UTEST(0x8000000000000001ULL, 17, 0x787878787878787, 10);
> + UTEST(0x8000000000000001ULL, 0x787878787878787, 17, 10);
> + UTEST(0, 5, 0, 0);
> +
> + STEST(0x7FFFFFFFFFFFFFFFULL, 17, 0x787878787878787, 8);
> + STEST(0x7FFFFFFFFFFFFFFFULL, -17, -0x787878787878787, 8);
> + STEST(-0x7FFFFFFFFFFFFFFFULL, 17, -0x787878787878787, -8);
> + STEST(-0x7FFFFFFFFFFFFFFFULL, -17, 0x787878787878787, -8);
> + STEST(33, 5, 6, 3);
> + STEST(33, -5, -6, 3);
> + STEST(-33, 5, -6, -3);
> + STEST(-33, -5, 6, -3);
> +}
> +#endif
> diff --git a/x86/Makefile.i386 b/x86/Makefile.i386
> index c04e5aa..960e274 100644
> --- a/x86/Makefile.i386
> +++ b/x86/Makefile.i386
> @@ -3,7 +3,7 @@ bits = 32
> ldarch = elf32-i386
> COMMON_CFLAGS += -mno-sse -mno-sse2
>
> -cflatobjs += lib/x86/setjmp32.o
> +cflatobjs += lib/x86/setjmp32.o lib/ldiv32.o
>
> tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat \
> $(TEST_DIR)/cmpxchg8b.flat $(TEST_DIR)/la57.flat
>
next prev parent reply other threads:[~2021-05-05 13:16 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-05 13:14 [PATCH kvm-unit-tests] libcflat: provide long division routines Paolo Bonzini
2021-05-05 13:16 ` Paolo Bonzini [this message]
2021-05-05 19:46 ` Bill Wendling
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=941e5f21-7d0b-2e67-21d1-3c425a43f489@redhat.com \
--to=pbonzini@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=morbo@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).