Remove libgcc dependency.

libgcc for boot environment isn't always present and compatible.
libgcc is often absent if endianness or bit-size at boot is different
from running OS.
libgcc may use optimised opcodes that aren't available on boot time.
So instead of relying on libgcc shipped with the compiler, supply
the functions in GRUB directly.
Tests are present to ensure that those replacement functions behave the
way compiler expects them to.
This commit is contained in:
Vladimir Serbinenko 2015-03-03 20:23:42 +01:00
parent 77697d14e5
commit 064360e667
21 changed files with 1441 additions and 479 deletions

View File

@ -34,10 +34,8 @@ CPPFLAGS_DEFAULT += -I$(top_srcdir)/grub-core/lib/libgcrypt-grub/src/
CCASFLAGS_DEFAULT = $(CPPFLAGS_DEFAULT) -DASM_FILE=1
BUILD_CPPFLAGS += $(CPPFLAGS_DEFAULT)
LDADD_KERNEL = $(TARGET_LIBGCC)
CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding
LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_LDFLAGS_STATIC_LIBGCC)
LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC)
CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1
CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags

View File

@ -7,6 +7,7 @@
#endif
#define GCRYPT_NO_DEPRECATED 1
#define HAVE_MEMMOVE 1
/* Define to 1 to enable disk cache statistics. */
#define DISK_CACHE_STATS @DISK_CACHE_STATS@

View File

@ -1131,22 +1131,17 @@ fi
# Set them to their new values for the tests below.
CC="$TARGET_CC"
if test "x$TARGET_APPLE_LINKER" = x1 ; then
if test x"$platform" = xemu ; then
CFLAGS="$TARGET_CFLAGS -Wno-error"
elif test "x$TARGET_APPLE_LINKER" = x1 ; then
CFLAGS="$TARGET_CFLAGS -nostdlib -static -Wno-error"
else
CFLAGS="$TARGET_CFLAGS -nostdlib -Wno-error"
fi
CPPFLAGS="$TARGET_CPPFLAGS"
if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 || test "x$grub_cv_cc_target_clang" = xyes ; then
TARGET_LIBGCC=
else
TARGET_LIBGCC=-lgcc
fi
LIBS="$TARGET_LIBGCC"
grub_ASM_USCORE
if test "x$TARGET_APPLE_LINKER" = x0 ; then
if test "x$TARGET_APPLE_LINKER" = x0 && test x"$platform" != xemu; then
if test x$grub_cv_asm_uscore = xyes; then
DEFSYM="-Wl,--defsym,_abort=_main -Wl,--defsym,__main=_main"
else
@ -1156,7 +1151,9 @@ CFLAGS="$TARGET_CFLAGS -nostdlib $DEFSYM"
fi
# Check for libgcc symbols
AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __ucmpdi2 _restgpr_14_x)
if test x"$platform" = xemu; then
AC_CHECK_FUNCS(__udivsi3 __umodsi3 __divsi3 __modsi3 __divdi3 __moddi3 __udivdi3 __umoddi3 __ctzdi2 __ctzsi2 __aeabi_uidiv __aeabi_uidivmod __aeabi_idiv __aeabi_idivmod __aeabi_ulcmp __muldi3 __aeabi_lmul __aeabi_memcpy __aeabi_memset __aeabi_lasr __aeabi_llsl __aeabi_llsr _restgpr_14_x __ucmpdi2 __ashldi3 __ashrdi3 __lshrdi3 __bswapsi2 __bswapdi2 __bzero __register_frame_info __deregister_frame_info ___chkstk_ms __chkstk_ms)
fi
if test "x$TARGET_APPLE_LINKER" = x1 ; then
CFLAGS="$TARGET_CFLAGS -nostdlib -static"
@ -1717,12 +1714,6 @@ if test x"$enable_werror" != xno ; then
HOST_CFLAGS="$HOST_CFLAGS -Werror"
fi
if test "x$grub_cv_cc_target_clang" = xno; then
TARGET_LDFLAGS_STATIC_LIBGCC="-static-libgcc"
else
TARGET_LDFLAGS_STATIC_LIBGCC=
fi
TARGET_CPP="$TARGET_CC -E"
TARGET_CCAS=$TARGET_CC
@ -1739,8 +1730,6 @@ AC_SUBST(GRUB_TARGET_CPU)
AC_SUBST(GRUB_PLATFORM)
AC_SUBST(TARGET_OBJCONV)
AC_SUBST(TARGET_LIBGCC)
AC_SUBST(TARGET_LDFLAGS_STATIC_LIBGCC)
AC_SUBST(TARGET_CPP)
AC_SUBST(TARGET_CCAS)
AC_SUBST(TARGET_OBJ2ELF)

View File

@ -76,6 +76,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h
else
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt.h
endif
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
@ -83,9 +88,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
if !COND_clang
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
endif
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
if COND_i386_pc

View File

