Subversion Repositories Kolibri OS

Rev

Rev 4874 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2. FUNCTION
  3.         <<memmove>>---move possibly overlapping memory
  4.  
  5. INDEX
  6.         memmove
  7.  
  8. ANSI_SYNOPSIS
  9.         #include <string.h>
  10.         void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>);
  11.  
  12. TRAD_SYNOPSIS
  13.         #include <string.h>
  14.         void *memmove(<[dst]>, <[src]>, <[length]>)
  15.         void *<[dst]>;
  16.         void *<[src]>;
  17.         size_t <[length]>;
  18.  
  19. DESCRIPTION
  20.         This function moves <[length]> characters from the block of
  21.         memory starting at <<*<[src]>>> to the memory starting at
  22.         <<*<[dst]>>>. <<memmove>> reproduces the characters correctly
  23.         at <<*<[dst]>>> even if the two areas overlap.
  24.  
  25.  
  26. RETURNS
  27.         The function returns <[dst]> as passed.
  28.  
  29. PORTABILITY
  30. <<memmove>> is ANSI C.
  31.  
  32. <<memmove>> requires no supporting OS subroutines.
  33.  
  34. QUICKREF
  35.         memmove ansi pure
  36. */
  37.  
  38. #include <string.h>
  39. #include <_ansi.h>
  40. #include <stddef.h>
  41. #include <limits.h>
  42. #include "local.h"
  43.  
  44. /* Nonzero if either X or Y is not aligned on a "long" boundary.  */
  45. #define UNALIGNED(X, Y) \
  46.   (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
  47.  
  48. /* How many bytes are copied each iteration of the 4X unrolled loop.  */
  49. #define BIGBLOCKSIZE    (sizeof (long) << 2)
  50.  
  51. /* How many bytes are copied each iteration of the word copy loop.  */
  52. #define LITTLEBLOCKSIZE (sizeof (long))
  53.  
  54. /* Threshhold for punting to the byte copier.  */
  55. #define TOO_SMALL(LEN)  ((LEN) < BIGBLOCKSIZE)
  56.  
  57. /*SUPPRESS 20*/
  58. _PTR
  59. __inhibit_loop_to_libcall
  60. _DEFUN (memmove, (dst_void, src_void, length),
  61.         _PTR dst_void _AND
  62.         _CONST _PTR src_void _AND
  63.         size_t length)
  64. {
  65. #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
  66.   char *dst = dst_void;
  67.   _CONST char *src = src_void;
  68.  
  69.   if (src < dst && dst < src + length)
  70.     {
  71.       /* Have to copy backwards */
  72.       src += length;
  73.       dst += length;
  74.       while (length--)
  75.         {
  76.           *--dst = *--src;
  77.         }
  78.     }
  79.   else
  80.     {
  81.       while (length--)
  82.         {
  83.           *dst++ = *src++;
  84.         }
  85.     }
  86.  
  87.   return dst_void;
  88. #else
  89.   char *dst = dst_void;
  90.   _CONST char *src = src_void;
  91.   long *aligned_dst;
  92.   _CONST long *aligned_src;
  93.  
  94.   if (src < dst && dst < src + length)
  95.     {
  96.       /* Destructive overlap...have to copy backwards */
  97.       src += length;
  98.       dst += length;
  99.       while (length--)
  100.         {
  101.           *--dst = *--src;
  102.         }
  103.     }
  104.   else
  105.     {
  106.       /* Use optimizing algorithm for a non-destructive copy to closely
  107.          match memcpy. If the size is small or either SRC or DST is unaligned,
  108.          then punt into the byte copy loop.  This should be rare.  */
  109.       if (!TOO_SMALL(length) && !UNALIGNED (src, dst))
  110.         {
  111.           aligned_dst = (long*)dst;
  112.           aligned_src = (long*)src;
  113.  
  114.           /* Copy 4X long words at a time if possible.  */
  115.           while (length >= BIGBLOCKSIZE)
  116.             {
  117.               *aligned_dst++ = *aligned_src++;
  118.               *aligned_dst++ = *aligned_src++;
  119.               *aligned_dst++ = *aligned_src++;
  120.               *aligned_dst++ = *aligned_src++;
  121.               length -= BIGBLOCKSIZE;
  122.             }
  123.  
  124.           /* Copy one long word at a time if possible.  */
  125.           while (length >= LITTLEBLOCKSIZE)
  126.             {
  127.               *aligned_dst++ = *aligned_src++;
  128.               length -= LITTLEBLOCKSIZE;
  129.             }
  130.  
  131.           /* Pick up any residual with a byte copier.  */
  132.           dst = (char*)aligned_dst;
  133.           src = (char*)aligned_src;
  134.         }
  135.  
  136.       while (length--)
  137.         {
  138.           *dst++ = *src++;
  139.         }
  140.     }
  141.  
  142.   return dst_void;
  143. #endif /* not PREFER_SIZE_OVER_SPEED */
  144. }
  145.