memcpy.S 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * internal version of memcpy(), issued by the compiler to copy blocks of
  3. * data around. This is really memmove() - it has to be able to deal with
  4. * possible overlaps, because that ambiguity is when the compiler gives up
  5. * and calls a function. We have our own, internal version so that we get
  6. * something we trust, even if the user has redefined the normal symbol.
  7. *
  8. * Copyright 2004-2009 Analog Devices Inc.
  9. *
  10. * Licensed under the Clear BSD license or the GPL-2 (or later)
  11. */
  12. #include <linux/linkage.h>
  13. /* void *memcpy(void *dest, const void *src, size_t n);
  14. * R0 = To Address (dest) (leave unchanged to form result)
  15. * R1 = From Address (src)
  16. * R2 = count
  17. *
  18. * Note: Favours word alignment
  19. */
  20. #ifdef CONFIG_MEMCPY_L1
  21. .section .l1.text
  22. #else
  23. .text
  24. #endif
  25. .align 2
  26. ENTRY(_memcpy)
  27. CC = R2 <= 0; /* length not positive? */
  28. IF CC JUMP .L_P1L2147483647; /* Nothing to do */
  29. P0 = R0 ; /* dst*/
  30. P1 = R1 ; /* src*/
  31. P2 = R2 ; /* length */
  32. /* check for overlapping data */
  33. CC = R1 < R0; /* src < dst */
  34. IF !CC JUMP .Lno_overlap;
  35. R3 = R1 + R2;
  36. CC = R0 < R3; /* and dst < src+len */
  37. IF CC JUMP .Lhas_overlap;
  38. .Lno_overlap:
  39. /* Check for aligned data.*/
  40. R3 = R1 | R0;
  41. R1 = 0x3;
  42. R3 = R3 & R1;
  43. CC = R3; /* low bits set on either address? */
  44. IF CC JUMP .Lnot_aligned;
  45. /* Both addresses are word-aligned, so we can copy
  46. at least part of the data using word copies.*/
  47. P2 = P2 >> 2;
  48. CC = P2 <= 2;
  49. IF !CC JUMP .Lmore_than_seven;
  50. /* less than eight bytes... */
  51. P2 = R2;
  52. LSETUP(.Lthree_start, .Lthree_end) LC0=P2;
  53. .Lthree_start:
  54. R3 = B[P1++] (X);
  55. .Lthree_end:
  56. B[P0++] = R3;
  57. RTS;
  58. .Lmore_than_seven:
  59. /* There's at least eight bytes to copy. */
  60. P2 += -1; /* because we unroll one iteration */
  61. LSETUP(.Lword_loops, .Lword_loope) LC0=P2;
  62. I1 = P1;
  63. R3 = [I1++];
  64. #if ANOMALY_05000202
  65. .Lword_loops:
  66. [P0++] = R3;
  67. .Lword_loope:
  68. R3 = [I1++];
  69. #else
  70. .Lword_loops:
  71. .Lword_loope:
  72. MNOP || [P0++] = R3 || R3 = [I1++];
  73. #endif
  74. [P0++] = R3;
  75. /* Any remaining bytes to copy? */
  76. R3 = 0x3;
  77. R3 = R2 & R3;
  78. CC = R3 == 0;
  79. P1 = I1; /* in case there's something left, */
  80. IF !CC JUMP .Lbytes_left;
  81. RTS;
  82. .Lbytes_left: P2 = R3;
  83. .Lnot_aligned:
  84. /* From here, we're copying byte-by-byte. */
  85. LSETUP (.Lbyte_start, .Lbyte_end) LC0=P2;
  86. .Lbyte_start:
  87. R1 = B[P1++] (X);
  88. .Lbyte_end:
  89. B[P0++] = R1;
  90. .L_P1L2147483647:
  91. RTS;
  92. .Lhas_overlap:
  93. /* Need to reverse the copying, because the
  94. * dst would clobber the src.
  95. * Don't bother to work out alignment for
  96. * the reverse case.
  97. */
  98. P0 = P0 + P2;
  99. P0 += -1;
  100. P1 = P1 + P2;
  101. P1 += -1;
  102. LSETUP(.Lover_start, .Lover_end) LC0=P2;
  103. .Lover_start:
  104. R1 = B[P1--] (X);
  105. .Lover_end:
  106. B[P0--] = R1;
  107. RTS;
  108. ENDPROC(_memcpy)