@ -132,6 +132,7 @@ kernel = {
common = kern/rescue_reader.c;
common = kern/term.c;
noemu = kern/compiler-rt.c;
noemu = kern/mm.c;
noemu = kern/time.c;
noemu = kern/generic/millisleep.c;
@ -254,6 +255,7 @@ kernel = {
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
sparc64_ieee1275 = kern/sparc64/cache.S;
sparc64_ieee1275 = kern/sparc64/dl.c;
@ -265,7 +267,7 @@ kernel = {
arm = kern/arm/cache_armv7.S;
extra_dist = kern/arm/cache.S;
arm = kern/arm/cache.c;
arm = kern/arm/misc.S;
arm = kern/arm/compiler-rt.S;
arm64 = kern/arm64/cache.c;
arm64 = kern/arm64/cache_flush.S;
@ -443,13 +445,13 @@ image = {
common = lib/xzembed/xz_dec_bcj.c;
common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c;
common = kern/compiler-rt.c;
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1';
objcopyflags = '-O binary';
mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
ldadd = '$(TARGET_LIBGCC)';
cflags = '-Wno-unreachable-code $(TARGET_LDFLAGS_STATIC_LIBGCC)';
mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
cflags = '-Wno-unreachable-code';
enable = mips;
};
@ -461,9 +463,7 @@ image = {
cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1';
objcopyflags = '-O binary';
mips_ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) -Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
ldadd = '$(TARGET_LIBGCC)';
cflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC)';
mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)';
enable = mips;
};
@ -481,7 +481,7 @@ image = {
name = fwstart;
mips_loongson = boot/mips/loongson/fwstart.S;
objcopyflags = '-O binary';
ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
enable = mips_loongson;
};
@ -489,7 +489,7 @@ image = {
name = fwstart_fuloong2f;
mips_loongson = boot/mips/loongson/fuloong2f.S;
objcopyflags = '-O binary';
ldflags = '$(TARGET_LDFLAGS_STATIC_LIBGCC) $(TARGET_LIBGCC) -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
enable = mips_loongson;
};
@ -1982,6 +1982,31 @@ module = {
common = tests/div_test.c;
};
module = {
name = mul_test;
common = tests/mul_test.c;
};
module = {
name = shift_test;
common = tests/shift_test.c;
};
module = {
name = cmp_test;
common = tests/cmp_test.c;
};
module = {
name = ctz_test;
common = tests/ctz_test.c;
};
module = {
name = bswap_test;
common = tests/bswap_test.c;
};
module = {
name = videotest_checksum;
common = tests/videotest_checksum.c;

View File

@ -21,7 +21,7 @@
#include <grub/decompressor.h>
void *
memset (void *s, int c, grub_size_t len)
grub_memset (void *s, int c, grub_size_t len)
{
grub_uint8_t *ptr;
for (ptr = s; len; ptr++, len--)
@ -68,15 +68,6 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n)
return 0;
}
int memcmp (const void *s1, const void *s2, grub_size_t n)
__attribute__ ((alias ("grub_memcmp")));
void *memmove (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memmove")));
void *memcpy (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memmove")));
void *grub_decompressor_scratch;
void

View File

@ -0,0 +1,404 @@
/* compiler-rt.c - compiler helpers. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010-2014 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/misc.h>
#include <grub/compiler-rt.h>
#ifndef GRUB_EMBED_DECOMPRESSOR
void * GRUB_BUILTIN_ATTR
memcpy (void *dest, const void *src, grub_size_t n)
{
return grub_memmove (dest, src, n);
}
void * GRUB_BUILTIN_ATTR
memmove (void *dest, const void *src, grub_size_t n)
{
return grub_memmove (dest, src, n);
}
int GRUB_BUILTIN_ATTR
memcmp (const void *s1, const void *s2, grub_size_t n)
{
return grub_memcmp (s1, s2, n);
}
void * GRUB_BUILTIN_ATTR
memset (void *s, int c, grub_size_t n)
{
return grub_memset (s, c, n);
}
#ifdef __APPLE__
void GRUB_BUILTIN_ATTR
__bzero (void *s, grub_size_t n)
{
grub_memset (s, 0, n);
}
#endif
#if GRUB_DIVISION_IN_SOFTWARE
grub_uint32_t
__udivsi3 (grub_uint32_t a, grub_uint32_t b)
{
return grub_divmod64 (a, b, 0);
}
grub_int32_t
__divsi3 (grub_int32_t a, grub_int32_t b)
{
return grub_divmod64s (a, b, 0);
}
grub_uint32_t
__umodsi3 (grub_uint32_t a, grub_uint32_t b)
{
grub_uint64_t ret;
grub_divmod64 (a, b, &ret);
return ret;
}
grub_int32_t
__modsi3 (grub_int32_t a, grub_int32_t b)
{
grub_int64_t ret;
grub_divmod64s (a, b, &ret);
return ret;
}
grub_uint64_t
__udivdi3 (grub_uint64_t a, grub_uint64_t b)
{
return grub_divmod64 (a, b, 0);
}
grub_uint64_t
__umoddi3 (grub_uint64_t a, grub_uint64_t b)
{
grub_uint64_t ret;
grub_divmod64 (a, b, &ret);
return ret;
}
grub_int64_t
__divdi3 (grub_int64_t a, grub_int64_t b)
{
return grub_divmod64s (a, b, 0);
}
grub_int64_t
__moddi3 (grub_int64_t a, grub_int64_t b)
{
grub_int64_t ret;
grub_divmod64s (a, b, &ret);
return ret;
}
#endif
#endif
#ifdef NEED_CTZDI2
unsigned
__ctzdi2 (grub_uint64_t x)
{
unsigned ret = 0;
if (!x)
return 64;
if (!(x & 0xffffffff))
{
x >>= 32;
ret |= 32;
}
if (!(x & 0xffff))
{
x >>= 16;
ret |= 16;
}
if (!(x & 0xff))
{
x >>= 8;
ret |= 8;
}
if (!(x & 0xf))
{
x >>= 4;
ret |= 4;
}
if (!(x & 0x3))
{
x >>= 2;
ret |= 2;
}
if (!(x & 0x1))
{
x >>= 1;
ret |= 1;
}
return ret;
}
#endif
#ifdef NEED_CTZSI2
unsigned
__ctzsi2 (grub_uint32_t x)
{
unsigned ret = 0;
if (!x)
return 32;
if (!(x & 0xffff))
{
x >>= 16;
ret |= 16;
}
if (!(x & 0xff))
{
x >>= 8;
ret |= 8;
}
if (!(x & 0xf))
{
x >>= 4;
ret |= 4;
}
if (!(x & 0x3))
{
x >>= 2;
ret |= 2;
}
if (!(x & 0x1))
{
x >>= 1;
ret |= 1;
}
return ret;
}
#endif
#if defined (__clang__) && !defined(GRUB_EMBED_DECOMPRESSOR)
/* clang emits references to abort(). */
void __attribute__ ((noreturn))
abort (void)
{
grub_fatal ("compiler abort");
}
#endif
#if (defined (__MINGW32__) || defined (__CYGWIN__))
void __register_frame_info (void)
{
}
void __deregister_frame_info (void)
{
}
void ___chkstk_ms (void)
{
}
void __chkstk_ms (void)
{
}
#endif
union component64
{
grub_uint64_t full;
struct
{
#ifdef GRUB_CPU_WORDS_BIGENDIAN
grub_uint32_t high;
grub_uint32_t low;
#else
grub_uint32_t low;
grub_uint32_t high;
#endif
};
};
#if defined (__powerpc__) || defined (__arm__) || defined(__mips__)
/* Based on libgcc2.c from gcc suite. */
grub_uint64_t
__lshrdi3 (grub_uint64_t u, int b)
{
if (b == 0)
return u;
const union component64 uu = {.full = u};
const int bm = 32 - b;
union component64 w;
if (bm <= 0)
{
w.high = 0;
w.low = (grub_uint32_t) uu.high >> -bm;
}
else
{
const grub_uint32_t carries = (grub_uint32_t) uu.high << bm;
w.high = (grub_uint32_t) uu.high >> b;
w.low = ((grub_uint32_t) uu.low >> b) | carries;
}
return w.full;
}
/* Based on libgcc2.c from gcc suite. */
grub_uint64_t
__ashrdi3 (grub_uint64_t u, int b)
{
if (b == 0)
return u;
const union component64 uu = {.full = u};
const int bm = 32 - b;
union component64 w;
if (bm <= 0)
{
/* w.high = 1..1 or 0..0 */
w.high = ((grub_int32_t) uu.high) >> (32 - 1);
w.low = ((grub_int32_t) uu.high) >> -bm;
}
else
{
const grub_uint32_t carries = ((grub_uint32_t) uu.high) << bm;
w.high = ((grub_int32_t) uu.high) >> b;
w.low = ((grub_uint32_t) uu.low >> b) | carries;
}
return w.full;
}
/* Based on libgcc2.c from gcc suite. */
grub_uint64_t
__ashldi3 (grub_uint64_t u, int b)
{
if (b == 0)
return u;
const union component64 uu = {.full = u};
const int bm = 32 - b;
union component64 w;
if (bm <= 0)
{
w.low = 0;
w.high = (grub_uint32_t) uu.low << -bm;
}
else
{
const grub_uint32_t carries = (grub_uint32_t) uu.low >> bm;
w.low = (grub_uint32_t) uu.low << b;
w.high = ((grub_uint32_t) uu.high << b) | carries;
}
return w.full;
}
/* Based on libgcc2.c from gcc suite. */
int
__ucmpdi2 (grub_uint64_t a, grub_uint64_t b)
{
union component64 ac, bc;
ac.full = a;
bc.full = b;
if (ac.high < bc.high)
return 0;
else if (ac.high > bc.high)
return 2;
if (ac.low < bc.low)
return 0;
else if (ac.low > bc.low)
return 2;
return 1;
}
#endif
#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || defined(__arm__)
/* Based on libgcc2.c from gcc suite. */
grub_uint32_t
__bswapsi2 (grub_uint32_t u)
{
return ((((u) & 0xff000000) >> 24)
| (((u) & 0x00ff0000) >> 8)
| (((u) & 0x0000ff00) << 8)
| (((u) & 0x000000ff) << 24));
}
/* Based on libgcc2.c from gcc suite. */
grub_uint64_t
__bswapdi2 (grub_uint64_t u)
{
return ((((u) & 0xff00000000000000ull) >> 56)
| (((u) & 0x00ff000000000000ull) >> 40)
| (((u) & 0x0000ff0000000000ull) >> 24)
| (((u) & 0x000000ff00000000ull) >> 8)
| (((u) & 0x00000000ff000000ull) << 8)
| (((u) & 0x0000000000ff0000ull) << 24)
| (((u) & 0x000000000000ff00ull) << 40)
| (((u) & 0x00000000000000ffull) << 56));
}
#endif
#ifdef __arm__
grub_uint32_t
__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b)
__attribute__ ((alias ("__udivsi3")));
grub_int32_t
__aeabi_idiv (grub_int32_t a, grub_int32_t b)
__attribute__ ((alias ("__divsi3")));
void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memcpy")));
void *__aeabi_memset (void *s, int c, grub_size_t n)
__attribute__ ((alias ("memset")));
int
__aeabi_ulcmp (grub_uint64_t a, grub_uint64_t b)
{
return __ucmpdi2 (a, b) - 1;
}
grub_uint64_t
__aeabi_lasr (grub_uint64_t u, int b)
__attribute__ ((alias ("__ashrdi3")));
grub_uint64_t
__aeabi_llsr (grub_uint64_t u, int b)
__attribute__ ((alias ("__lshrdi3")));
grub_uint64_t
__aeabi_llsl (grub_uint64_t u, int b)
__attribute__ ((alias ("__ashldi3")));
#endif

View File

@ -95,25 +95,6 @@ grub_memmove (void *dest, const void *src, grub_size_t n)
return dest;
}
#ifndef __APPLE__
void *memmove (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memmove")));
/* GCC emits references to memcpy() for struct copies etc. */
void *memcpy (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memmove")));
#else
void * GRUB_BUILTIN_ATTR
memcpy (void *dest, const void *src, grub_size_t n)
{
return grub_memmove (dest, src, n);
}
void * GRUB_BUILTIN_ATTR
memmove (void *dest, const void *src, grub_size_t n)
{
return grub_memmove (dest, src, n);
}
#endif
char *
grub_strcpy (char *dest, const char *src)
{
@ -253,16 +234,6 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n)
return 0;
}
#ifndef __APPLE__
int memcmp (const void *s1, const void *s2, grub_size_t n)
__attribute__ ((alias ("grub_memcmp")));
#else
int GRUB_BUILTIN_ATTR
memcmp (const void *s1, const void *s2, grub_size_t n)
{
return grub_memcmp (s1, s2, n);
}
#endif
int
grub_strcmp (const char *s1, const char *s2)
@ -532,26 +503,6 @@ grub_memset (void *s, int c, grub_size_t len)
return s;
}
#ifndef __APPLE__
void *memset (void *s, int c, grub_size_t n)
__attribute__ ((alias ("grub_memset")));
#else
void * GRUB_BUILTIN_ATTR
memset (void *s, int c, grub_size_t n)
{
return grub_memset (s, c, n);
}
#endif
#if !defined(GRUB_UTIL) && defined(__APPLE__)
void GRUB_BUILTIN_ATTR
__bzero (void *s, grub_size_t n)
{
grub_memset (s, 0, n);
}
#endif
grub_size_t
grub_strlen (const char *s)
@ -631,163 +582,6 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
return q;
}
#if !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
#if GRUB_DIVISION_IN_SOFTWARE
grub_uint32_t
__udivsi3 (grub_uint32_t a, grub_uint32_t b)
{
return grub_divmod64 (a, b, 0);
}
grub_int32_t
__divsi3 (grub_int32_t a, grub_int32_t b)
{
return grub_divmod64s (a, b, 0);
}
grub_uint32_t
__umodsi3 (grub_uint32_t a, grub_uint32_t b)
{
grub_uint64_t ret;
grub_divmod64 (a, b, &ret);
return ret;
}
grub_int32_t
__modsi3 (grub_int32_t a, grub_int32_t b)
{
grub_int64_t ret;
grub_divmod64s (a, b, &ret);
return ret;
}
grub_uint64_t
__udivdi3 (grub_uint64_t a, grub_uint64_t b)
{
return grub_divmod64 (a, b, 0);
}
grub_uint64_t
__umoddi3 (grub_uint64_t a, grub_uint64_t b)
{
grub_uint64_t ret;
grub_divmod64 (a, b, &ret);
return ret;
}
grub_int64_t
__divdi3 (grub_int64_t a, grub_int64_t b)
{
return grub_divmod64s (a, b, 0);
}
grub_int64_t
__moddi3 (grub_int64_t a, grub_int64_t b)
{
grub_int64_t ret;
grub_divmod64s (a, b, &ret);
return ret;
}
#endif
#ifdef NEED_CTZDI2
unsigned
__ctzdi2 (grub_uint64_t x)
{
unsigned ret = 0;
if (!x)
return 64;
if (!(x & 0xffffffff))
{
x >>= 32;
ret |= 32;
}
if (!(x & 0xffff))
{
x >>= 16;
ret |= 16;
}
if (!(x & 0xff))
{
x >>= 8;
ret |= 8;
}
if (!(x & 0xf))
{
x >>= 4;
ret |= 4;
}
if (!(x & 0x3))
{
x >>= 2;
ret |= 2;
}
if (!(x & 0x1))
{
x >>= 1;
ret |= 1;
}
return ret;
}
#endif
#ifdef NEED_CTZSI2
unsigned
__ctzsi2 (grub_uint32_t x)
{
unsigned ret = 0;
if (!x)
return 32;
if (!(x & 0xffff))
{
x >>= 16;
ret |= 16;
}
if (!(x & 0xff))
{
x >>= 8;
ret |= 8;
}
if (!(x & 0xf))
{
x >>= 4;
ret |= 4;
}
if (!(x & 0x3))
{
x >>= 2;
ret |= 2;
}
if (!(x & 0x1))
{
x >>= 1;
ret |= 1;
}
return ret;
}
#endif
#ifdef __arm__
grub_uint32_t
__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b)
__attribute__ ((alias ("__udivsi3")));
grub_int32_t
__aeabi_idiv (grub_int32_t a, grub_int32_t b)
__attribute__ ((alias ("__divsi3")));
void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memcpy")));
void *__aeabi_memset (void *s, int c, grub_size_t n)
__attribute__ ((alias ("grub_memset")));
#endif
#endif /* GRUB_UTIL */
/* Convert a long long value to a string. This function avoids 64-bit
modular arithmetic or divisions. */
static inline char *
@ -1296,15 +1090,6 @@ grub_abort (void)
grub_exit ();
}
#if defined (__clang__) && !defined (GRUB_UTIL)
/* clang emits references to abort(). */
void __attribute__ ((noreturn))
abort (void)
{
grub_abort ();
}
#endif
void
grub_fatal (const char *fmt, ...)
{
@ -1317,23 +1102,6 @@ grub_fatal (const char *fmt, ...)
grub_abort ();
}
#if (defined (__MINGW32__) || defined (__CYGWIN__)) && !defined(GRUB_UTIL)
void __register_frame_info (void)
{
}
void __deregister_frame_info (void)
{
}
void ___chkstk_ms (void)
{
}
void __chkstk_ms (void)
{
}
#endif
#if BOOT_TIME_STATS
#include <grub/time.h>

