kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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
> 


  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).