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@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@denx.de> Cc: Simon Glass <sjg@chromium.org> Cc: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Tested-by: Bin Meng <bmeng.cn@gmail.com>master
parent
a53fbf4046
commit
aa7839b39c
@ -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; |
||||
} |
@ -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 |
Loading…
Reference in new issue