When both "dest" and "src" are aligned, copying the data in chunks
(unsigned long) is more efficient than a byte-by-byte copy.

Also tweak '__aeabi_memcpy()', '__aeabi_memcpy4()', and
'__aeabi_memcpy8()', since 'grub_memcpy()' is not inline anymore.

Signed-off-by: Gary Lin <g...@suse.com>
---
 grub-core/kern/compiler-rt.c |  8 ++++----
 grub-core/kern/misc.c        | 30 ++++++++++++++++++++++++++++++
 include/grub/misc.h          |  8 +-------
 3 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
index eda689a0c..8f3865e95 100644
--- a/grub-core/kern/compiler-rt.c
+++ b/grub-core/kern/compiler-rt.c
@@ -24,7 +24,7 @@
 void * GRUB_BUILTIN_ATTR
 memcpy (void *dest, const void *src, grub_size_t n)
 {
-       return grub_memmove (dest, src, n);
+       return grub_memcpy (dest, src, n);
 }
 void * GRUB_BUILTIN_ATTR
 memmove (void *dest, const void *src, grub_size_t n)
@@ -372,11 +372,11 @@ 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")));
+  __attribute__ ((alias ("memcpy")));
 void *__aeabi_memcpy4 (void *dest, const void *src, grub_size_t n)
-  __attribute__ ((alias ("grub_memcpy")));
+  __attribute__ ((alias ("memcpy")));
 void *__aeabi_memcpy8 (void *dest, const void *src, grub_size_t n)
-  __attribute__ ((alias ("grub_memcpy")));
+  __attribute__ ((alias ("memcpy")));
 void *__aeabi_memset (void *s, int c, grub_size_t n)
   __attribute__ ((alias ("memset")));
 
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 2b7922393..016932583 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -99,6 +99,36 @@ grub_memmove (void *dest, const void *src, grub_size_t n)
   return dest;
 }
 
+static void *
+__memcpy_aligned (void *dest, const void *src, grub_size_t n)
+{
+  unsigned long *dw = (unsigned long *) dest;
+  const unsigned long *sw = (const unsigned long *) src;
+  grub_uint8_t *d;
+  const grub_uint8_t *s;
+
+  for (; n >= sizeof (unsigned long); n -= sizeof (unsigned long))
+    *dw++ = *sw++;
+
+  d = (grub_uint8_t *) dw;
+  s = (const grub_uint8_t *) sw;
+  for (; n > 0; n--)
+    *d++ = *s++;
+
+  return dest;
+}
+
+void *
+grub_memcpy (void *dest, const void *src, grub_size_t n)
+{
+  /* Check if 'dest' and 'src' are aligned */
+  if (((grub_addr_t) dest & (sizeof (unsigned long) - 1)) == 0 &&
+      ((grub_addr_t) src & (sizeof (unsigned long) - 1)) == 0)
+    return __memcpy_aligned (dest, src, n);
+
+  return grub_memmove (dest, src, n);
+}
+
 char *
 grub_strcpy (char *dest, const char *src)
 {
diff --git a/include/grub/misc.h b/include/grub/misc.h
index e087e7b3e..b6b14ca55 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -38,6 +38,7 @@
 #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, 
condition, __VA_ARGS__)
 
 void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
+void *EXPORT_FUNC(grub_memcpy) (void *dest, const void *src, grub_size_t n);
 char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
 
 static inline char *
@@ -103,13 +104,6 @@ grub_strlcpy (char *dest, const char *src, grub_size_t 
size)
   return res;
 }
 
-/* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
-static inline void *
-grub_memcpy (void *dest, const void *src, grub_size_t n)
-{
-  return grub_memmove (dest, src, n);
-}
-
 #if defined(__x86_64__) && !defined (GRUB_UTIL)
 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (__MINGW64__)
 #define GRUB_ASM_ATTR __attribute__ ((sysv_abi))
-- 
2.51.0


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to