linux/arch/tile/lib/memmove.c
<<
>>
Prefs
   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