string.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*#************************************************************************#*/
  2. /*#-------------------------------------------------------------------------*/
  3. /*#                                                                         */
  4. /*# FUNCTION NAME: memcpy()                                                 */
  5. /*#                                                                         */
  6. /*# PARAMETERS:  void* dst;   Destination address.                          */
  7. /*#              void* src;   Source address.                               */
  8. /*#              int   len;   Number of bytes to copy.                      */
  9. /*#                                                                         */
  10. /*# RETURNS:     dst.                                                       */
  11. /*#                                                                         */
  12. /*# DESCRIPTION: Copies len bytes of memory from src to dst.  No guarantees */
  13. /*#              about copying of overlapping memory areas. This routine is */
  14. /*#              very sensitive to compiler changes in register allocation. */
  15. /*#              Should really be rewritten to avoid this problem.          */
  16. /*#                                                                         */
  17. /*#-------------------------------------------------------------------------*/
  18. /*#                                                                         */
  19. /*# HISTORY                                                                 */
  20. /*#                                                                         */
  21. /*# DATE      NAME            CHANGES                                       */
  22. /*# ----      ----            -------                                       */
  23. /*# 941007    Kenny R         Creation                                      */
  24. /*# 941011    Kenny R         Lots of optimizations and inlining.           */
  25. /*# 941129    Ulf A           Adapted for use in libc.                      */
  26. /*# 950216    HP              N==0 forgotten if non-aligned src/dst.        */
  27. /*#                           Added some optimizations.                     */
  28. /*# 001025    HP              Make src and dst char *.  Align dst to     */
  29. /*#       dword, not just word-if-both-src-and-dst-     */
  30. /*#       are-misaligned.     */
  31. /*#                                                                         */
  32. /*#-------------------------------------------------------------------------*/
  33. #include <linux/types.h>
  34. void *memcpy(void *pdst,
  35.              const void *psrc,
  36.              size_t pn)
  37. {
  38.   /* Ok.  Now we want the parameters put in special registers.
  39.      Make sure the compiler is able to make something useful of this.
  40.       As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
  41.      If gcc was allright, it really would need no temporaries, and no
  42.      stack space to save stuff on. */
  43.   register void *return_dst __asm__ ("r10") = pdst;
  44.   register char *dst __asm__ ("r13") = pdst;
  45.   register const char *src __asm__ ("r11") = psrc;
  46.   register int n __asm__ ("r12") = pn;
  47.   
  48.  
  49.   /* When src is aligned but not dst, this makes a few extra needless
  50.      cycles.  I believe it would take as many to check that the
  51.      re-alignment was unnecessary.  */
  52.   if (((unsigned long) dst & 3) != 0
  53.       /* Don't align if we wouldn't copy more than a few bytes; so we
  54.  don't have to check further for overflows.  */
  55.       && n >= 3)
  56.   {
  57.     if ((unsigned long) dst & 1)
  58.     {
  59.       n--;
  60.       *(char*)dst = *(char*)src;
  61.       src++;
  62.       dst++;
  63.     }
  64.     if ((unsigned long) dst & 2)
  65.     {
  66.       n -= 2;
  67.       *(short*)dst = *(short*)src;
  68.       src += 2;
  69.       dst += 2;
  70.     }
  71.   }
  72.   /* Decide which copying method to use. */
  73.   if (n >= 44*2)                /* Break even between movem and
  74.                                    move16 is at 38.7*2, but modulo 44. */
  75.   {
  76.     /* For large copies we use 'movem' */
  77.   /* It is not optimal to tell the compiler about clobbering any
  78.      registers; that will move the saving/restoring of those registers
  79.      to the function prologue/epilogue, and make non-movem sizes
  80.      suboptimal.
  81.       This method is not foolproof; it assumes that the "asm reg"
  82.      declarations at the beginning of the function really are used
  83.      here (beware: they may be moved to temporary registers).
  84.       This way, we do not have to save/move the registers around into
  85.      temporaries; we can safely use them straight away.
  86.       If you want to check that the allocation was right; then
  87.       check the equalities in the first comment.  It should say
  88.       "r13=r13, r11=r11, r12=r12" */
  89.     __asm__ volatile ("
  90.         ;; Check that the following is true (same register names on
  91.         ;; both sides of equal sign, as in r8=r8):
  92.         ;; %0=r13, %1=r11, %2=r12
  93.         ;;
  94. ;; Save the registers we'll use in the movem process
  95. ;; on the stack.
  96. subq  11*4,$sp
  97. movem $r10,[$sp]
  98.         ;; Now we've got this:
  99. ;; r11 - src
  100. ;; r13 - dst
  101. ;; r12 - n
  102.         ;; Update n for the first loop
  103.         subq    44,$r12
  104. 0:
  105. movem [$r11+],$r10
  106.         subq   44,$r12
  107.         bge     0b
  108. movem $r10,[$r13+]
  109.         addq   44,$r12  ;; compensate for last loop underflowing n
  110. ;; Restore registers from stack
  111.         movem [$sp+],$r10" 
  112.      /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n) 
  113.      /* Inputs */ : "0" (dst), "1" (src), "2" (n));
  114.     
  115.   }
  116.   /* Either we directly starts copying, using dword copying
  117.      in a loop, or we copy as much as possible with 'movem' 
  118.      and then the last block (<44 bytes) is copied here.
  119.      This will work since 'movem' will have updated src,dst,n. */
  120.   while ( n >= 16 )
  121.   {
  122.     *((long*)dst)++ = *((long*)src)++;
  123.     *((long*)dst)++ = *((long*)src)++;
  124.     *((long*)dst)++ = *((long*)src)++;
  125.     *((long*)dst)++ = *((long*)src)++;
  126.     n -= 16;
  127.   }
  128.   /* A switch() is definitely the fastest although it takes a LOT of code.
  129.    * Particularly if you inline code this.
  130.    */
  131.   switch (n)
  132.   {
  133.     case 0:
  134.       break;
  135.     case 1:
  136.       *(char*)dst = *(char*)src;
  137.       break;
  138.     case 2:
  139.       *(short*)dst = *(short*)src;
  140.       break;
  141.     case 3:
  142.       *((short*)dst)++ = *((short*)src)++;
  143.       *(char*)dst = *(char*)src;
  144.       break;
  145.     case 4:
  146.       *((long*)dst)++ = *((long*)src)++;
  147.       break;
  148.     case 5:
  149.       *((long*)dst)++ = *((long*)src)++;
  150.       *(char*)dst = *(char*)src;
  151.       break;
  152.     case 6:
  153.       *((long*)dst)++ = *((long*)src)++;
  154.       *(short*)dst = *(short*)src;
  155.       break;
  156.     case 7:
  157.       *((long*)dst)++ = *((long*)src)++;
  158.       *((short*)dst)++ = *((short*)src)++;
  159.       *(char*)dst = *(char*)src;
  160.       break;
  161.     case 8:
  162.       *((long*)dst)++ = *((long*)src)++;
  163.       *((long*)dst)++ = *((long*)src)++;
  164.       break;
  165.     case 9:
  166.       *((long*)dst)++ = *((long*)src)++;
  167.       *((long*)dst)++ = *((long*)src)++;
  168.       *(char*)dst = *(char*)src;
  169.       break;
  170.     case 10:
  171.       *((long*)dst)++ = *((long*)src)++;
  172.       *((long*)dst)++ = *((long*)src)++;
  173.       *(short*)dst = *(short*)src;
  174.       break;
  175.     case 11:
  176.       *((long*)dst)++ = *((long*)src)++;
  177.       *((long*)dst)++ = *((long*)src)++;
  178.       *((short*)dst)++ = *((short*)src)++;
  179.       *(char*)dst = *(char*)src;
  180.       break;
  181.     case 12:
  182.       *((long*)dst)++ = *((long*)src)++;
  183.       *((long*)dst)++ = *((long*)src)++;
  184.       *((long*)dst)++ = *((long*)src)++;
  185.       break;
  186.     case 13:
  187.       *((long*)dst)++ = *((long*)src)++;
  188.       *((long*)dst)++ = *((long*)src)++;
  189.       *((long*)dst)++ = *((long*)src)++;
  190.       *(char*)dst = *(char*)src;
  191.       break;
  192.     case 14:
  193.       *((long*)dst)++ = *((long*)src)++;
  194.       *((long*)dst)++ = *((long*)src)++;
  195.       *((long*)dst)++ = *((long*)src)++;
  196.       *(short*)dst = *(short*)src;
  197.       break;
  198.     case 15:
  199.       *((long*)dst)++ = *((long*)src)++;
  200.       *((long*)dst)++ = *((long*)src)++;
  201.       *((long*)dst)++ = *((long*)src)++;
  202.       *((short*)dst)++ = *((short*)src)++;
  203.       *(char*)dst = *(char*)src;
  204.       break;
  205.   }
  206.   return return_dst; /* destination pointer. */
  207. } /* memcpy() */