| /* |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. See the file COPYING in the main directory of this archive |
| * for more details. |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/string.h> |
| |
| void *memmove(void *dest, const void *src, size_t n) |
| { |
| void *xdest = dest; |
| size_t temp; |
| |
| if (!n) |
| return xdest; |
| |
| if (dest < src) { |
| if ((long)dest & 1) { |
| char *cdest = dest; |
| const char *csrc = src; |
| *cdest++ = *csrc++; |
| dest = cdest; |
| src = csrc; |
| n--; |
| } |
| if (n > 2 && (long)dest & 2) { |
| short *sdest = dest; |
| const short *ssrc = src; |
| *sdest++ = *ssrc++; |
| dest = sdest; |
| src = ssrc; |
| n -= 2; |
| } |
| temp = n >> 2; |
| if (temp) { |
| long *ldest = dest; |
| const long *lsrc = src; |
| temp--; |
| do |
| *ldest++ = *lsrc++; |
| while (temp--); |
| dest = ldest; |
| src = lsrc; |
| } |
| if (n & 2) { |
| short *sdest = dest; |
| const short *ssrc = src; |
| *sdest++ = *ssrc++; |
| dest = sdest; |
| src = ssrc; |
| } |
| if (n & 1) { |
| char *cdest = dest; |
| const char *csrc = src; |
| *cdest = *csrc; |
| } |
| } else { |
| dest = (char *)dest + n; |
| src = (const char *)src + n; |
| if ((long)dest & 1) { |
| char *cdest = dest; |
| const char *csrc = src; |
| *--cdest = *--csrc; |
| dest = cdest; |
| src = csrc; |
| n--; |
| } |
| if (n > 2 && (long)dest & 2) { |
| short *sdest = dest; |
| const short *ssrc = src; |
| *--sdest = *--ssrc; |
| dest = sdest; |
| src = ssrc; |
| n -= 2; |
| } |
| temp = n >> 2; |
| if (temp) { |
| long *ldest = dest; |
| const long *lsrc = src; |
| temp--; |
| do |
| *--ldest = *--lsrc; |
| while (temp--); |
| dest = ldest; |
| src = lsrc; |
| } |
| if (n & 2) { |
| short *sdest = dest; |
| const short *ssrc = src; |
| *--sdest = *--ssrc; |
| dest = sdest; |
| src = ssrc; |
| } |
| if (n & 1) { |
| char *cdest = dest; |
| const char *csrc = src; |
| *--cdest = *--csrc; |
| } |
| } |
| return xdest; |
| } |
| EXPORT_SYMBOL(memmove); |