Re: [PATCH kvm-unit-tests] libcflat: provide long division routines

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 5, 2021 at 6:16 AM Paolo Bonzini <pbonzini@xxxxxxxxxx> wrote:
>
> 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@xxxxxxxxxx>
> > Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
>
Thanks, Paolo!

-bw

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



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux