memcpy.S 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* Copyright (C) 1999-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #include <sysdep.h>
  15. /* void *memcpy(void *dst, const void *src, size_t n);
  16. No overlap between the memory of DST and of SRC are assumed. */
  17. ENTRY(memcpy)
  18. mov r4,r3 /* Save destination. */
  19. /* If less than 11 bytes, just do a byte copy. */
  20. mov #11,r0
  21. cmp/gt r6,r0
  22. bt L_byteloop_init
  23. /* Check if we need to word-align source. */
  24. mov r5,r0
  25. tst #1,r0
  26. bt L_wordalign
  27. mov.b @r0+,r1 /* Copy one byte. */
  28. add #-1,r6
  29. mov.b r1,@r4
  30. add #1,r4
  31. .balignw 4,0x0009
  32. L_wordalign:
  33. /* Check if we need to longword-align source. */
  34. tst #2,r0
  35. bt L_copy
  36. mov.w @r0+,r1 /* Copy one word. */
  37. add #-2,r6
  38. #ifdef __BIG_ENDIAN__
  39. add #1,r4
  40. mov.b r1,@r4
  41. shlr8 r1
  42. mov.b r1,@-r4
  43. add #2,r4
  44. #else
  45. mov.b r1,@r4
  46. add #1,r4
  47. shlr8 r1
  48. mov.b r1,@r4
  49. add #1,r4
  50. #endif
  51. L_copy:
  52. mov r0,r5
  53. /* Calculate the correct routine to handle the destination
  54. alignment and simultaneously calculate the loop counts for
  55. both the 2 word copy loop and byte copy loop. */
  56. mova L_jumptable,r0
  57. mov r0,r1
  58. mov r4,r0
  59. mov r6,r7
  60. and #3,r0
  61. shlr2 r7
  62. shll r0
  63. shlr r7
  64. mov.w @(r0,r1),r2
  65. mov #7,r0
  66. braf r2
  67. and r0,r6
  68. L_base:
  69. .balign 4
  70. L_jumptable:
  71. .word L_copydest0 - L_base
  72. .word L_copydest1_or_3 - L_base
  73. .word L_copydest2 - L_base
  74. .word L_copydest1_or_3 - L_base
  75. .balign 4
  76. /* Copy routine for (dest mod 4) == 1 or == 3. */
  77. L_copydest1_or_3:
  78. add #-1,r4
  79. .balignw 4,0x0009
  80. L_copydest1_or_3_loop:
  81. mov.l @r5+,r0 /* Read first longword. */
  82. dt r7
  83. mov.l @r5+,r1 /* Read second longword. */
  84. #ifdef __BIG_ENDIAN__
  85. /* Write first longword as byte, word, byte. */
  86. mov.b r0,@(4,r4)
  87. shlr8 r0
  88. mov.w r0,@(2,r4)
  89. shlr16 r0
  90. mov.b r0,@(1,r4)
  91. mov r1,r0
  92. /* Write second longword as byte, word, byte. */
  93. mov.b r0,@(8,r4)
  94. shlr8 r0
  95. mov.w r0,@(6,r4)
  96. shlr16 r0
  97. mov.b r0,@(5,r4)
  98. #else
  99. /* Write first longword as byte, word, byte. */
  100. mov.b r0,@(1,r4)
  101. shlr8 r0
  102. mov.w r0,@(2,r4)
  103. shlr16 r0
  104. mov.b r0,@(4,r4)
  105. mov r1,r0
  106. /* Write second longword as byte, word, byte. */
  107. mov.b r0,@(5,r4)
  108. shlr8 r0
  109. mov.w r0,@(6,r4)
  110. shlr16 r0
  111. mov.b r0,@(8,r4)
  112. #endif
  113. bf/s L_copydest1_or_3_loop
  114. add #8,r4
  115. bra L_byteloop_init
  116. add #1,r4
  117. .balign 4
  118. /* Copy routine for (dest mod 4) == 2. */
  119. L_copydest2:
  120. L_copydest2_loop:
  121. mov.l @r5+,r0
  122. dt r7
  123. mov.l @r5+,r1
  124. #ifdef __BIG_ENDIAN__
  125. mov.w r0,@(2,r4)
  126. shlr16 r0
  127. mov.w r0,@r4
  128. mov r1,r0
  129. mov.w r0,@(6,r4)
  130. shlr16 r0
  131. mov.w r0,@(4,r4)
  132. #else
  133. mov.w r0,@r4
  134. shlr16 r0
  135. mov.w r0,@(2,r4)
  136. mov r1,r0
  137. mov.w r0,@(4,r4)
  138. shlr16 r0
  139. mov.w r0,@(6,r4)
  140. #endif
  141. bf/s L_copydest2_loop
  142. add #8,r4
  143. bra L_byteloop_init
  144. nop
  145. .balign 4
  146. /* Copy routine for (dest mod 4) == 0. */
  147. L_copydest0:
  148. add #-8,r4
  149. .balignw 4,0x0009
  150. L_copydest0_loop:
  151. mov.l @r5+,r0
  152. dt r7
  153. mov.l @r5+,r1
  154. add #8,r4
  155. mov.l r0,@r4
  156. bf/s L_copydest0_loop
  157. mov.l r1,@(4,r4)
  158. add #8,r4 /* Fall through. */
  159. L_byteloop_init:
  160. tst r6,r6
  161. bt L_exit
  162. .balignw 4,0x0009
  163. /* Copy remaining bytes. */
  164. L_byteloop:
  165. mov.b @r5+,r0
  166. dt r6
  167. mov.b r0,@r4
  168. bf/s L_byteloop
  169. add #1,r4
  170. L_exit:
  171. rts
  172. mov r3,r0 /* Return destination. */
  173. END(memcpy)
  174. libc_hidden_builtin_def (memcpy)