View File

@ -0,0 +1,130 @@
/*
* Special support for eabi and SVR4
*
* Copyright (C) 1995-2014 Free Software Foundation, Inc.
* Written By Michael Meissner
* 64-bit support written by David Edelsohn
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 3, or (at your option) any
* later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* Under Section 7 of GPL version 3, you are granted additional
* permissions described in the GCC Runtime Library Exception, version
* 3.1, as published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License and
* a copy of the GCC Runtime Library Exception along with this program;
* see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
* <http://www.gnu.org/licenses/>.
*/
/* Do any initializations needed for the eabi environment */
#include <grub/symbol.h>
#include <grub/dl.h>
.section ".text"
#define CFI_RESTORE(reg) .cfi_restore reg
#define CFI_OFFSET(reg, off) .cfi_offset reg, off
#define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
#define CFI_STARTPROC .cfi_startproc
#define CFI_ENDPROC .cfi_endproc
/* Routines for restoring integer registers, called by the compiler. */
/* Called with r11 pointing to the stack header word of the caller of the */
/* function, just beyond the end of the integer restore area. */
CFI_STARTPROC
CFI_DEF_CFA_REGISTER (11)
CFI_OFFSET (65, 4)
CFI_OFFSET (14, -72)
CFI_OFFSET (15, -68)
CFI_OFFSET (16, -64)
CFI_OFFSET (17, -60)
CFI_OFFSET (18, -56)
CFI_OFFSET (19, -52)
CFI_OFFSET (20, -48)
CFI_OFFSET (21, -44)
CFI_OFFSET (22, -40)
CFI_OFFSET (23, -36)
CFI_OFFSET (24, -32)
CFI_OFFSET (25, -28)
CFI_OFFSET (26, -24)
CFI_OFFSET (27, -20)
CFI_OFFSET (28, -16)
CFI_OFFSET (29, -12)
CFI_OFFSET (30, -8)
CFI_OFFSET (31, -4)
FUNCTION(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */
CFI_RESTORE (14)
FUNCTION(_restgpr_15_x) lwz 15,-68(11)
CFI_RESTORE (15)
FUNCTION(_restgpr_16_x) lwz 16,-64(11)
CFI_RESTORE (16)
FUNCTION(_restgpr_17_x) lwz 17,-60(11)
CFI_RESTORE (17)
FUNCTION(_restgpr_18_x) lwz 18,-56(11)
CFI_RESTORE (18)
FUNCTION(_restgpr_19_x) lwz 19,-52(11)
CFI_RESTORE (19)
FUNCTION(_restgpr_20_x) lwz 20,-48(11)
CFI_RESTORE (20)
FUNCTION(_restgpr_21_x) lwz 21,-44(11)
CFI_RESTORE (21)
FUNCTION(_restgpr_22_x) lwz 22,-40(11)
CFI_RESTORE (22)
FUNCTION(_restgpr_23_x) lwz 23,-36(11)
CFI_RESTORE (23)
FUNCTION(_restgpr_24_x) lwz 24,-32(11)
CFI_RESTORE (24)
FUNCTION(_restgpr_25_x) lwz 25,-28(11)
CFI_RESTORE (25)
FUNCTION(_restgpr_26_x) lwz 26,-24(11)
CFI_RESTORE (26)
FUNCTION(_restgpr_27_x) lwz 27,-20(11)
CFI_RESTORE (27)
FUNCTION(_restgpr_28_x) lwz 28,-16(11)
CFI_RESTORE (28)
FUNCTION(_restgpr_29_x) lwz 29,-12(11)
CFI_RESTORE (29)
FUNCTION(_restgpr_30_x) lwz 30,-8(11)
CFI_RESTORE (30)
FUNCTION(_restgpr_31_x) lwz 0,4(11)
lwz 31,-4(11)
CFI_RESTORE (31)
mtlr 0
CFI_RESTORE (65)
mr 1,11
CFI_DEF_CFA_REGISTER (1)
blr
CFI_ENDPROC
CFI_STARTPROC
FUNCTION(_savegpr_14) stw 14,-72(11) /* save gp registers */
FUNCTION(_savegpr_15) stw 15,-68(11)
FUNCTION(_savegpr_16) stw 16,-64(11)
FUNCTION(_savegpr_17) stw 17,-60(11)
FUNCTION(_savegpr_18) stw 18,-56(11)
FUNCTION(_savegpr_19) stw 19,-52(11)
FUNCTION(_savegpr_20) stw 20,-48(11)
FUNCTION(_savegpr_21) stw 21,-44(11)
FUNCTION(_savegpr_22) stw 22,-40(11)
FUNCTION(_savegpr_23) stw 23,-36(11)
FUNCTION(_savegpr_24) stw 24,-32(11)
FUNCTION(_savegpr_25) stw 25,-28(11)
FUNCTION(_savegpr_26) stw 26,-24(11)
FUNCTION(_savegpr_27) stw 27,-20(11)
FUNCTION(_savegpr_28) stw 28,-16(11)
FUNCTION(_savegpr_29) stw 29,-12(11)
FUNCTION(_savegpr_30) stw 30,-8(11)
FUNCTION(_savegpr_31) stw 31,-4(11)
blr
CFI_ENDPROC

View File

@ -42,21 +42,6 @@ strcasecmp (const char *s1, const char *s2)
return grub_strcasecmp (s1, s2);
}
#ifdef GRUB_UTIL
static inline void *
memcpy (void *dest, const void *src, grub_size_t n)
{
return grub_memcpy (dest, src, n);
}
static inline int
memcmp (const void *s1, const void *s2, grub_size_t n)
{
return grub_memcmp (s1, s2, n);
}
#endif
static inline void
bcopy (const void *src, void *dest, grub_size_t n)
{
@ -99,4 +84,9 @@ memchr (const void *s, int c, grub_size_t n)
return grub_memchr (s, c, n);
}
#define memcmp grub_memcmp
#define memcpy grub_memcpy
#define memmove grub_memmove
#define memset grub_memset
#endif

