riscv: optimized memset
[platform/kernel/linux-starfive.git] / arch / riscv / lib / string.c
index bd52581..7fc9ec5 100644 (file)
@@ -112,3 +112,44 @@ EXPORT_SYMBOL(__memmove);
 
 void *memmove(void *dest, const void *src, size_t count) __weak __alias(__memmove);
 EXPORT_SYMBOL(memmove);
+
+void *__memset(void *s, int c, size_t count)
+{
+       union types dest = { .as_u8 = s };
+
+       if (count >= MIN_THRESHOLD) {
+               unsigned long cu = (unsigned long)c;
+
+               /* Compose an ulong with 'c' repeated 4/8 times */
+#ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER
+               cu *= 0x0101010101010101UL;
+#else
+               cu |= cu << 8;
+               cu |= cu << 16;
+               /* Suppress warning on 32 bit machines */
+               cu |= (cu << 16) << 16;
+#endif
+               if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) {
+                       /*
+                        * Fill the buffer one byte at time until
+                        * the destination is word aligned.
+                        */
+                       for (; count && dest.as_uptr & WORD_MASK; count--)
+                               *dest.as_u8++ = c;
+               }
+
+               /* Copy using the largest size allowed */
+               for (; count >= BYTES_LONG; count -= BYTES_LONG)
+                       *dest.as_ulong++ = cu;
+       }
+
+       /* copy the remainder */
+       while (count--)
+               *dest.as_u8++ = c;
+
+       return s;
+}
+EXPORT_SYMBOL(__memset);
+
+void *memset(void *s, int c, size_t count) __weak __alias(__memset);
+EXPORT_SYMBOL(memset);