From: "Martin Storsjö" Subject: [PATCH v2] msvcrt: Avoid disallowed unaligned writes in memset on ARM Message-Id: <20210916092540.902864-1-martin@martin.st> Date: Thu, 16 Sep 2021 12:25:40 +0300 This fixes a regression in memset on ARM since 7b17d7081512db52ef852705445762ac4016c29f. ARM can do 64 bit writes with the STRD instruction, but that instruction requires a 32 bit aligned address - while these stores are unaligned. Two consecutive stores to uint32_t* pointers can also be fused into one single STRD, as a uint32_t* is supposed to be properly aligned - therefore, do these stores as stores to volatile uint32_t* to avoid fusing them. Signed-off-by: Martin Storsjö --- v2: Using a macro to hide the difference. --- dlls/msvcrt/string.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index f2b1b4a5b11..6fade4d80fc 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -2876,17 +2876,28 @@ void *__cdecl memset(void *dst, int c, size_t n) unsigned char *d = (unsigned char *)dst; size_t a = 0x20 - ((uintptr_t)d & 0x1f); +#ifdef __arm__ +#define MEMSET_UNALIGNED_64(dst, off, val) do { \ + *(volatile uint32_t *)((dst) + (off) + 0) = val; \ + *(volatile uint32_t *)((dst) + (off) + 4) = val; \ + } while (0) +#else +#define MEMSET_UNALIGNED_64(dst, off, val) do { \ + *(uint64_t *)((dst) + (off)) = val; \ + } while (0) +#endif + if (n >= 16) { - *(uint64_t *)(d + 0) = v; - *(uint64_t *)(d + 8) = v; - *(uint64_t *)(d + n - 16) = v; - *(uint64_t *)(d + n - 8) = v; + MEMSET_UNALIGNED_64(d, 0, v); + MEMSET_UNALIGNED_64(d, 8, v); + MEMSET_UNALIGNED_64(d, n - 16, v); + MEMSET_UNALIGNED_64(d, n - 8, v); if (n <= 32) return dst; - *(uint64_t *)(d + 16) = v; - *(uint64_t *)(d + 24) = v; - *(uint64_t *)(d + n - 32) = v; - *(uint64_t *)(d + n - 24) = v; + MEMSET_UNALIGNED_64(d, 16, v); + MEMSET_UNALIGNED_64(d, 24, v); + MEMSET_UNALIGNED_64(d, n - 32, v); + MEMSET_UNALIGNED_64(d, n - 24, v); if (n <= 64) return dst; n = (n - a) & ~0x1f; @@ -2895,8 +2906,8 @@ void *__cdecl memset(void *dst, int c, size_t n) } if (n >= 8) { - *(uint64_t *)d = v; - *(uint64_t *)(d + n - 8) = v; + MEMSET_UNALIGNED_64(d, 0, v); + MEMSET_UNALIGNED_64(d, n - 8, v); return dst; } if (n >= 4) @@ -2916,6 +2927,7 @@ void *__cdecl memset(void *dst, int c, size_t n) *(uint8_t *)d = v; return dst; } +#undef MEMSET_UNALIGNED_64 return dst; } -- 2.25.1