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