aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/lib/memmove.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/lib/memmove.c')
-rw-r--r--arch/microblaze/lib/memmove.c59
1 files changed, 48 insertions, 11 deletions
diff --git a/arch/microblaze/lib/memmove.c b/arch/microblaze/lib/memmove.c
index 0929198c5e68..123e3616f2dd 100644
--- a/arch/microblaze/lib/memmove.c
+++ b/arch/microblaze/lib/memmove.c
@@ -31,16 +31,12 @@
31#include <linux/string.h> 31#include <linux/string.h>
32 32
33#ifdef __HAVE_ARCH_MEMMOVE 33#ifdef __HAVE_ARCH_MEMMOVE
34#ifndef CONFIG_OPT_LIB_FUNCTION
34void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) 35void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
35{ 36{
36 const char *src = v_src; 37 const char *src = v_src;
37 char *dst = v_dst; 38 char *dst = v_dst;
38 39
39#ifdef CONFIG_OPT_LIB_FUNCTION
40 const uint32_t *i_src;
41 uint32_t *i_dst;
42#endif
43
44 if (!c) 40 if (!c)
45 return v_dst; 41 return v_dst;
46 42
@@ -48,7 +44,6 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
48 if (v_dst <= v_src) 44 if (v_dst <= v_src)
49 return memcpy(v_dst, v_src, c); 45 return memcpy(v_dst, v_src, c);
50 46
51#ifndef CONFIG_OPT_LIB_FUNCTION
52 /* copy backwards, from end to beginning */ 47 /* copy backwards, from end to beginning */
53 src += c; 48 src += c;
54 dst += c; 49 dst += c;
@@ -58,7 +53,22 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
58 *--dst = *--src; 53 *--dst = *--src;
59 54
60 return v_dst; 55 return v_dst;
61#else 56}
57#else /* CONFIG_OPT_LIB_FUNCTION */
58void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
59{
60 const char *src = v_src;
61 char *dst = v_dst;
62 const uint32_t *i_src;
63 uint32_t *i_dst;
64
65 if (!c)
66 return v_dst;
67
68 /* Use memcpy when source is higher than dest */
69 if (v_dst <= v_src)
70 return memcpy(v_dst, v_src, c);
71
62 /* The following code tries to optimize the copy by using unsigned 72 /* The following code tries to optimize the copy by using unsigned
63 * alignment. This will work fine if both source and destination are 73 * alignment. This will work fine if both source and destination are
64 * aligned on the same boundary. However, if they are aligned on 74 * aligned on the same boundary. However, if they are aligned on
@@ -104,7 +114,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
104 case 0x1: /* Unaligned - Off by 1 */ 114 case 0x1: /* Unaligned - Off by 1 */
105 /* Word align the source */ 115 /* Word align the source */
106 i_src = (const void *) (((unsigned)src + 4) & ~3); 116 i_src = (const void *) (((unsigned)src + 4) & ~3);
107 117#ifndef __MICROBLAZEEL__
108 /* Load the holding buffer */ 118 /* Load the holding buffer */
109 buf_hold = *--i_src >> 24; 119 buf_hold = *--i_src >> 24;
110 120
@@ -113,7 +123,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
113 *--i_dst = buf_hold << 8 | value; 123 *--i_dst = buf_hold << 8 | value;
114 buf_hold = value >> 24; 124 buf_hold = value >> 24;
115 } 125 }
126#else
127 /* Load the holding buffer */
128 buf_hold = (*--i_src & 0xFF) << 24;
116 129
130 for (; c >= 4; c -= 4) {
131 value = *--i_src;
132 *--i_dst = buf_hold | ((value & 0xFFFFFF00)>>8);
133 buf_hold = (value & 0xFF) << 24;
134 }
135#endif
117 /* Realign the source */ 136 /* Realign the source */
118 src = (const void *)i_src; 137 src = (const void *)i_src;
119 src += 1; 138 src += 1;
@@ -121,7 +140,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
121 case 0x2: /* Unaligned - Off by 2 */ 140 case 0x2: /* Unaligned - Off by 2 */
122 /* Word align the source */ 141 /* Word align the source */
123 i_src = (const void *) (((unsigned)src + 4) & ~3); 142 i_src = (const void *) (((unsigned)src + 4) & ~3);
124 143#ifndef __MICROBLAZEEL__
125 /* Load the holding buffer */ 144 /* Load the holding buffer */
126 buf_hold = *--i_src >> 16; 145 buf_hold = *--i_src >> 16;
127 146
@@ -130,7 +149,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
130 *--i_dst = buf_hold << 16 | value; 149 *--i_dst = buf_hold << 16 | value;
131 buf_hold = value >> 16; 150 buf_hold = value >> 16;
132 } 151 }
152#else
153 /* Load the holding buffer */
154 buf_hold = (*--i_src & 0xFFFF) << 16;
133 155
156 for (; c >= 4; c -= 4) {
157 value = *--i_src;
158 *--i_dst = buf_hold | ((value & 0xFFFF0000)>>16);
159 buf_hold = (value & 0xFFFF) << 16;
160 }
161#endif
134 /* Realign the source */ 162 /* Realign the source */
135 src = (const void *)i_src; 163 src = (const void *)i_src;
136 src += 2; 164 src += 2;
@@ -138,7 +166,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
138 case 0x3: /* Unaligned - Off by 3 */ 166 case 0x3: /* Unaligned - Off by 3 */
139 /* Word align the source */ 167 /* Word align the source */
140 i_src = (const void *) (((unsigned)src + 4) & ~3); 168 i_src = (const void *) (((unsigned)src + 4) & ~3);
141 169#ifndef __MICROBLAZEEL__
142 /* Load the holding buffer */ 170 /* Load the holding buffer */
143 buf_hold = *--i_src >> 8; 171 buf_hold = *--i_src >> 8;
144 172
@@ -147,7 +175,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
147 *--i_dst = buf_hold << 24 | value; 175 *--i_dst = buf_hold << 24 | value;
148 buf_hold = value >> 8; 176 buf_hold = value >> 8;
149 } 177 }
178#else
179 /* Load the holding buffer */
180 buf_hold = (*--i_src & 0xFFFFFF) << 8;
150 181
182 for (; c >= 4; c -= 4) {
183 value = *--i_src;
184 *--i_dst = buf_hold | ((value & 0xFF000000)>> 24);
185 buf_hold = (value & 0xFFFFFF) << 8;;
186 }
187#endif
151 /* Realign the source */ 188 /* Realign the source */
152 src = (const void *)i_src; 189 src = (const void *)i_src;
153 src += 3; 190 src += 3;
@@ -169,7 +206,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
169 *--dst = *--src; 206 *--dst = *--src;
170 } 207 }
171 return v_dst; 208 return v_dst;
172#endif
173} 209}
210#endif /* CONFIG_OPT_LIB_FUNCTION */
174EXPORT_SYMBOL(memmove); 211EXPORT_SYMBOL(memmove);
175#endif /* __HAVE_ARCH_MEMMOVE */ 212#endif /* __HAVE_ARCH_MEMMOVE */