Piotr Caban : msvcrt: Optimize memmove implementation.
Alexandre Julliard
julliard at winehq.org
Fri Aug 21 16:43:26 CDT 2020
Module: wine
Branch: master
Commit: dd90fdda0e8b8f4b0c669d637193ffdddd1de820
URL: https://source.winehq.org/git/wine.git/?a=commit;h=dd90fdda0e8b8f4b0c669d637193ffdddd1de820
Author: Piotr Caban <piotr at codeweavers.com>
Date: Thu Aug 20 20:00:42 2020 +0200
msvcrt: Optimize memmove implementation.
Based on Torbjorn Granlund code from Glibc.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49663
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcrt/string.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 87 insertions(+), 4 deletions(-)
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index ab6747db5c..3343f1e3cc 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -2483,23 +2483,106 @@ int __cdecl MSVCRT_memcmp(const void *ptr1, const void *ptr2, MSVCRT_size_t n)
/*********************************************************************
* memmove (MSVCRT.@)
*/
+#ifdef WORDS_BIGENDIAN
+# define MERGE(w1, sh1, w2, sh2) ((w1 << sh1) | (w2 >> sh2))
+#else
+# define MERGE(w1, sh1, w2, sh2) ((w1 >> sh1) | (w2 << sh2))
+#endif
void * __cdecl MSVCRT_memmove(void *dst, const void *src, MSVCRT_size_t n)
{
- volatile unsigned char *d = dst; /* avoid gcc optimizations */
+ unsigned char *d = dst;
const unsigned char *s = src;
+ int sh1;
+
+ if (!n) return dst;
if ((MSVCRT_size_t)dst - (MSVCRT_size_t)src >= n)
{
+ for (; (MSVCRT_size_t)d % sizeof(MSVCRT_size_t) && n; n--) *d++ = *s++;
+
+ sh1 = 8 * ((MSVCRT_size_t)s % sizeof(MSVCRT_size_t));
+ if (!sh1)
+ {
+ while (n >= sizeof(MSVCRT_size_t))
+ {
+ *(MSVCRT_size_t*)d = *(MSVCRT_size_t*)s;
+ s += sizeof(MSVCRT_size_t);
+ d += sizeof(MSVCRT_size_t);
+ n -= sizeof(MSVCRT_size_t);
+ }
+ }
+ else if (n >= 2 * sizeof(MSVCRT_size_t))
+ {
+ int sh2 = 8 * sizeof(MSVCRT_size_t) - sh1;
+ MSVCRT_size_t x, y;
+
+ s -= sh1 / 8;
+ x = *(MSVCRT_size_t*)s;
+ do
+ {
+ s += sizeof(MSVCRT_size_t);
+ y = *(MSVCRT_size_t*)s;
+ *(MSVCRT_size_t*)d = MERGE(x, sh1, y, sh2);
+ d += sizeof(MSVCRT_size_t);
+
+ s += sizeof(MSVCRT_size_t);
+ x = *(MSVCRT_size_t*)s;
+ *(MSVCRT_size_t*)d = MERGE(y, sh1, x, sh2);
+ d += sizeof(MSVCRT_size_t);
+
+ n -= 2 * sizeof(MSVCRT_size_t);
+ } while (n >= 2 * sizeof(MSVCRT_size_t));
+ s += sh1 / 8;
+ }
while (n--) *d++ = *s++;
+ return dst;
}
else
{
- d += n - 1;
- s += n - 1;
- while (n--) *d-- = *s--;
+ d += n;
+ s += n;
+
+ for (; (MSVCRT_size_t)d % sizeof(MSVCRT_size_t) && n; n--) *--d = *--s;
+
+ sh1 = 8 * ((MSVCRT_size_t)s % sizeof(MSVCRT_size_t));
+ if (!sh1)
+ {
+ while (n >= sizeof(MSVCRT_size_t))
+ {
+ s -= sizeof(MSVCRT_size_t);
+ d -= sizeof(MSVCRT_size_t);
+ *(MSVCRT_size_t*)d = *(MSVCRT_size_t*)s;
+ n -= sizeof(MSVCRT_size_t);
+ }
+ }
+ else if (n >= 2 * sizeof(MSVCRT_size_t))
+ {
+ int sh2 = 8 * sizeof(MSVCRT_size_t) - sh1;
+ MSVCRT_size_t x, y;
+
+ s -= sh1 / 8;
+ x = *(MSVCRT_size_t*)s;
+ do
+ {
+ s -= sizeof(MSVCRT_size_t);
+ y = *(MSVCRT_size_t*)s;
+ d -= sizeof(MSVCRT_size_t);
+ *(MSVCRT_size_t*)d = MERGE(y, sh1, x, sh2);
+
+ s -= sizeof(MSVCRT_size_t);
+ x = *(MSVCRT_size_t*)s;
+ d -= sizeof(MSVCRT_size_t);
+ *(MSVCRT_size_t*)d = MERGE(x, sh1, y, sh2);
+
+ n -= 2 * sizeof(MSVCRT_size_t);
+ } while (n >= 2 * sizeof(MSVCRT_size_t));
+ s += sh1 / 8;
+ }
+ while (n--) *--d = *--s;
}
return dst;
}
+#undef MERGE
/*********************************************************************
* memcpy (MSVCRT.@)
More information about the wine-cvs
mailing list