diff options
Diffstat (limited to 'arch/microblaze/lib/memmove.c')
| -rw-r--r-- | arch/microblaze/lib/memmove.c | 59 |
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 | ||
| 34 | void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) | 35 | void *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 */ | ||
| 58 | void *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 */ | ||
| 174 | EXPORT_SYMBOL(memmove); | 211 | EXPORT_SYMBOL(memmove); |
| 175 | #endif /* __HAVE_ARCH_MEMMOVE */ | 212 | #endif /* __HAVE_ARCH_MEMMOVE */ |
