1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * arch/openrisc/lib/memcpy.c 4 * 5 * Optimized memory copy routines for openrisc. These are mostly copied 6 * from ohter sources but slightly entended based on ideas discuassed in 7 * #openrisc. 8 * 9 * The word unroll implementation is an extension to the arm byte 10 * unrolled implementation, but using word copies (if things are 11 * properly aligned) 12 * 13 * The great arm loop unroll algorithm can be found at: 14 * arch/arm/boot/compressed/string.c 15 */ 16 17 #include <linux/export.h> 18 19 #include <linux/string.h> 20 21 #ifdef CONFIG_OR1K_1200 22 /* 23 * Do memcpy with word copies and loop unrolling. This gives the 24 * best performance on the OR1200 and MOR1KX archirectures 25 */ 26 void *memcpy(void *dest, __const void *src, __kernel_size_t n) 27 { 28 int i = 0; 29 unsigned char *d, *s; 30 uint32_t *dest_w = (uint32_t *)dest, *src_w = (uint32_t *)src; 31 32 /* If both source and dest are word aligned copy words */ 33 if (!((unsigned int)dest_w & 3) && !((unsigned int)src_w & 3)) { 34 /* Copy 32 bytes per loop */ 35 for (i = n >> 5; i > 0; i--) { 36 *dest_w++ = *src_w++; 37 *dest_w++ = *src_w++; 38 *dest_w++ = *src_w++; 39 *dest_w++ = *src_w++; 40 *dest_w++ = *src_w++; 41 *dest_w++ = *src_w++; 42 *dest_w++ = *src_w++; 43 *dest_w++ = *src_w++; 44 } 45 46 if (n & 1 << 4) { 47 *dest_w++ = *src_w++; 48 *dest_w++ = *src_w++; 49 *dest_w++ = *src_w++; 50 *dest_w++ = *src_w++; 51 } 52 53 if (n & 1 << 3) { 54 *dest_w++ = *src_w++; 55 *dest_w++ = *src_w++; 56 } 57 58 if (n & 1 << 2) 59 *dest_w++ = *src_w++; 60 61 d = (unsigned char *)dest_w; 62 s = (unsigned char *)src_w; 63 64 } else { 65 d = (unsigned char *)dest_w; 66 s = (unsigned char *)src_w; 67 68 for (i = n >> 3; i > 0; i--) { 69 *d++ = *s++; 70 *d++ = *s++; 71 *d++ = *s++; 72 *d++ = *s++; 73 *d++ = *s++; 74 *d++ = *s++; 75 *d++ = *s++; 76 *d++ = *s++; 77 } 78 79 if (n & 1 << 2) { 80 *d++ = *s++; 81 *d++ = *s++; 82 *d++ = *s++; 83 *d++ = *s++; 84 } 85 } 86 87 if (n & 1 << 1) { 88 *d++ = *s++; 89 *d++ = *s++; 90 } 91 92 if (n & 1) 93 *d++ = *s++; 94 95 return dest; 96 } 97 #else 98 /* 99 * Use word copies but no loop unrolling as we cannot assume there 100 * will be benefits on the archirecture 101 */ 102 void *memcpy(void *dest, __const void *src, __kernel_size_t n) 103 { 104 unsigned char *d = (unsigned char *)dest, *s = (unsigned char *)src; 105 uint32_t *dest_w = (uint32_t *)dest, *src_w = (uint32_t *)src; 106 107 /* If both source and dest are word aligned copy words */ 108 if (!((unsigned int)dest_w & 3) && !((unsigned int)src_w & 3)) { 109 for (; n >= 4; n -= 4) 110 *dest_w++ = *src_w++; 111 } 112 113 d = (unsigned char *)dest_w; 114 s = (unsigned char *)src_w; 115 116 /* For remaining or if not aligned, copy bytes */ 117 for (; n >= 1; n -= 1) 118 *d++ = *s++; 119 120 return dest; 121 122 } 123 #endif 124 125 EXPORT_SYMBOL(memcpy); 126