View File

@ -0,0 +1,121 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2015 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/test.h>
#include <grub/dl.h>
#include <grub/misc.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint64_t vectors[] = {
0xffffffffffffffffULL, 1, 2, 0, 0x0102030405060708ULL
};
static void
test16 (grub_uint16_t a)
{
grub_uint16_t b, c;
grub_uint8_t *ap, *bp;
int i;
b = grub_swap_bytes16 (a);
c = grub_swap_bytes16 (b);
grub_test_assert (a == c, "bswap not idempotent: 0x%llx, 0x%llx, 0x%llx",
(long long) a, (long long) b, (long long) c);
ap = (grub_uint8_t *) &a;
bp = (grub_uint8_t *) &b;
for (i = 0; i < 2; i++)
{
grub_test_assert (ap[i] == bp[1 - i],
"bswap bytes wrong: 0x%llx, 0x%llx",
(long long) a, (long long) b);
}
}
static void
test32 (grub_uint32_t a)
{
grub_uint32_t b, c;
grub_uint8_t *ap, *bp;
int i;
b = grub_swap_bytes32 (a);
c = grub_swap_bytes32 (b);
grub_test_assert (a == c, "bswap not idempotent: 0x%llx, 0x%llx, 0x%llx",
(long long) a, (long long) b, (long long) c);
ap = (grub_uint8_t *) &a;
bp = (grub_uint8_t *) &b;
for (i = 0; i < 4; i++)
{
grub_test_assert (ap[i] == bp[3 - i],
"bswap bytes wrong: 0x%llx, 0x%llx",
(long long) a, (long long) b);
}
}
static void
test64 (grub_uint64_t a)
{
grub_uint64_t b, c;
grub_uint8_t *ap, *bp;
int i;
b = grub_swap_bytes64 (a);
c = grub_swap_bytes64 (b);
grub_test_assert (a == c, "bswap not idempotent: 0x%llx, 0x%llx, 0x%llx",
(long long) a, (long long) b, (long long) c);
ap = (grub_uint8_t *) &a;
bp = (grub_uint8_t *) &b;
for (i = 0; i < 4; i++)
{
grub_test_assert (ap[i] == bp[7 - i],
"bswap bytes wrong: 0x%llx, 0x%llx",
(long long) a, (long long) b);
}
}
static void
test_all(grub_uint64_t a)
{
test64 (a);
test32 (a);
test16 (a);
}
static void
bswap_test (void)
{
grub_uint64_t a = 404, b = 7;
grub_size_t i;
for (i = 0; i < ARRAY_SIZE (vectors); i++)
{
test_all (vectors[i]);
}
for (i = 0; i < 40000; i++)
{
a = 17 * a + 13 * b;
b = 23 * a + 29 * b;
if (b == 0)
b = 1;
if (a == 0)
a = 1;
test_all (a);
test_all (b);
}
}
/* Register example_test method as a functional test. */
GRUB_FUNCTIONAL_TEST (bswap_test, bswap_test);

