1/* 2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11 * NON INFRINGEMENT. See the GNU General Public License for 12 * more details. 13 */ 14 15#include <linux/types.h> 16#include <linux/string.h> 17#include <linux/module.h> 18 19void *memmove(void *dest, const void *src, size_t n) 20{ 21 if ((const char *)src >= (char *)dest + n 22 || (char *)dest >= (const char *)src + n) { 23 /* We found no overlap, so let memcpy do all the heavy 24 * lifting (prefetching, etc.) 25 */ 26 return memcpy(dest, src, n); 27 } 28 29 if (n != 0) { 30 const uint8_t *in; 31 uint8_t x; 32 uint8_t *out; 33 int stride; 34 35 if (src < dest) { 36 /* copy backwards */ 37 in = (const uint8_t *)src + n - 1; 38 out = (uint8_t *)dest + n - 1; 39 stride = -1; 40 } else { 41 /* copy forwards */ 42 in = (const uint8_t *)src; 43 out = (uint8_t *)dest; 44 stride = 1; 45 } 46 47 /* Manually software-pipeline this loop. */ 48 x = *in; 49 in += stride; 50 51 while (--n != 0) { 52 *out = x; 53 out += stride; 54 x = *in; 55 in += stride; 56 } 57 58 *out = x; 59 } 60 61 return dest; 62} 63EXPORT_SYMBOL(memmove); 64