memmove.S 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /* $Id: memmove.S,v 1.2 2001/07/27 11:51:09 gniibe Exp $
  3. *
  4. * "memmove" implementation of SuperH
  5. *
  6. * Copyright (C) 1999 Niibe Yutaka
  7. *
  8. */
  9. /*
  10. * void *memmove(void *dst, const void *src, size_t n);
  11. * The memory areas may overlap.
  12. */
  13. #include <linux/linkage.h>
  14. ENTRY(memmove)
  15. ! if dest > src, call memcpy (it copies in decreasing order)
  16. cmp/hi r5,r4
  17. bf 1f
  18. mov.l 2f,r0
  19. jmp @r0
  20. nop
  21. .balign 4
  22. 2: .long memcpy
  23. 1:
  24. sub r5,r4 ! From here, r4 has the distance to r0
  25. tst r6,r6
  26. bt/s 9f ! if n=0, do nothing
  27. mov r5,r0
  28. add r6,r5
  29. mov #12,r1
  30. cmp/gt r6,r1
  31. bt/s 8f ! if it's too small, copy a byte at once
  32. add #-1,r4
  33. add #1,r4
  34. !
  35. ! [ ... ] DST [ ... ] SRC
  36. ! [ ... ] [ ... ]
  37. ! : :
  38. ! r0+r4--> [ ... ] r0 --> [ ... ]
  39. ! : :
  40. ! [ ... ] [ ... ]
  41. ! r5 -->
  42. !
  43. mov r4,r1
  44. mov #3,r2
  45. and r2,r1
  46. shll2 r1
  47. mov r0,r3 ! Save the value on R0 to R3
  48. mova jmptable,r0
  49. add r1,r0
  50. mov.l @r0,r1
  51. jmp @r1
  52. mov r3,r0 ! and back to R0
  53. .balign 4
  54. jmptable:
  55. .long case0
  56. .long case1
  57. .long case2
  58. .long case3
  59. ! copy a byte at once
  60. 8: mov.b @r0+,r1
  61. cmp/hs r5,r0
  62. bf/s 8b ! while (r0<r5)
  63. mov.b r1,@(r0,r4)
  64. add #1,r4
  65. 9:
  66. add r4,r0
  67. rts
  68. sub r6,r0
  69. case_none:
  70. bra 8b
  71. add #-1,r4
  72. case0:
  73. !
  74. ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR
  75. !
  76. ! First, align to long word boundary
  77. mov r0,r3
  78. and r2,r3
  79. tst r3,r3
  80. bt/s 2f
  81. add #-1,r4
  82. mov #4,r2
  83. sub r3,r2
  84. 1: dt r2
  85. mov.b @r0+,r1
  86. bf/s 1b
  87. mov.b r1,@(r0,r4)
  88. !
  89. 2: ! Second, copy a long word at once
  90. add #-3,r4
  91. add #-3,r5
  92. 3: mov.l @r0+,r1
  93. cmp/hs r5,r0
  94. bf/s 3b
  95. mov.l r1,@(r0,r4)
  96. add #3,r5
  97. !
  98. ! Third, copy a byte at once, if necessary
  99. cmp/eq r5,r0
  100. bt/s 9b
  101. add #4,r4
  102. bra 8b
  103. add #-1,r4
  104. case3:
  105. !
  106. ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR.
  107. !
  108. ! First, align to long word boundary
  109. mov r0,r3
  110. and r2,r3
  111. tst r3,r3
  112. bt/s 2f
  113. add #-1,r4
  114. mov #4,r2
  115. sub r3,r2
  116. 1: dt r2
  117. mov.b @r0+,r1
  118. bf/s 1b
  119. mov.b r1,@(r0,r4)
  120. !
  121. 2: ! Second, read a long word and write a long word at once
  122. add #-2,r4
  123. mov.l @(r0,r4),r1
  124. add #-7,r5
  125. add #-4,r4
  126. !
  127. #ifdef __LITTLE_ENDIAN__
  128. shll8 r1
  129. 3: mov r1,r3 ! JIHG
  130. shlr8 r3 ! xJIH
  131. mov.l @r0+,r1 ! NMLK
  132. mov r1,r2
  133. shll16 r2
  134. shll8 r2 ! Kxxx
  135. or r2,r3 ! KJIH
  136. cmp/hs r5,r0
  137. bf/s 3b
  138. mov.l r3,@(r0,r4)
  139. #else
  140. shlr8 r1
  141. 3: mov r1,r3 ! GHIJ
  142. shll8 r3 ! HIJx
  143. mov.l @r0+,r1 ! KLMN
  144. mov r1,r2
  145. shlr16 r2
  146. shlr8 r2 ! xxxK
  147. or r2,r3 ! HIJK
  148. cmp/hs r5,r0
  149. bf/s 3b
  150. mov.l r3,@(r0,r4)
  151. #endif
  152. add #7,r5
  153. !
  154. ! Third, copy a byte at once, if necessary
  155. cmp/eq r5,r0
  156. bt/s 9b
  157. add #7,r4
  158. add #-3,r0
  159. bra 8b
  160. add #-1,r4
  161. case2:
  162. !
  163. ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR..
  164. !
  165. ! First, align to word boundary
  166. tst #1,r0
  167. bt/s 2f
  168. add #-1,r4
  169. mov.b @r0+,r1
  170. mov.b r1,@(r0,r4)
  171. !
  172. 2: ! Second, read a word and write a word at once
  173. add #-1,r4
  174. add #-1,r5
  175. !
  176. 3: mov.w @r0+,r1
  177. cmp/hs r5,r0
  178. bf/s 3b
  179. mov.w r1,@(r0,r4)
  180. add #1,r5
  181. !
  182. ! Third, copy a byte at once, if necessary
  183. cmp/eq r5,r0
  184. bt/s 9b
  185. add #2,r4
  186. mov.b @r0,r1
  187. mov.b r1,@(r0,r4)
  188. bra 9b
  189. add #1,r0
  190. case1:
  191. !
  192. ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R...
  193. !
  194. ! First, align to long word boundary
  195. mov r0,r3
  196. and r2,r3
  197. tst r3,r3
  198. bt/s 2f
  199. add #-1,r4
  200. mov #4,r2
  201. sub r3,r2
  202. 1: dt r2
  203. mov.b @r0+,r1
  204. bf/s 1b
  205. mov.b r1,@(r0,r4)
  206. !
  207. 2: ! Second, read a long word and write a long word at once
  208. mov.l @(r0,r4),r1
  209. add #-7,r5
  210. add #-4,r4
  211. !
  212. #ifdef __LITTLE_ENDIAN__
  213. shll16 r1
  214. shll8 r1
  215. 3: mov r1,r3 ! JIHG
  216. shlr16 r3
  217. shlr8 r3 ! xxxJ
  218. mov.l @r0+,r1 ! NMLK
  219. mov r1,r2
  220. shll8 r2 ! MLKx
  221. or r2,r3 ! MLKJ
  222. cmp/hs r5,r0
  223. bf/s 3b
  224. mov.l r3,@(r0,r4)
  225. #else
  226. shlr16 r1
  227. shlr8 r1
  228. 3: mov r1,r3 ! GHIJ
  229. shll16 r3
  230. shll8 r3 ! Jxxx
  231. mov.l @r0+,r1 ! KLMN
  232. mov r1,r2
  233. shlr8 r2 ! xKLM
  234. or r2,r3 ! JKLM
  235. cmp/hs r5,r0
  236. bf/s 3b ! while(r0<r5)
  237. mov.l r3,@(r0,r4)
  238. #endif
  239. add #7,r5
  240. !
  241. ! Third, copy a byte at once, if necessary
  242. cmp/eq r5,r0
  243. bt/s 9b
  244. add #5,r4
  245. add #-3,r0
  246. bra 8b
  247. add #-1,r4