190
grub-core/tests/cmp_test.c Normal file
View File

@ -0,0 +1,190 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2015 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/test.h>
#include <grub/dl.h>
#include <grub/misc.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint64_t vectors[][2] = {
{ 0xffffffffffffffffULL, 1},
{ 1, 0xffffffffffffffffULL},
{ 0xffffffffffffffffULL, 0xffffffffffffffffULL},
{ 1, 1 },
{ 2, 1 }
};
/* Don't change those to use shift as shift may call to compile rt
functions and we're not testing them now.
*/
static int
leading_bit64 (grub_uint64_t a)
{
return !!(a & 0x8000000000000000LL);
}
static int
leading_bit32 (grub_uint32_t a)
{
return !!(a & 0x80000000);
}
/* Computes (a < b) without involving comparison operator. */
static int
is_less32 (grub_uint32_t a, grub_uint32_t b)
{
if (leading_bit32(a) && !leading_bit32(b))
return 0;
if (!leading_bit32(a) && leading_bit32(b))
return 1;
return leading_bit32(a - b);
}
static void
test32 (grub_uint32_t a, grub_uint32_t b)
{
grub_test_assert ((a < b) == is_less32(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((a > b) == is_less32(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b < a) == is_less32(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b > a) == is_less32(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert (!(is_less32(a, b) && is_less32(b, a)), "comparison inconsistent: %lld, %lld",
(long long) a, (long long) b);
}
/* Computes (a > b) without involving comparison operator. */
static int
is_less32s (grub_int32_t a, grub_int32_t b)
{
if (leading_bit32(a) && !leading_bit32(b))
return 1; /* a < 0 && b >= 0. */
if (!leading_bit32(a) && leading_bit32(b))
return 0; /* b < 0 && a >= 0. */
return leading_bit32(a - b);
}
static void
test32s (grub_int32_t a, grub_int32_t b)
{
grub_test_assert ((a < b) == is_less32s(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((a > b) == is_less32s(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b < a) == is_less32s(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b > a) == is_less32s(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert (!(is_less32s(a, b) && is_less32s(b, a)), "comparison inconsistent: %lld, %lld",
(long long) a, (long long) b);
}
/* Computes (a > b) without involving comparison operator. */
static int
is_less64 (grub_uint64_t a, grub_uint64_t b)
{
if (leading_bit64(a) && !leading_bit64(b))
return 0;
if (!leading_bit64(a) && leading_bit64(b))
return 1;
return leading_bit64(a - b);
}
static void
test64 (grub_uint64_t a, grub_uint64_t b)
{
grub_test_assert ((a < b) == is_less64(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((a > b) == is_less64(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b < a) == is_less64(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b > a) == is_less64(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert (!(is_less64(a, b) && is_less64(b, a)), "comparison inconsistent: %lld, %lld",
(long long) a, (long long) b);
}
/* Computes (a > b) without involving comparison operator. */
static int
is_less64s (grub_int64_t a, grub_int64_t b)
{
if (leading_bit64(a) && !leading_bit64(b))
return 1; /* a < 0 && b >= 0. */
if (!leading_bit64(a) && leading_bit64(b))
return 0; /* b < 0 && a >= 0. */
return leading_bit64(a - b);
}
static void
test64s (grub_int64_t a, grub_int64_t b)
{
grub_test_assert ((a < b) == is_less64s(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((a > b) == is_less64s(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b < a) == is_less64s(b, a), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert ((b > a) == is_less64s(a, b), "comparison result mismatch: %lld, %lld",
(long long) a, (long long) b);
grub_test_assert (!(is_less64s(a, b) && is_less64s(b, a)), "comparison inconsistent: %lld, %lld",
(long long) a, (long long) b);
}
static void
test_all(grub_uint64_t a, grub_uint64_t b)
{
test64 (a, b);
test32 (a, b);
test64s (a, b);
test32s (a, b);
test64s (a, -b);
test32s (a, -b);
test64s (-a, b);
test32s (-a, b);
test64s (-a, -b);
test32s (-a, -b);
}
static void
cmp_test (void)
{
grub_uint64_t a = 404, b = 7;
grub_size_t i;
for (i = 0; i < ARRAY_SIZE (vectors); i++)
{
test_all (vectors[i][0], vectors[i][1]);
}
for (i = 0; i < 40000; i++)
{
a = 17 * a + 13 * b;
b = 23 * a + 29 * b;
if (b == 0)
b = 1;
if (a == 0)
a = 1;
test_all (a, b);
}
}
/* Register example_test method as a functional test. */
GRUB_FUNCTIONAL_TEST (cmp_test, cmp_test);

111
grub-core/tests/ctz_test.c Normal file
View File

@ -0,0 +1,111 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/test.h>
#include <grub/dl.h>
#include <grub/misc.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* ull version is not used on i386 other than in this test.
Avoid requiring extra function.
*/
#if defined (__i386__)
#define SKIP_ULL 1
#endif
static grub_uint64_t vectors[] = {
0xffffffffffffffffULL, 1, 2, 0, 0x0102030405060708ULL
};
static void
test_ui (unsigned int a)
{
int i;
a |= 1;
for (i = 0; i < (int) (8 * sizeof (a)); i++)
{
grub_test_assert (__builtin_ctz(a << i) == i,
"ctz mismatch: ctz(0x%llx) != 0x%x",
(long long) (a << i), __builtin_ctz(a << i));
}
}
static void
test_ul (unsigned long a)
{
int i;
a |= 1;
for (i = 0; i < (int) (8 * sizeof (a)); i++)
{
grub_test_assert (__builtin_ctzl(a << i) == i,
"ctzl mismatch: ctzl(0x%llx) != 0x%x",
(long long) (a << i), __builtin_ctz(a << i));
}
}
#ifndef SKIP_ULL
static void
test_ull (unsigned long long a)
{
int i;
a |= 1;
for (i = 0; i < (int) (8 * sizeof (a)); i++)
{
grub_test_assert (__builtin_ctzll(a << i) == i,
"ctzll mismatch: ctzll(0x%llx) != 0x%x",
(long long) (a << i), __builtin_ctz(a << i));
}
}
#endif
static void
test_all(grub_uint64_t a)
{
test_ui (a);
test_ul (a);
#ifndef SKIP_ULL
test_ull (a);
#endif
}
static void
ctz_test (void)
{
grub_uint64_t a = 404, b = 7;
grub_size_t i;
for (i = 0; i < ARRAY_SIZE (vectors); i++)
{
test_all (vectors[i]);
}
for (i = 0; i < 40000; i++)
{
a = 17 * a + 13 * b;
b = 23 * a + 29 * b;
if (b == 0)
b = 1;
if (a == 0)
a = 1;
test_all (a);
test_all (b);
}
}
/* Register example_test method as a functional test. */
GRUB_FUNCTIONAL_TEST (ctz_test, ctz_test);

View File

@ -65,6 +65,11 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)),
grub_dl_load ("pbkdf2_test");
grub_dl_load ("signature_test");
grub_dl_load ("sleep_test");
grub_dl_load ("bswap_test");
grub_dl_load ("ctz_test");
grub_dl_load ("cmp_test");
grub_dl_load ("mul_test");
grub_dl_load ("shift_test");
FOR_LIST_ELEMENTS (test, grub_test_list)
ok = !grub_test_run (test) && ok;

View File

@ -0,0 +1,73 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/test.h>
#include <grub/dl.h>
#include <grub/misc.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint64_t vectors[][2] = {
{ 0xffffffffffffffffULL, 1},
{ 1, 0xffffffffffffffffULL},
{ 0xffffffffffffffffULL, 0xffffffffffffffffULL},
{ 1, 1 },
{ 2, 1 }
};
static void
test64(grub_uint64_t a, grub_uint64_t b)
{
grub_uint64_t r1 = a * b, r2 = 0, r3;
int i;
for (i = 0; i < 64; i++)
if ((a & (1LL << i)))
r2 += b << i;
r3 = ((grub_int64_t) a) * ((grub_int64_t) b);
grub_test_assert (r1 == r2,
"multiplication mismatch (u): 0x%llx x 0x%llx = 0x%llx != 0x%llx",
(long long) a, (long long) b, (long long) r2, (long long) r1);
grub_test_assert (r3 == r2,
"multiplication mismatch (s): 0x%llx x 0x%llx = 0x%llx != 0x%llx",
(long long) a, (long long) b, (long long) r2, (long long) r3);
}
static void
mul_test (void)
{
grub_uint64_t a = 404, b = 7;
grub_size_t i;
for (i = 0; i < ARRAY_SIZE (vectors); i++)
{
test64 (vectors[i][0], vectors[i][1]);
}
for (i = 0; i < 40000; i++)
{
a = 17 * a + 13 * b;
b = 23 * a + 29 * b;
if (b == 0)
b = 1;
if (a == 0)
a = 1;
test64 (a, b);
}
}
/* Register example_test method as a functional test. */
GRUB_FUNCTIONAL_TEST (mul_test, mul_test);

View File

@ -0,0 +1,157 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2015 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/test.h>
#include <grub/dl.h>
#include <grub/misc.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint64_t vectors[] = {
0xffffffffffffffffULL, 1, 2, 0, 0x0102030405060708ULL
};
/* We're testing shifts, don't replace access to this with a shift. */
static const grub_uint8_t bitmask[] =
{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
typedef union {
grub_uint64_t v64;
grub_uint8_t v8[8];
} grub_raw_u64_t;
static int
get_bit64 (grub_uint64_t v, int b)
{
grub_raw_u64_t vr = { .v64 = v };
grub_uint8_t *p = vr.v8;
if (b >= 64)
return 0;
#ifdef GRUB_CPU_WORDS_BIGENDIAN
p += 7 - b / 8;
#else
p += b / 8;
#endif
return !!(*p & bitmask[b % 8]);
}
static grub_uint64_t
set_bit64 (grub_uint64_t v, int b)
{
grub_raw_u64_t vr = { .v64 = v };
grub_uint8_t *p = vr.v8;
if (b >= 64)
return v;
#ifdef GRUB_CPU_WORDS_BIGENDIAN
p += 7 - b / 8;
#else
p += b / 8;
#endif
*p |= bitmask[b % 8];
return vr.v64;
}
static grub_uint64_t
left_shift64 (grub_uint64_t v, int s)
{
grub_uint64_t r = 0;
int i;
for (i = 0; i + s < 64; i++)
if (get_bit64 (v, i))
r = set_bit64 (r, i + s);
return r;
}
static grub_uint64_t
right_shift64 (grub_uint64_t v, int s)
{
grub_uint64_t r = 0;
int i;
for (i = s; i < 64; i++)
if (get_bit64 (v, i))
r = set_bit64 (r, i - s);
return r;
}
static grub_uint64_t
arithmetic_right_shift64 (grub_uint64_t v, int s)
{
grub_uint64_t r = 0;
int i;
for (i = s; i < 64; i++)
if (get_bit64 (v, i))
r = set_bit64 (r, i - s);
if (get_bit64 (v, 63))
for (i -= s; i < 64; i++)
r = set_bit64 (r, i);
return r;
}
static void
test64 (grub_uint64_t v)
{
int i;
for (i = 0; i < 64; i++)
{
grub_test_assert ((v << i) == left_shift64 (v, i),
"lshift wrong: 0x%llx << %d: 0x%llx, 0x%llx",
(long long) v, i,
(long long) (v << i), (long long) left_shift64 (v, i));
grub_test_assert ((v >> i) == right_shift64 (v, i),
"rshift wrong: 0x%llx >> %d: 0x%llx, 0x%llx",
(long long) v, i,
(long long) (v >> i), (long long) right_shift64 (v, i));
grub_test_assert ((((grub_int64_t) v) >> i) == (grub_int64_t) arithmetic_right_shift64 (v, i),
"arithmetic rshift wrong: ((grub_int64_t) 0x%llx) >> %d: 0x%llx, 0x%llx",
(long long) v, i,
(long long) (((grub_int64_t) v) >> i), (long long) arithmetic_right_shift64 (v, i));
}
}
static void
test_all(grub_uint64_t a)
{
test64 (a);
}
static void
shift_test (void)
{
grub_uint64_t a = 404, b = 7;
grub_size_t i;
for (i = 0; i < ARRAY_SIZE (vectors); i++)
{
test_all (vectors[i]);
}
for (i = 0; i < 4000; i++)
{
a = 17 * a + 13 * b;
b = 23 * a + 29 * b;
if (b == 0)
b = 1;
if (a == 0)
a = 1;
test_all (a);
test_all (b);
}
}
/* Register example_test method as a functional test. */
GRUB_FUNCTIONAL_TEST (shift_test, shift_test);

193
include/grub/compiler-rt.h Normal file
View File

@ -0,0 +1,193 @@
/* compiler-rt.h - prototypes for compiler helpers. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010-2014 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_COMPILER_RT_HEADER
#define GRUB_COMPILER_RT_HEADER 1
#include <stdarg.h>
#include <grub/types.h>
#include <grub/symbol.h>
#include <grub/misc.h>
#if defined(GRUB_DIVISION_IN_SOFTWARE) && GRUB_DIVISION_IN_SOFTWARE
grub_uint32_t
EXPORT_FUNC (__udivsi3) (grub_uint32_t a, grub_uint32_t b);
grub_uint32_t
EXPORT_FUNC (__umodsi3) (grub_uint32_t a, grub_uint32_t b);
grub_int32_t
EXPORT_FUNC (__divsi3) (grub_int32_t a, grub_int32_t b);
grub_int32_t
EXPORT_FUNC (__modsi3) (grub_int32_t a, grub_int32_t b);
grub_int64_t
EXPORT_FUNC (__divdi3) (grub_int64_t a, grub_int64_t b);
grub_int64_t
EXPORT_FUNC (__moddi3) (grub_int64_t a, grub_int64_t b);
grub_uint64_t
EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b);
grub_uint64_t
EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b);
#endif
#if defined (__sparc__) || defined (__powerpc__) || defined (__mips__) || defined (__arm__)
unsigned
EXPORT_FUNC (__ctzdi2) (grub_uint64_t x);
#define NEED_CTZDI2 1
#endif
#if defined (__mips__) || defined (__arm__)
unsigned
EXPORT_FUNC (__ctzsi2) (grub_uint32_t x);
#define NEED_CTZSI2 1
#endif
#ifdef __arm__
grub_uint32_t
EXPORT_FUNC (__aeabi_uidiv) (grub_uint32_t a, grub_uint32_t b);
grub_uint32_t
EXPORT_FUNC (__aeabi_uidivmod) (grub_uint32_t a, grub_uint32_t b);
grub_int32_t
EXPORT_FUNC (__aeabi_idiv) (grub_int32_t a, grub_int32_t b);
grub_int32_t
EXPORT_FUNC (__aeabi_idivmod) (grub_int32_t a, grub_int32_t b);
int
EXPORT_FUNC (__aeabi_ulcmp) (grub_uint64_t a, grub_uint64_t b);
/* Needed for allowing modules to be compiled as thumb. */
grub_uint64_t
EXPORT_FUNC (__muldi3) (grub_uint64_t a, grub_uint64_t b);
grub_uint64_t
EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b);
void *
EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n);
void *
EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n);
grub_uint64_t
EXPORT_FUNC (__aeabi_lasr) (grub_uint64_t u, int b);
grub_uint64_t
EXPORT_FUNC (__aeabi_llsl) (grub_uint64_t u, int b);
grub_uint64_t
EXPORT_FUNC (__aeabi_llsr) (grub_uint64_t u, int b);
#endif
#if defined (__powerpc__)
void EXPORT_FUNC (_restgpr_14_x) (void);
void EXPORT_FUNC (_restgpr_15_x) (void);
void EXPORT_FUNC (_restgpr_16_x) (void);
void EXPORT_FUNC (_restgpr_17_x) (void);
void EXPORT_FUNC (_restgpr_18_x) (void);
void EXPORT_FUNC (_restgpr_19_x) (void);
void EXPORT_FUNC (_restgpr_20_x) (void);
void EXPORT_FUNC (_restgpr_21_x) (void);
void EXPORT_FUNC (_restgpr_22_x) (void);
void EXPORT_FUNC (_restgpr_23_x) (void);
void EXPORT_FUNC (_restgpr_24_x) (void);
void EXPORT_FUNC (_restgpr_25_x) (void);
void EXPORT_FUNC (_restgpr_26_x) (void);
void EXPORT_FUNC (_restgpr_27_x) (void);
void EXPORT_FUNC (_restgpr_28_x) (void);
void EXPORT_FUNC (_restgpr_29_x) (void);
void EXPORT_FUNC (_restgpr_30_x) (void);
void EXPORT_FUNC (_restgpr_31_x) (void);
void EXPORT_FUNC (_savegpr_14) (void);
void EXPORT_FUNC (_savegpr_15) (void);
void EXPORT_FUNC (_savegpr_16) (void);
void EXPORT_FUNC (_savegpr_17) (void);
void EXPORT_FUNC (_savegpr_18) (void);
void EXPORT_FUNC (_savegpr_19) (void);
void EXPORT_FUNC (_savegpr_20) (void);
void EXPORT_FUNC (_savegpr_21) (void);
void EXPORT_FUNC (_savegpr_22) (void);
void EXPORT_FUNC (_savegpr_23) (void);
void EXPORT_FUNC (_savegpr_24) (void);
void EXPORT_FUNC (_savegpr_25) (void);
void EXPORT_FUNC (_savegpr_26) (void);
void EXPORT_FUNC (_savegpr_27) (void);
void EXPORT_FUNC (_savegpr_28) (void);
void EXPORT_FUNC (_savegpr_29) (void);
void EXPORT_FUNC (_savegpr_30) (void);
void EXPORT_FUNC (_savegpr_31) (void);
#endif
#if defined (__powerpc__) || defined(__mips__) || defined (__arm__)
int
EXPORT_FUNC(__ucmpdi2) (grub_uint64_t a, grub_uint64_t b);
grub_uint64_t
EXPORT_FUNC(__ashldi3) (grub_uint64_t u, int b);
grub_uint64_t
EXPORT_FUNC(__ashrdi3) (grub_uint64_t u, int b);
grub_uint64_t
EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b);
#endif
#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || defined (__arm__)
grub_uint32_t
EXPORT_FUNC(__bswapsi2) (grub_uint32_t u);
grub_uint64_t
EXPORT_FUNC(__bswapdi2) (grub_uint64_t u);
#endif
#if defined (__APPLE__) && defined(__i386__)
#define GRUB_BUILTIN_ATTR __attribute__ ((regparm(0)))
#else
#define GRUB_BUILTIN_ATTR
#endif
/* Prototypes for aliases. */
int GRUB_BUILTIN_ATTR EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n);
void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n);
void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n);
void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memset) (void *s, int c, grub_size_t n);
#ifdef __APPLE__
void GRUB_BUILTIN_ATTR EXPORT_FUNC (__bzero) (void *s, grub_size_t n);
#endif
#if defined (__MINGW32__) || defined (__CYGWIN__)
void EXPORT_FUNC (__register_frame_info) (void);
void EXPORT_FUNC (__deregister_frame_info) (void);
void EXPORT_FUNC (___chkstk_ms) (void);
void EXPORT_FUNC (__chkstk_ms) (void);
#endif
#endif

View File

@ -1,91 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/* We need to include config-util.h.in for HAVE_*. */
#ifndef __STDC_VERSION__
#define __STDC_VERSION__ 0
#endif
#include <config-util.h>
/* On x86 these functions aren't really needed. Save some space. */
#if !defined (__i386__) && !defined (__x86_64__)
# ifdef HAVE___ASHLDI3
void EXPORT_FUNC (__ashldi3) (void);
# endif
# ifdef HAVE___ASHRDI3
void EXPORT_FUNC (__ashrdi3) (void);
# endif
# ifdef HAVE___LSHRDI3
void EXPORT_FUNC (__lshrdi3) (void);
# endif
# ifdef HAVE___UCMPDI2
void EXPORT_FUNC (__ucmpdi2) (void);
# endif
# ifdef HAVE___BSWAPSI2
void EXPORT_FUNC (__bswapsi2) (void);
# endif
# ifdef HAVE___BSWAPDI2
void EXPORT_FUNC (__bswapdi2) (void);
# endif
#endif
#ifdef HAVE__RESTGPR_14_X
void EXPORT_FUNC (_restgpr_14_x) (void);
void EXPORT_FUNC (_restgpr_15_x) (void);
void EXPORT_FUNC (_restgpr_16_x) (void);
void EXPORT_FUNC (_restgpr_17_x) (void);
void EXPORT_FUNC (_restgpr_18_x) (void);
void EXPORT_FUNC (_restgpr_19_x) (void);
void EXPORT_FUNC (_restgpr_20_x) (void);
void EXPORT_FUNC (_restgpr_21_x) (void);
void EXPORT_FUNC (_restgpr_22_x) (void);
void EXPORT_FUNC (_restgpr_23_x) (void);
void EXPORT_FUNC (_restgpr_24_x) (void);
void EXPORT_FUNC (_restgpr_25_x) (void);
void EXPORT_FUNC (_restgpr_26_x) (void);
void EXPORT_FUNC (_restgpr_27_x) (void);
void EXPORT_FUNC (_restgpr_28_x) (void);
void EXPORT_FUNC (_restgpr_29_x) (void);
void EXPORT_FUNC (_restgpr_30_x) (void);
void EXPORT_FUNC (_restgpr_31_x) (void);
void EXPORT_FUNC (_savegpr_14) (void);
void EXPORT_FUNC (_savegpr_15) (void);
void EXPORT_FUNC (_savegpr_16) (void);
void EXPORT_FUNC (_savegpr_17) (void);
void EXPORT_FUNC (_savegpr_18) (void);
void EXPORT_FUNC (_savegpr_19) (void);
void EXPORT_FUNC (_savegpr_20) (void);
void EXPORT_FUNC (_savegpr_21) (void);
void EXPORT_FUNC (_savegpr_22) (void);
void EXPORT_FUNC (_savegpr_23) (void);
void EXPORT_FUNC (_savegpr_24) (void);
void EXPORT_FUNC (_savegpr_25) (void);
void EXPORT_FUNC (_savegpr_26) (void);
void EXPORT_FUNC (_savegpr_27) (void);
void EXPORT_FUNC (_savegpr_28) (void);
void EXPORT_FUNC (_savegpr_29) (void);
void EXPORT_FUNC (_savegpr_30) (void);
void EXPORT_FUNC (_savegpr_31) (void);
#endif
#if defined (__arm__)
void EXPORT_FUNC (__aeabi_lasr) (void);
void EXPORT_FUNC (__aeabi_llsl) (void);
void EXPORT_FUNC (__aeabi_llsr) (void);
void EXPORT_FUNC (__aeabi_ulcmp) (void);
#endif

View File

@ -71,12 +71,6 @@ grub_memcpy (void *dest, const void *src, grub_size_t n)
return grub_memmove (dest, src, n);
}
#if defined (__APPLE__) && defined(__i386__) && !defined (GRUB_UTIL)
#define GRUB_BUILTIN_ATTR __attribute__ ((regparm(0)))
#else
#define GRUB_BUILTIN_ATTR
#endif
#if defined(__x86_64__) && !defined (GRUB_UTIL)
#if defined (__MINGW32__) || defined (__CYGWIN__) || defined (__MINGW64__)
#define GRUB_ASM_ATTR __attribute__ ((sysv_abi))
@ -85,19 +79,6 @@ grub_memcpy (void *dest, const void *src, grub_size_t n)
#endif
#endif
/* Prototypes for aliases. */
#ifndef GRUB_UTIL
int GRUB_BUILTIN_ATTR EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n);
void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n);
void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n);
void *GRUB_BUILTIN_ATTR EXPORT_FUNC(memset) (void *s, int c, grub_size_t n);
#ifdef __APPLE__
void GRUB_BUILTIN_ATTR EXPORT_FUNC (__bzero) (void *s, grub_size_t n);
#endif
#endif
int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n);
int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2);
int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n);
@ -378,6 +359,7 @@ grub_int64_t
EXPORT_FUNC_IF_SOFTDIV(grub_divmod64s) (grub_int64_t n,
grub_int64_t d,
grub_int64_t *r);
grub_uint32_t
EXPORT_FUNC_IF_SOFTDIV (grub_divmod32) (grub_uint32_t n,
grub_uint32_t d,
@ -388,41 +370,6 @@ EXPORT_FUNC_IF_SOFTDIV (grub_divmod32s) (grub_int32_t n,
grub_int32_t d,
grub_int32_t *r);
#if defined(GRUB_DIVISION_IN_SOFTWARE) && GRUB_DIVISION_IN_SOFTWARE
grub_uint32_t
EXPORT_FUNC (__udivsi3) (grub_uint32_t a, grub_uint32_t b);
grub_uint32_t
EXPORT_FUNC (__umodsi3) (grub_uint32_t a, grub_uint32_t b);
grub_int32_t
EXPORT_FUNC (__divsi3) (grub_int32_t a, grub_int32_t b);
grub_int32_t
EXPORT_FUNC (__modsi3) (grub_int32_t a, grub_int32_t b);
grub_int64_t
EXPORT_FUNC (__divdi3) (grub_int64_t a, grub_int64_t b);
grub_int64_t
EXPORT_FUNC (__moddi3) (grub_int64_t a, grub_int64_t b);
grub_uint64_t
EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b);
grub_uint64_t
EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b);
#endif
#if (defined (__MINGW32__) || defined (__CYGWIN__)) && !defined(GRUB_UTIL)
void EXPORT_FUNC (__register_frame_info) (void);
void EXPORT_FUNC (__deregister_frame_info) (void);
void EXPORT_FUNC (___chkstk_ms) (void);
void EXPORT_FUNC (__chkstk_ms) (void);
#endif
/* Inline functions. */
static inline char *
@ -491,50 +438,6 @@ grub_error_load (const struct grub_error_saved *save)
grub_errno = save->grub_errno;
}
#ifndef GRUB_UTIL
#if defined (__arm__)
#endif
#if defined (__sparc__) || defined (__powerpc__)
unsigned
EXPORT_FUNC (__ctzdi2) (grub_uint64_t x);
#define NEED_CTZDI2 1
#endif
#if defined (__mips__) || defined (__arm__)
unsigned
EXPORT_FUNC (__ctzsi2) (grub_uint32_t x);
#define NEED_CTZSI2 1
#endif
#ifdef __arm__
grub_uint32_t
EXPORT_FUNC (__aeabi_uidiv) (grub_uint32_t a, grub_uint32_t b);
grub_int32_t
EXPORT_FUNC (__aeabi_idiv) (grub_int32_t a, grub_int32_t b);
grub_uint32_t
EXPORT_FUNC (__aeabi_uidivmod) (grub_uint32_t a, grub_uint32_t b);
grub_int32_t
EXPORT_FUNC (__aeabi_idivmod) (grub_int32_t a, grub_int32_t b);
/* Needed for allowing modules to be compiled as thumb. */
grub_uint64_t
EXPORT_FUNC (__muldi3) (grub_uint64_t a, grub_uint64_t b);
grub_uint64_t
EXPORT_FUNC (__aeabi_lmul) (grub_uint64_t a, grub_uint64_t b);
void *
EXPORT_FUNC (__aeabi_memcpy) (void *dest, const void *src, grub_size_t n);
void *
EXPORT_FUNC(__aeabi_memset) (void *s, int c, grub_size_t n);
#endif
#endif /* GRUB_UTIL */
#if BOOT_TIME_STATS
struct grub_boot_time
{

View File

@ -21,6 +21,8 @@
#define __XEN_INTERFACE_VERSION__ 0x0003020a
#define memset grub_memset
#ifdef ASM_FILE
#define __ASSEMBLY__
#include <xen/xen.h>