memcpy.S 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /*
  2. * "memcpy" implementation of SuperH
  3. *
  4. * Copyright (C) 1999 Niibe Yutaka
  5. * Copyright (c) 2002 STMicroelectronics Ltd
  6. * Modified from memcpy.S and micro-optimised for SH4
  7. * Stuart Menefy (stuart.menefy@st.com)
  8. *
  9. */
  10. /*
  11. * void *memcpy(void *dst, const void *src, size_t n);
  12. *
  13. * It is assumed that there is no overlap between src and dst.
  14. * If there is an overlap, then the results are undefined.
  15. */
  16. #include <endian.h>
  17. !
  18. ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR.
  19. !
  20. ! Size is 16 or greater, and may have trailing bytes
  21. .balign 32
  22. .Lcase1:
  23. ! Read a long word and write a long word at once
  24. ! At the start of each iteration, r7 contains last long load
  25. add #-1,r5 ! 79 EX
  26. mov r4,r2 ! 5 MT (0 cycles latency)
  27. mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency)
  28. add #-4,r5 ! 50 EX
  29. add #7,r2 ! 79 EX
  30. !
  31. #ifdef __LITTLE_ENDIAN__
  32. ! 6 cycles, 4 bytes per iteration
  33. 3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK
  34. mov r7, r3 ! 5 MT (latency=0) ! RQPO
  35. cmp/hi r2,r0 ! 57 MT
  36. shll16 r3 ! 103 EX
  37. mov r1,r6 ! 5 MT (latency=0)
  38. shll8 r3 ! 102 EX ! Oxxx
  39. shlr8 r6 ! 106 EX ! xNML
  40. mov r1, r7 ! 5 MT (latency=0)
  41. or r6,r3 ! 82 EX ! ONML
  42. bt/s 3b ! 109 BR
  43. mov.l r3,@-r0 ! 30 LS
  44. #else
  45. 3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! KLMN
  46. mov r7,r3 ! 5 MT (latency=0) ! OPQR
  47. cmp/hi r2,r0 ! 57 MT
  48. shlr16 r3 ! 107 EX
  49. shlr8 r3 ! 106 EX ! xxxO
  50. mov r1,r6 ! 5 MT (latency=0)
  51. shll8 r6 ! 102 EX ! LMNx
  52. mov r1,r7 ! 5 MT (latency=0)
  53. or r6,r3 ! 82 EX ! LMNO
  54. bt/s 3b ! 109 BR
  55. mov.l r3,@-r0 ! 30 LS
  56. #endif
  57. ! Finally, copy a byte at once, if necessary
  58. add #4,r5 ! 50 EX
  59. cmp/eq r4,r0 ! 54 MT
  60. add #-6,r2 ! 50 EX
  61. bt 9f ! 109 BR
  62. 8: cmp/hi r2,r0 ! 57 MT
  63. mov.b @(r0,r5),r1 ! 20 LS (latency=2)
  64. bt/s 8b ! 109 BR
  65. mov.b r1,@-r0 ! 29 LS
  66. 9: rts
  67. nop
  68. !
  69. ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R...
  70. !
  71. ! Size is 16 or greater, and may have trailing bytes
  72. .balign 32
  73. .Lcase3:
  74. ! Read a long word and write a long word at once
  75. ! At the start of each iteration, r7 contains last long load
  76. add #-3,r5 ! 79 EX
  77. mov r4,r2 ! 5 MT (0 cycles latency)
  78. mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency)
  79. add #-4,r5 ! 50 EX
  80. add #7,r2 ! 79 EX
  81. !
  82. #ifdef __LITTLE_ENDIAN__
  83. ! 6 cycles, 4 bytes per iteration
  84. 3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK
  85. mov r7, r3 ! 5 MT (latency=0) ! RQPO
  86. cmp/hi r2,r0 ! 57 MT
  87. shll8 r3 ! 102 EX ! QPOx
  88. mov r1,r6 ! 5 MT (latency=0)
  89. shlr16 r6 ! 107 EX
  90. shlr8 r6 ! 106 EX ! xxxN
  91. mov r1, r7 ! 5 MT (latency=0)
  92. or r6,r3 ! 82 EX ! QPON
  93. bt/s 3b ! 109 BR
  94. mov.l r3,@-r0 ! 30 LS
  95. #else
  96. 3: mov r1,r3 ! OPQR
  97. shlr8 r3 ! xOPQ
  98. mov.l @(r0,r5),r1 ! KLMN
  99. mov r1,r6
  100. shll16 r6
  101. shll8 r6 ! Nxxx
  102. or r6,r3 ! NOPQ
  103. cmp/hi r2,r0
  104. bt/s 3b
  105. mov.l r3,@-r0
  106. #endif
  107. ! Finally, copy a byte at once, if necessary
  108. add #6,r5 ! 50 EX
  109. cmp/eq r4,r0 ! 54 MT
  110. add #-6,r2 ! 50 EX
  111. bt 9f ! 109 BR
  112. 8: cmp/hi r2,r0 ! 57 MT
  113. mov.b @(r0,r5),r1 ! 20 LS (latency=2)
  114. bt/s 8b ! 109 BR
  115. mov.b r1,@-r0 ! 29 LS
  116. 9: rts
  117. nop
  118. /* void * memcpy(void *dst, const void *src, size_t len) */
  119. .text
  120. .align 4
  121. .type memcpy,@function
  122. .globl memcpy;
  123. memcpy:
  124. ! Calculate the invariants which will be used in the remainder
  125. ! of the code:
  126. !
  127. ! r4 --> [ ... ] DST [ ... ] SRC
  128. ! [ ... ] [ ... ]
  129. ! : :
  130. ! r0 --> [ ... ] r0+r5 --> [ ... ]
  131. !
  132. !
  133. ! Short circuit the common case of src, dst and len being 32 bit aligned
  134. ! and test for zero length move
  135. mov r6, r0 ! 5 MT (0 cycle latency)
  136. or r4, r0 ! 82 EX
  137. or r5, r0 ! 82 EX
  138. tst r6, r6 ! 86 MT
  139. bt/s 99f ! 111 BR (zero len)
  140. tst #3, r0 ! 87 MT
  141. mov r4, r0 ! 5 MT (0 cycle latency)
  142. add r6, r0 ! 49 EX
  143. mov #16, r1 ! 6 EX
  144. bt/s .Lcase00 ! 111 BR (aligned)
  145. sub r4, r5 ! 75 EX
  146. ! Arguments are not nicely long word aligned or zero len.
  147. ! Check for small copies, and if so do a simple byte at a time copy.
  148. !
  149. ! Deciding on an exact value of 'small' is not easy, as the point at which
  150. ! using the optimised routines become worthwhile varies (these are the
  151. ! cycle counts for differnet sizes using byte-at-a-time vs. optimised):
  152. ! size byte-at-time long word byte
  153. ! 16 42 39-40 46-50 50-55
  154. ! 24 58 43-44 54-58 62-67
  155. ! 36 82 49-50 66-70 80-85
  156. ! However the penalty for getting it 'wrong' is much higher for long word
  157. ! aligned data (and this is more common), so use a value of 16.
  158. cmp/gt r6,r1 ! 56 MT
  159. add #-1,r5 ! 50 EX
  160. bf/s 6f ! 108 BR (not small)
  161. mov r5, r3 ! 5 MT (latency=0)
  162. shlr r6 ! 104 EX
  163. mov.b @(r0,r5),r1 ! 20 LS (latency=2)
  164. bf/s 4f ! 111 BR
  165. add #-1,r3 ! 50 EX
  166. tst r6, r6 ! 86 MT
  167. bt/s 98f ! 110 BR
  168. mov.b r1,@-r0 ! 29 LS
  169. ! 4 cycles, 2 bytes per iteration
  170. 3: mov.b @(r0,r5),r1 ! 20 LS (latency=2)
  171. 4: mov.b @(r0,r3),r2 ! 20 LS (latency=2)
  172. dt r6 ! 67 EX
  173. mov.b r1,@-r0 ! 29 LS
  174. bf/s 3b ! 111 BR
  175. mov.b r2,@-r0 ! 29 LS
  176. 98:
  177. rts
  178. nop
  179. 99: rts
  180. mov r4, r0
  181. ! Size is not small, so its worthwhile looking for optimisations.
  182. ! First align destination to a long word boundary.
  183. !
  184. ! r5 = normal value -1
  185. 6: tst #3, r0 ! 87 MT
  186. mov #3, r3 ! 6 EX
  187. bt/s 2f ! 111 BR
  188. and r0,r3 ! 78 EX
  189. ! 3 cycles, 1 byte per iteration
  190. 1: dt r3 ! 67 EX
  191. mov.b @(r0,r5),r1 ! 19 LS (latency=2)
  192. add #-1, r6 ! 79 EX
  193. bf/s 1b ! 109 BR
  194. mov.b r1,@-r0 ! 28 LS
  195. 2: add #1, r5 ! 79 EX
  196. ! Now select the appropriate bulk transfer code based on relative
  197. ! alignment of src and dst.
  198. mov r0, r3 ! 5 MT (latency=0)
  199. mov r5, r0 ! 5 MT (latency=0)
  200. tst #1, r0 ! 87 MT
  201. bf/s 1f ! 111 BR
  202. mov #64, r7 ! 6 EX
  203. ! bit 0 clear
  204. cmp/ge r7, r6 ! 55 MT
  205. bt/s 2f ! 111 BR
  206. tst #2, r0 ! 87 MT
  207. ! small
  208. bt/s .Lcase0
  209. mov r3, r0
  210. bra .Lcase2
  211. nop
  212. ! big
  213. 2: bt/s .Lcase0b
  214. mov r3, r0
  215. bra .Lcase2b
  216. nop
  217. ! bit 0 set
  218. 1: tst #2, r0 ! 87 MT
  219. bt/s .Lcase1
  220. mov r3, r0
  221. bra .Lcase3
  222. nop
  223. !
  224. ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR
  225. !
  226. ! src, dst and size are all long word aligned
  227. ! size is non-zero
  228. .balign 32
  229. .Lcase00:
  230. mov #64, r1 ! 6 EX
  231. mov r5, r3 ! 5 MT (latency=0)
  232. cmp/gt r6, r1 ! 56 MT
  233. add #-4, r5 ! 50 EX
  234. bf .Lcase00b ! 108 BR (big loop)
  235. shlr2 r6 ! 105 EX
  236. shlr r6 ! 104 EX
  237. mov.l @(r0, r5), r1 ! 21 LS (latency=2)
  238. bf/s 4f ! 111 BR
  239. add #-8, r3 ! 50 EX
  240. tst r6, r6 ! 86 MT
  241. bt/s 5f ! 110 BR
  242. mov.l r1,@-r0 ! 30 LS
  243. ! 4 cycles, 2 long words per iteration
  244. 3: mov.l @(r0, r5), r1 ! 21 LS (latency=2)
  245. 4: mov.l @(r0, r3), r2 ! 21 LS (latency=2)
  246. dt r6 ! 67 EX
  247. mov.l r1, @-r0 ! 30 LS
  248. bf/s 3b ! 109 BR
  249. mov.l r2, @-r0 ! 30 LS
  250. 5: rts
  251. nop
  252. ! Size is 16 or greater and less than 64, but may have trailing bytes
  253. .balign 32
  254. .Lcase0:
  255. add #-4, r5 ! 50 EX
  256. mov r4, r7 ! 5 MT (latency=0)
  257. mov.l @(r0, r5), r1 ! 21 LS (latency=2)
  258. mov #4, r2 ! 6 EX
  259. add #11, r7 ! 50 EX
  260. tst r2, r6 ! 86 MT
  261. mov r5, r3 ! 5 MT (latency=0)
  262. bt/s 4f ! 111 BR
  263. add #-4, r3 ! 50 EX
  264. mov.l r1,@-r0 ! 30 LS
  265. ! 4 cycles, 2 long words per iteration
  266. 3: mov.l @(r0, r5), r1 ! 21 LS (latency=2)
  267. 4: mov.l @(r0, r3), r2 ! 21 LS (latency=2)
  268. cmp/hi r7, r0
  269. mov.l r1, @-r0 ! 30 LS
  270. bt/s 3b ! 109 BR
  271. mov.l r2, @-r0 ! 30 LS
  272. ! Copy the final 0-3 bytes
  273. add #3,r5 ! 50 EX
  274. cmp/eq r0, r4 ! 54 MT
  275. add #-10, r7 ! 50 EX
  276. bt 9f ! 110 BR
  277. ! 3 cycles, 1 byte per iteration
  278. 1: mov.b @(r0,r5),r1 ! 19 LS
  279. cmp/hi r7,r0 ! 57 MT
  280. bt/s 1b ! 111 BR
  281. mov.b r1,@-r0 ! 28 LS
  282. 9: rts
  283. nop
  284. ! Size is at least 64 bytes, so will be going round the big loop at least once.
  285. !
  286. ! r2 = rounded up r4
  287. ! r3 = rounded down r0
  288. .balign 32
  289. .Lcase0b:
  290. add #-4, r5 ! 50 EX
  291. .Lcase00b:
  292. mov r0, r3 ! 5 MT (latency=0)
  293. mov #(~0x1f), r1 ! 6 EX
  294. and r1, r3 ! 78 EX
  295. mov r4, r2 ! 5 MT (latency=0)
  296. cmp/eq r3, r0 ! 54 MT
  297. add #0x1f, r2 ! 50 EX
  298. bt/s 1f ! 110 BR
  299. and r1, r2 ! 78 EX
  300. ! copy initial words until cache line aligned
  301. mov.l @(r0, r5), r1 ! 21 LS (latency=2)
  302. tst #4, r0 ! 87 MT
  303. mov r5, r6 ! 5 MT (latency=0)
  304. add #-4, r6 ! 50 EX
  305. bt/s 4f ! 111 BR
  306. add #8, r3 ! 50 EX
  307. tst #0x18, r0 ! 87 MT
  308. bt/s 1f ! 109 BR
  309. mov.l r1,@-r0 ! 30 LS
  310. ! 4 cycles, 2 long words per iteration
  311. 3: mov.l @(r0, r5), r1 ! 21 LS (latency=2)
  312. 4: mov.l @(r0, r6), r7 ! 21 LS (latency=2)
  313. cmp/eq r3, r0 ! 54 MT
  314. mov.l r1, @-r0 ! 30 LS
  315. bf/s 3b ! 109 BR
  316. mov.l r7, @-r0 ! 30 LS
  317. ! Copy the cache line aligned blocks
  318. !
  319. ! In use: r0, r2, r4, r5
  320. ! Scratch: r1, r3, r6, r7
  321. !
  322. ! We could do this with the four scratch registers, but if src
  323. ! and dest hit the same cache line, this will thrash, so make
  324. ! use of additional registers.
  325. !
  326. ! We also need r0 as a temporary (for movca), so 'undo' the invariant:
  327. ! r5: src (was r0+r5)
  328. ! r1: dest (was r0)
  329. ! this can be reversed at the end, so we don't need to save any extra
  330. ! state.
  331. !
  332. 1: mov.l r8, @-r15 ! 30 LS
  333. add r0, r5 ! 49 EX
  334. mov.l r9, @-r15 ! 30 LS
  335. mov r0, r1 ! 5 MT (latency=0)
  336. mov.l r10, @-r15 ! 30 LS
  337. add #-0x1c, r5 ! 50 EX
  338. mov.l r11, @-r15 ! 30 LS
  339. ! 16 cycles, 32 bytes per iteration
  340. 2: mov.l @(0x00,r5),r0 ! 18 LS (latency=2)
  341. add #-0x20, r1 ! 50 EX
  342. mov.l @(0x04,r5),r3 ! 18 LS (latency=2)
  343. mov.l @(0x08,r5),r6 ! 18 LS (latency=2)
  344. mov.l @(0x0c,r5),r7 ! 18 LS (latency=2)
  345. mov.l @(0x10,r5),r8 ! 18 LS (latency=2)
  346. mov.l @(0x14,r5),r9 ! 18 LS (latency=2)
  347. mov.l @(0x18,r5),r10 ! 18 LS (latency=2)
  348. mov.l @(0x1c,r5),r11 ! 18 LS (latency=2)
  349. movca.l r0,@r1 ! 40 LS (latency=3-7)
  350. mov.l r3,@(0x04,r1) ! 33 LS
  351. mov.l r6,@(0x08,r1) ! 33 LS
  352. mov.l r7,@(0x0c,r1) ! 33 LS
  353. mov.l r8,@(0x10,r1) ! 33 LS
  354. add #-0x20, r5 ! 50 EX
  355. mov.l r9,@(0x14,r1) ! 33 LS
  356. cmp/eq r2,r1 ! 54 MT
  357. mov.l r10,@(0x18,r1) ! 33 LS
  358. bf/s 2b ! 109 BR
  359. mov.l r11,@(0x1c,r1) ! 33 LS
  360. mov r1, r0 ! 5 MT (latency=0)
  361. mov.l @r15+, r11 ! 15 LS
  362. sub r1, r5 ! 75 EX
  363. mov.l @r15+, r10 ! 15 LS
  364. cmp/eq r4, r0 ! 54 MT
  365. bf/s 1f ! 109 BR
  366. mov.l @r15+, r9 ! 15 LS
  367. rts
  368. 1: mov.l @r15+, r8 ! 15 LS
  369. sub r4, r1 ! 75 EX (len remaining)
  370. ! number of trailing bytes is non-zero
  371. !
  372. ! invariants restored (r5 already decremented by 4)
  373. ! also r1=num bytes remaining
  374. mov #4, r2 ! 6 EX
  375. mov r4, r7 ! 5 MT (latency=0)
  376. add #0x1c, r5 ! 50 EX (back to -4)
  377. cmp/hs r2, r1 ! 58 MT
  378. bf/s 5f ! 108 BR
  379. add #11, r7 ! 50 EX
  380. mov.l @(r0, r5), r6 ! 21 LS (latency=2)
  381. tst r2, r1 ! 86 MT
  382. mov r5, r3 ! 5 MT (latency=0)
  383. bt/s 4f ! 111 BR
  384. add #-4, r3 ! 50 EX
  385. cmp/hs r2, r1 ! 58 MT
  386. bt/s 5f ! 111 BR
  387. mov.l r6,@-r0 ! 30 LS
  388. ! 4 cycles, 2 long words per iteration
  389. 3: mov.l @(r0, r5), r6 ! 21 LS (latency=2)
  390. 4: mov.l @(r0, r3), r2 ! 21 LS (latency=2)
  391. cmp/hi r7, r0
  392. mov.l r6, @-r0 ! 30 LS
  393. bt/s 3b ! 109 BR
  394. mov.l r2, @-r0 ! 30 LS
  395. ! Copy the final 0-3 bytes
  396. 5: cmp/eq r0, r4 ! 54 MT
  397. add #-10, r7 ! 50 EX
  398. bt 9f ! 110 BR
  399. add #3,r5 ! 50 EX
  400. ! 3 cycles, 1 byte per iteration
  401. 1: mov.b @(r0,r5),r1 ! 19 LS
  402. cmp/hi r7,r0 ! 57 MT
  403. bt/s 1b ! 111 BR
  404. mov.b r1,@-r0 ! 28 LS
  405. 9: rts
  406. nop
  407. !
  408. ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR..
  409. !
  410. .balign 32
  411. .Lcase2:
  412. ! Size is 16 or greater and less then 64, but may have trailing bytes
  413. 2: mov r5, r6 ! 5 MT (latency=0)
  414. add #-2,r5 ! 50 EX
  415. mov r4,r2 ! 5 MT (latency=0)
  416. add #-4,r6 ! 50 EX
  417. add #7,r2 ! 50 EX
  418. 3: mov.w @(r0,r5),r1 ! 20 LS (latency=2)
  419. mov.w @(r0,r6),r3 ! 20 LS (latency=2)
  420. cmp/hi r2,r0 ! 57 MT
  421. mov.w r1,@-r0 ! 29 LS
  422. bt/s 3b ! 111 BR
  423. mov.w r3,@-r0 ! 29 LS
  424. bra 10f
  425. nop
  426. .balign 32
  427. .Lcase2b:
  428. ! Size is at least 64 bytes, so will be going round the big loop at least once.
  429. !
  430. ! r2 = rounded up r4
  431. ! r3 = rounded down r0
  432. mov r0, r3 ! 5 MT (latency=0)
  433. mov #(~0x1f), r1 ! 6 EX
  434. and r1, r3 ! 78 EX
  435. mov r4, r2 ! 5 MT (latency=0)
  436. cmp/eq r3, r0 ! 54 MT
  437. add #0x1f, r2 ! 50 EX
  438. add #-2, r5 ! 50 EX
  439. bt/s 1f ! 110 BR
  440. and r1, r2 ! 78 EX
  441. ! Copy a short word one at a time until we are cache line aligned
  442. ! Normal values: r0, r2, r3, r4
  443. ! Unused: r1, r6, r7
  444. ! Mod: r5 (=r5-2)
  445. !
  446. add #2, r3 ! 50 EX
  447. 2: mov.w @(r0,r5),r1 ! 20 LS (latency=2)
  448. cmp/eq r3,r0 ! 54 MT
  449. bf/s 2b ! 111 BR
  450. mov.w r1,@-r0 ! 29 LS
  451. ! Copy the cache line aligned blocks
  452. !
  453. ! In use: r0, r2, r4, r5 (=r5-2)
  454. ! Scratch: r1, r3, r6, r7
  455. !
  456. ! We could do this with the four scratch registers, but if src
  457. ! and dest hit the same cache line, this will thrash, so make
  458. ! use of additional registers.
  459. !
  460. ! We also need r0 as a temporary (for movca), so 'undo' the invariant:
  461. ! r5: src (was r0+r5)
  462. ! r1: dest (was r0)
  463. ! this can be reversed at the end, so we don't need to save any extra
  464. ! state.
  465. !
  466. 1: mov.l r8, @-r15 ! 30 LS
  467. add r0, r5 ! 49 EX
  468. mov.l r9, @-r15 ! 30 LS
  469. mov r0, r1 ! 5 MT (latency=0)
  470. mov.l r10, @-r15 ! 30 LS
  471. add #-0x1e, r5 ! 50 EX
  472. mov.l r11, @-r15 ! 30 LS
  473. mov.l r12, @-r15 ! 30 LS
  474. ! 17 cycles, 32 bytes per iteration
  475. #ifdef __LITTLE_ENDIAN__
  476. 2: mov.w @r5+, r0 ! 14 LS (latency=2) ..JI
  477. add #-0x20, r1 ! 50 EX
  478. mov.l @r5+, r3 ! 15 LS (latency=2) NMLK
  479. mov.l @r5+, r6 ! 15 LS (latency=2) RQPO
  480. shll16 r0 ! 103 EX JI..
  481. mov.l @r5+, r7 ! 15 LS (latency=2)
  482. xtrct r3, r0 ! 48 EX LKJI
  483. mov.l @r5+, r8 ! 15 LS (latency=2)
  484. xtrct r6, r3 ! 48 EX PONM
  485. mov.l @r5+, r9 ! 15 LS (latency=2)
  486. xtrct r7, r6 ! 48 EX
  487. mov.l @r5+, r10 ! 15 LS (latency=2)
  488. xtrct r8, r7 ! 48 EX
  489. mov.l @r5+, r11 ! 15 LS (latency=2)
  490. xtrct r9, r8 ! 48 EX
  491. mov.w @r5+, r12 ! 15 LS (latency=2)
  492. xtrct r10, r9 ! 48 EX
  493. movca.l r0,@r1 ! 40 LS (latency=3-7)
  494. xtrct r11, r10 ! 48 EX
  495. mov.l r3, @(0x04,r1) ! 33 LS
  496. xtrct r12, r11 ! 48 EX
  497. mov.l r6, @(0x08,r1) ! 33 LS
  498. mov.l r7, @(0x0c,r1) ! 33 LS
  499. mov.l r8, @(0x10,r1) ! 33 LS
  500. add #-0x40, r5 ! 50 EX
  501. mov.l r9, @(0x14,r1) ! 33 LS
  502. cmp/eq r2,r1 ! 54 MT
  503. mov.l r10, @(0x18,r1) ! 33 LS
  504. bf/s 2b ! 109 BR
  505. mov.l r11, @(0x1c,r1) ! 33 LS
  506. #else
  507. 2: mov.w @(0x1e,r5), r0 ! 17 LS (latency=2)
  508. add #-2, r5 ! 50 EX
  509. mov.l @(0x1c,r5), r3 ! 18 LS (latency=2)
  510. add #-4, r1 ! 50 EX
  511. mov.l @(0x18,r5), r6 ! 18 LS (latency=2)
  512. shll16 r0 ! 103 EX
  513. mov.l @(0x14,r5), r7 ! 18 LS (latency=2)
  514. xtrct r3, r0 ! 48 EX
  515. mov.l @(0x10,r5), r8 ! 18 LS (latency=2)
  516. xtrct r6, r3 ! 48 EX
  517. mov.l @(0x0c,r5), r9 ! 18 LS (latency=2)
  518. xtrct r7, r6 ! 48 EX
  519. mov.l @(0x08,r5), r10 ! 18 LS (latency=2)
  520. xtrct r8, r7 ! 48 EX
  521. mov.l @(0x04,r5), r11 ! 18 LS (latency=2)
  522. xtrct r9, r8 ! 48 EX
  523. mov.w @(0x02,r5), r12 ! 18 LS (latency=2)
  524. xtrct r10, r9 ! 48 EX
  525. movca.l r0,@r1 ! 40 LS (latency=3-7)
  526. add #-0x1c, r1 ! 50 EX
  527. mov.l r3, @(0x1c,r1) ! 33 LS
  528. xtrct r11, r10 ! 48 EX
  529. mov.l r6, @(0x18,r1) ! 33 LS
  530. xtrct r12, r11 ! 48 EX
  531. mov.l r7, @(0x14,r1) ! 33 LS
  532. mov.l r8, @(0x10,r1) ! 33 LS
  533. add #-0x3e, r5 ! 50 EX
  534. mov.l r9, @(0x0c,r1) ! 33 LS
  535. cmp/eq r2,r1 ! 54 MT
  536. mov.l r10, @(0x08,r1) ! 33 LS
  537. bf/s 2b ! 109 BR
  538. mov.l r11, @(0x04,r1) ! 33 LS
  539. #endif
  540. mov.l @r15+, r12
  541. mov r1, r0 ! 5 MT (latency=0)
  542. mov.l @r15+, r11 ! 15 LS
  543. sub r1, r5 ! 75 EX
  544. mov.l @r15+, r10 ! 15 LS
  545. cmp/eq r4, r0 ! 54 MT
  546. bf/s 1f ! 109 BR
  547. mov.l @r15+, r9 ! 15 LS
  548. rts
  549. 1: mov.l @r15+, r8 ! 15 LS
  550. add #0x1e, r5 ! 50 EX
  551. ! Finish off a short word at a time
  552. ! r5 must be invariant - 2
  553. 10: mov r4,r2 ! 5 MT (latency=0)
  554. add #1,r2 ! 50 EX
  555. cmp/hi r2, r0 ! 57 MT
  556. bf/s 1f ! 109 BR
  557. add #2, r2 ! 50 EX
  558. 3: mov.w @(r0,r5),r1 ! 20 LS
  559. cmp/hi r2,r0 ! 57 MT
  560. bt/s 3b ! 109 BR
  561. mov.w r1,@-r0 ! 29 LS
  562. 1:
  563. !
  564. ! Finally, copy the last byte if necessary
  565. cmp/eq r4,r0 ! 54 MT
  566. bt/s 9b
  567. add #1,r5
  568. mov.b @(r0,r5),r1
  569. rts
  570. mov.b r1,@-r0
  571. .size memcpy,.-memcpy;
  572. libc_hidden_def (memcpy)