Blob Blame History Raw
From 064360e6671e0c5f2f47b73fd03b33be8a81f72c Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Tue, 3 Mar 2015 20:23:42 +0100
Subject: [PATCH 351/506] 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.
---
 conf/Makefile.common                         |   4 +-
 config.h.in                                  |   1 +
 configure.ac                                 |  25 +-
 grub-core/Makefile.am                        |   8 +-
 grub-core/Makefile.core.def                  |  43 ++-
 grub-core/boot/decompressor/minilib.c        |  11 +-
 grub-core/kern/arm/{misc.S => compiler-rt.S} |   0
 grub-core/kern/compiler-rt.c                 | 404 +++++++++++++++++++++++++++
 grub-core/kern/misc.c                        | 232 ---------------
 grub-core/kern/powerpc/compiler-rt.S         | 130 +++++++++
 grub-core/lib/posix_wrap/string.h            |  20 +-
 grub-core/tests/bswap_test.c                 | 121 ++++++++
 grub-core/tests/cmp_test.c                   | 190 +++++++++++++
 grub-core/tests/ctz_test.c                   | 111 ++++++++
 grub-core/tests/lib/functional_test.c        |   5 +
 grub-core/tests/mul_test.c                   |  73 +++++
 grub-core/tests/shift_test.c                 | 157 +++++++++++
 include/grub/compiler-rt.h                   | 193 +++++++++++++
 include/grub/libgcc.h                        |  91 ------
 include/grub/misc.h                          |  99 +------
 include/grub/xen.h                           |   2 +
 21 files changed, 1441 insertions(+), 479 deletions(-)
 rename grub-core/kern/arm/{misc.S => compiler-rt.S} (100%)
 create mode 100644 grub-core/kern/compiler-rt.c
 create mode 100644 grub-core/kern/powerpc/compiler-rt.S
 create mode 100644 grub-core/tests/bswap_test.c
 create mode 100644 grub-core/tests/cmp_test.c
 create mode 100644 grub-core/tests/ctz_test.c
 create mode 100644 grub-core/tests/mul_test.c
 create mode 100644 grub-core/tests/shift_test.c
 create mode 100644 include/grub/compiler-rt.h
 delete mode 100644 include/grub/libgcc.h

diff --git a/conf/Makefile.common b/conf/Makefile.common
index 8861096..96e58c9 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -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
diff --git a/config.h.in b/config.h.in
index ea0f383..9e8f991 100644
--- a/config.h.in
+++ b/config.h.in
@@ -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@
diff --git a/configure.ac b/configure.ac
index 9e24d89..be980ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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)
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 5c087c8..57c0b64 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -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
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index b539ccf..7a6fa21 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -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;
 };
 
@@ -1983,6 +1983,31 @@ module = {
 };
 
 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;
 };
diff --git a/grub-core/boot/decompressor/minilib.c b/grub-core/boot/decompressor/minilib.c
index 94edfd5..fc46ee0 100644
--- a/grub-core/boot/decompressor/minilib.c
+++ b/grub-core/boot/decompressor/minilib.c
@@ -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
diff --git a/grub-core/kern/arm/misc.S b/grub-core/kern/arm/compiler-rt.S
similarity index 100%
rename from grub-core/kern/arm/misc.S
rename to grub-core/kern/arm/compiler-rt.S
diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
new file mode 100644
index 0000000..d4cc155
--- /dev/null
+++ b/grub-core/kern/compiler-rt.c
@@ -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
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index b0347e7..906d2c2 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -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>
diff --git a/grub-core/kern/powerpc/compiler-rt.S b/grub-core/kern/powerpc/compiler-rt.S
new file mode 100644
index 0000000..b3b912d
--- /dev/null
+++ b/grub-core/kern/powerpc/compiler-rt.S
@@ -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
diff --git a/grub-core/lib/posix_wrap/string.h b/grub-core/lib/posix_wrap/string.h
index c4b9bf0..7ae6eee 100644
--- a/grub-core/lib/posix_wrap/string.h
+++ b/grub-core/lib/posix_wrap/string.h
@@ -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
diff --git a/grub-core/tests/bswap_test.c b/grub-core/tests/bswap_test.c
new file mode 100644
index 0000000..4eb3a98
--- /dev/null
+++ b/grub-core/tests/bswap_test.c
@@ -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);
diff --git a/grub-core/tests/cmp_test.c b/grub-core/tests/cmp_test.c
new file mode 100644
index 0000000..af5b395
--- /dev/null
+++ b/grub-core/tests/cmp_test.c
@@ -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);
diff --git a/grub-core/tests/ctz_test.c b/grub-core/tests/ctz_test.c
new file mode 100644
index 0000000..eb7a1df
--- /dev/null
+++ b/grub-core/tests/ctz_test.c
@@ -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);
diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c
index 5be7a58..d4822a1 100644
--- a/grub-core/tests/lib/functional_test.c
+++ b/grub-core/tests/lib/functional_test.c
@@ -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;
diff --git a/grub-core/tests/mul_test.c b/grub-core/tests/mul_test.c
new file mode 100644
index 0000000..cd64231
--- /dev/null
+++ b/grub-core/tests/mul_test.c
@@ -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);
diff --git a/grub-core/tests/shift_test.c b/grub-core/tests/shift_test.c
new file mode 100644
index 0000000..4120f52
--- /dev/null
+++ b/grub-core/tests/shift_test.c
@@ -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);
diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
new file mode 100644
index 0000000..9265c7e
--- /dev/null
+++ b/include/grub/compiler-rt.h
@@ -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
+
diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h
deleted file mode 100644
index 8e93b67..0000000
--- a/include/grub/libgcc.h
+++ /dev/null
@@ -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
diff --git a/include/grub/misc.h b/include/grub/misc.h
index a05b3fd..2a9f87c 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -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
 {
diff --git a/include/grub/xen.h b/include/grub/xen.h
index 6035d1a..9ba3b8e 100644
--- a/include/grub/xen.h
+++ b/include/grub/xen.h
@@ -21,6 +21,8 @@
 
 #define __XEN_INTERFACE_VERSION__ 0x0003020a
 
+#define memset grub_memset
+
 #ifdef ASM_FILE
 #define __ASSEMBLY__
 #include <xen/xen.h>
-- 
2.4.3