[U-Boot] [PATCH v2] x86: lib: Implement standalone __udivdi3 etc instead of libgcc ones

Stefan Roese sr at denx.de
Mon Nov 20 10:43:42 UTC 2017


Hi Bin,

On 20.11.2017 08:24, Bin Meng wrote:
> On Fri, Nov 17, 2017 at 2:02 PM, Stefan Roese <sr at denx.de> wrote:
>> This patch removes the inclusion of the libgcc math functions and
>> replaces them by functions coded in C, taken from the coreboot
>> project. This makes U-Boot building more independent from the toolchain
>> installed / available on the build system.
>>
>> The code taken from coreboot is authored from Vadim Bendebury
>> <vbendeb at chromium.org> on 2014-11-28 and committed with commit
>> ID e63990ef [libpayload: provide basic 64bit division implementation]
>> (coreboot git repository located here [1]).
>>
>> I modified the code so that its checkpatch clean without any
>> functional changes.
>>
>> [1] git://github.com/coreboot/coreboot.git
>>
>> Signed-off-by: Stefan Roese <sr at denx.de>
>> Cc: Simon Glass <sjg at chromium.org>
>> Cc: Bin Meng <bmeng.cn at gmail.com>
>> ---
>> v2:
>> - Added coreboot git repository link to commit message
>>
>>   arch/x86/config.mk    |   3 --
>>   arch/x86/lib/Makefile |   2 +-
>>   arch/x86/lib/div64.c  | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>   arch/x86/lib/gcc.c    |  29 -------------
>>   4 files changed, 114 insertions(+), 33 deletions(-)
>>   create mode 100644 arch/x86/lib/div64.c
>>   delete mode 100644 arch/x86/lib/gcc.c
>>
>> diff --git a/arch/x86/config.mk b/arch/x86/config.mk
>> index 8835dcf36f..472ada5490 100644
>> --- a/arch/x86/config.mk
>> +++ b/arch/x86/config.mk
>> @@ -34,9 +34,6 @@ PLATFORM_RELFLAGS += -ffunction-sections -fvisibility=hidden
>>   PLATFORM_LDFLAGS += -Bsymbolic -Bsymbolic-functions
>>   PLATFORM_LDFLAGS += -m $(if $(IS_32BIT),elf_i386,elf_x86_64)
>>
>> -LDFLAGS_FINAL += --wrap=__divdi3 --wrap=__udivdi3
>> -LDFLAGS_FINAL += --wrap=__moddi3 --wrap=__umoddi3
>> -
>>   # This is used in the top-level Makefile which does not include
>>   # PLATFORM_LDFLAGS
>>   LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined
>> diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
>> index fe00d7573f..d9b23f5cc4 100644
>> --- a/arch/x86/lib/Makefile
>> +++ b/arch/x86/lib/Makefile
>> @@ -18,7 +18,7 @@ obj-$(CONFIG_SEABIOS) += coreboot_table.o
>>   obj-y  += early_cmos.o
>>   obj-$(CONFIG_EFI) += efi/
>>   obj-y  += e820.o
>> -obj-y  += gcc.o
>> +obj-y  += div64.o
>>   obj-y  += init_helpers.o
>>   obj-y  += interrupts.o
>>   obj-y  += lpc-uclass.o
>> diff --git a/arch/x86/lib/div64.c b/arch/x86/lib/div64.c
>> new file mode 100644
>> index 0000000000..4efed74037
>> --- /dev/null
>> +++ b/arch/x86/lib/div64.c
>> @@ -0,0 +1,113 @@
>> +/*
>> + * This file is copied from the coreboot repository as part of
>> + * the libpayload project:
>> + *
>> + * Copyright 2014 Google Inc.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <common.h>
>> +
>> +union overlay64 {
>> +       u64 longw;
>> +       struct {
>> +               u32 lower;
>> +               u32 higher;
>> +       } words;
>> +};
>> +
>> +u64 __ashldi3(u64 num, unsigned int shift)
>> +{
>> +       union overlay64 output;
>> +
>> +       output.longw = num;
>> +       if (shift >= 32) {
>> +               output.words.higher = output.words.lower << (shift - 32);
>> +               output.words.lower = 0;
>> +       } else {
>> +               if (!shift)
>> +                       return num;
>> +               output.words.higher = (output.words.higher << shift) |
>> +                       (output.words.lower >> (32 - shift));
>> +               output.words.lower = output.words.lower << shift;
>> +       }
>> +       return output.longw;
>> +}
>> +
>> +u64 __lshrdi3(u64 num, unsigned int shift)
>> +{
>> +       union overlay64 output;
>> +
>> +       output.longw = num;
>> +       if (shift >= 32) {
>> +               output.words.lower = output.words.higher >> (shift - 32);
>> +               output.words.higher = 0;
>> +       } else {
>> +               if (!shift)
>> +                       return num;
>> +               output.words.lower = output.words.lower >> shift |
>> +                       (output.words.higher << (32 - shift));
>> +               output.words.higher = output.words.higher >> shift;
>> +       }
>> +       return output.longw;
>> +}
>> +
>> +#define MAX_32BIT_UINT ((((u64)1) << 32) - 1)
>> +
>> +static u64 _64bit_divide(u64 dividend, u64 divider, u64 *rem_p)
>> +{
>> +       u64 result = 0;
>> +
>> +       /*
>> +        * If divider is zero - let the rest of the system care about the
>> +        * exception.
>> +        */
>> +       if (!divider)
>> +               return 1 / (u32)divider;
>> +
>> +       /* As an optimization, let's not use 64 bit division unless we must. */
>> +       if (dividend <= MAX_32BIT_UINT) {
>> +               if (divider > MAX_32BIT_UINT) {
>> +                       result = 0;
>> +                       if (rem_p)
>> +                               *rem_p = divider;
>> +               } else {
>> +                       result = (u32)dividend / (u32)divider;
>> +                       if (rem_p)
>> +                               *rem_p = (u32)dividend % (u32)divider;
>> +               }
>> +               return result;
>> +       }
>> +
>> +       while (divider <= dividend) {
>> +               u64 locald = divider;
>> +               u64 limit = __lshrdi3(dividend, 1);
>> +               int shifts = 0;
>> +
>> +               while (locald <= limit) {
>> +                       shifts++;
>> +                       locald = locald + locald;
>> +               }
>> +               result |= __ashldi3(1, shifts);
>> +               dividend -= locald;
>> +       }
>> +
>> +       if (rem_p)
>> +               *rem_p = dividend;
>> +
>> +       return result;
>> +}
>> +
>> +u64 __udivdi3(u64 num, u64 den)
>> +{
>> +       return _64bit_divide(num, den, NULL);
>> +}
>> +
>> +u64 __umoddi3(u64 num, u64 den)
>> +{
>> +       u64 v = 0;
>> +
>> +       _64bit_divide(num, den, &v);
>> +       return v;
>> +}
>> diff --git a/arch/x86/lib/gcc.c b/arch/x86/lib/gcc.c
>> deleted file mode 100644
>> index 3c70d790d4..0000000000
>> --- a/arch/x86/lib/gcc.c
>> +++ /dev/null
>> @@ -1,29 +0,0 @@
>> -/*
>> - * This file is part of the coreboot project.
>> - *
>> - * Copyright (C) 2009 coresystems GmbH
>> - *
>> - * SPDX-License-Identifier:    GPL-2.0
>> - */
>> -
>> -#ifdef __GNUC__
>> -
>> -/*
>> - * GCC's libgcc handling is quite broken. While the libgcc functions
>> - * are always regparm(0) the code that calls them uses whatever the
>> - * compiler call specifies. Therefore we need a wrapper around those
>> - * functions. See gcc bug PR41055 for more information.
>> - */
>> -#define WRAP_LIBGCC_CALL(type, name) \
>> -       type __normal_##name(type a, type b) __attribute__((regparm(0))); \
>> -       type __wrap_##name(type a, type b); \
>> -       type __attribute__((no_instrument_function)) \
>> -               __wrap_##name(type a, type b) \
>> -                { return __normal_##name(a, b); }
>> -
>> -WRAP_LIBGCC_CALL(long long, __divdi3)
>> -WRAP_LIBGCC_CALL(unsigned long long, __udivdi3)
>> -WRAP_LIBGCC_CALL(long long, __moddi3)
>> -WRAP_LIBGCC_CALL(unsigned long long, __umoddi3)
>> -
>> -#endif
>> --
> 
> I don't see __divdi3 and __moddi3 in the new implementation. Are they
> not needed?

Yes, at least I couldn't find any problems compiling U-Boot for x86 with
this patch.

BTW: The code size also did shrink a bit with this patch.

Thanks,
Stefan


More information about the U-Boot mailing list