copy_subr.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /* $OpenBSD: copy_subr.S,v 1.6 2013/06/15 18:38:18 miod Exp $ */
  2. /*
  3. * Mach Operating System
  4. * Copyright (c) 1993-1992 Carnegie Mellon University
  5. * Copyright (c) 1991 OMRON Corporation
  6. * Copyright (c) 1996 Nivas Madhur
  7. * Copyright (c) 1998 Steve Murphree, Jr.
  8. * All Rights Reserved.
  9. *
  10. * Permission to use, copy, modify and distribute this software and its
  11. * documentation is hereby granted, provided that both the copyright
  12. * notice and this permission notice appear in all copies of the
  13. * software, derivative works or modified versions, and any portions
  14. * thereof, and that both notices appear in supporting documentation.
  15. *
  16. * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  17. * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
  18. * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  19. *
  20. * Carnegie Mellon requests users of this software to return to
  21. *
  22. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  23. * School of Computer Science
  24. * Carnegie Mellon University
  25. * Pittsburgh PA 15213-3890
  26. *
  27. * any improvements or extensions that they make and grant Carnegie the
  28. * rights to redistribute these changes.
  29. */
  30. #include <machine/asm.h>
  31. /*
  32. * copy count bytes of data from source to destination
  33. * Don Harper (don@omron.co.jp), Omron Corporation.
  34. */
  35. #if defined(MEMCPY) || defined(MEMMOVE)
  36. #define SRC %r3
  37. #define DEST %r2
  38. #define SAVE %r5
  39. #else
  40. #define SRC %r2
  41. #define DEST %r3
  42. #endif
  43. #define LEN %r4
  44. #ifdef MEMCPY
  45. ENTRY(memcpy)
  46. #endif
  47. #ifdef MEMMOVE
  48. ENTRY(memmove)
  49. #endif
  50. #ifdef BCOPY
  51. #define OVBCOPY
  52. ENTRY(bcopy)
  53. #endif
  54. #if defined(MEMCPY) || defined(MEMMOVE)
  55. or SAVE, DEST, %r0
  56. #endif
  57. bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* nothing to do if == 0 */
  58. /*
  59. * check position of source and destination data
  60. */
  61. cmp %r9,SRC,DEST /* compare source address to destination */
  62. bb1 eq,%r9,_ASM_LABEL(bcopy_out) /* nothing to do if equal */
  63. #if defined(MEMMOVE) || defined(OVBCOPY)
  64. bb1 lo,%r9,_ASM_LABEL(bcopy_reverse) /* reverse copy if src < dest */
  65. #endif
  66. /*
  67. * source address is greater than destination address, or we do
  68. * not have to care about overlapping areas: copy forward
  69. */
  70. cmp %r9,LEN,16 /* see if we have at least 16 bytes */
  71. bb1 lt,%r9,_ASM_LABEL(f_byte_copy) /* copy bytes for small data length */
  72. /*
  73. * determine copy strategy based on alignment of source and destination
  74. */
  75. mask %r6,SRC,3 /* get 2 low order bits of source address */
  76. mask %r7,DEST,3 /* get 2 low order bits of destination addr */
  77. mak %r6,%r6,0<4> /* convert source bits to table offset */
  78. mak %r7,%r7,0<2> /* convert destination bits to table offset */
  79. or.u %r12,%r0,%hi16(_ASM_LABEL(f_strat))
  80. or %r12,%r12,%lo16(_ASM_LABEL(f_strat))
  81. addu %r6,%r6,%r7 /* compute final table offset for strategy */
  82. ld %r12,%r12,%r6 /* load the strategy routine */
  83. jmp %r12 /* branch to strategy routine */
  84. /*
  85. * Copy three bytes from src to destination then copy words
  86. */
  87. ASLOCAL(f_3byte_word_copy)
  88. ld.bu %r6,SRC,0 /* load byte from source */
  89. ld.bu %r7,SRC,1 /* load byte from source */
  90. ld.bu %r8,SRC,2 /* load byte from source */
  91. st.b %r6,DEST,0 /* store byte to destination */
  92. st.b %r7,DEST,1 /* store byte to destination */
  93. st.b %r8,DEST,2 /* store byte to destination */
  94. addu SRC,SRC,3 /* increment source pointer */
  95. addu DEST,DEST,3 /* increment destination pointer */
  96. br.n _ASM_LABEL(f_word_copy) /* copy full words */
  97. subu LEN,LEN,3 /* decrement length */
  98. /*
  99. * Copy 1 halfword from src to destination then copy words
  100. */
  101. ASLOCAL(f_1half_word_copy)
  102. ld.hu %r6,SRC,0 /* load half-word from source */
  103. st.h %r6,DEST,0 /* store half-word to destination */
  104. addu SRC,SRC,2 /* increment source pointer */
  105. addu DEST,DEST,2 /* increment destination pointer */
  106. br.n _ASM_LABEL(f_word_copy) /* copy full words */
  107. subu LEN,LEN,2 /* decrement remaining length */
  108. /*
  109. * Copy 1 byte from src to destination then copy words
  110. */
  111. ASLOCAL(f_1byte_word_copy)
  112. ld.bu %r6,SRC,0 /* load 1 byte from source */
  113. st.b %r6,DEST,0 /* store 1 byte to destination */
  114. addu SRC,SRC,1 /* increment source pointer */
  115. addu DEST,DEST,1 /* increment destination pointer */
  116. subu LEN,LEN,1 /* decrement remaining length */
  117. /* FALLTHROUGH */
  118. /*
  119. * Copy as many full words as possible, 4 words per loop
  120. */
  121. ASLOCAL(f_word_copy)
  122. cmp %r10,LEN,16 /* see if we have 16 bytes remaining */
  123. bb1 lo,%r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */
  124. ld %r6,SRC,0 /* load first word */
  125. ld %r7,SRC,4 /* load second word */
  126. ld %r8,SRC,8 /* load third word */
  127. ld %r9,SRC,12 /* load fourth word */
  128. st %r6,DEST,0 /* store first word */
  129. st %r7,DEST,4 /* store second word */
  130. st %r8,DEST,8 /* store third word */
  131. st %r9,DEST,12 /* store fourth word */
  132. addu SRC,SRC,16 /* increment source pointer */
  133. addu DEST,DEST,16 /* increment destination pointer */
  134. br.n _ASM_LABEL(f_word_copy) /* branch to copy another block */
  135. subu LEN,LEN,16 /* decrement remaining length */
  136. ASLOCAL(f_1byte_half_copy)
  137. ld.bu %r6,SRC,0 /* load 1 byte from source */
  138. st.b %r6,DEST,0 /* store 1 byte to destination */
  139. addu SRC,SRC,1 /* increment source pointer */
  140. addu DEST,DEST,1 /* increment destination pointer */
  141. subu LEN,LEN,1 /* decrement remaining length */
  142. /* FALLTHROUGH */
  143. ASLOCAL(f_half_copy)
  144. cmp %r10,LEN,16 /* see if we have 16 bytes remaining */
  145. bb1 lo,%r10,_ASM_LABEL(f_byte_copy) /* not enough left, copy bytes */
  146. ld.hu %r6,SRC,0 /* load first half-word */
  147. ld.hu %r7,SRC,2 /* load second half-word */
  148. ld.hu %r8,SRC,4 /* load third half-word */
  149. ld.hu %r9,SRC,6 /* load fourth half-word */
  150. ld.hu %r10,SRC,8 /* load fifth half-word */
  151. ld.hu %r11,SRC,10 /* load sixth half-word */
  152. ld.hu %r12,SRC,12 /* load seventh half-word */
  153. ld.hu %r13,SRC,14 /* load eighth half-word */
  154. st.h %r6,DEST,0 /* store first half-word */
  155. st.h %r7,DEST,2 /* store second half-word */
  156. st.h %r8,DEST,4 /* store third half-word */
  157. st.h %r9,DEST,6 /* store fourth half-word */
  158. st.h %r10,DEST,8 /* store fifth half-word */
  159. st.h %r11,DEST,10 /* store sixth half-word */
  160. st.h %r12,DEST,12 /* store seventh half-word */
  161. st.h %r13,DEST,14 /* store eighth half-word */
  162. addu SRC,SRC,16 /* increment source pointer */
  163. addu DEST,DEST,16 /* increment destination pointer */
  164. br.n _ASM_LABEL(f_half_copy) /* branch to copy another block */
  165. subu LEN,LEN,16 /* decrement remaining length */
  166. ASLOCAL(f_byte_copy)
  167. bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */
  168. ld.bu %r6,SRC,0 /* load byte from source */
  169. st.b %r6,DEST,0 /* store byte in destination */
  170. addu SRC,SRC,1 /* increment source pointer */
  171. addu DEST,DEST,1 /* increment destination pointer */
  172. br.n _ASM_LABEL(f_byte_copy) /* branch for next byte */
  173. subu LEN,LEN,1 /* decrement remaining length */
  174. #if defined(MEMMOVE) || defined(OVBCOPY)
  175. /*
  176. * source address is less than destination address, copy in reverse
  177. */
  178. ASLOCAL(bcopy_reverse)
  179. /*
  180. * start copy pointers at end of data
  181. */
  182. addu SRC,SRC,LEN /* start source at end of data */
  183. addu DEST,DEST,LEN /* start destination at end of data */
  184. /*
  185. * check for short data
  186. */
  187. cmp %r9,LEN,16 /* see if we have at least 16 bytes */
  188. bb1 lt,%r9,_ASM_LABEL(r_byte_copy) /* copy bytes for small data length */
  189. /*
  190. * determine copy strategy based on alignment of source and destination
  191. */
  192. mask %r6,SRC,3 /* get 2 low order bits of source address */
  193. mask %r7,DEST,3 /* get 2 low order bits of destination addr */
  194. mak %r6,%r6,0<4> /* convert source bits to table offset */
  195. mak %r7,%r7,0<2> /* convert destination bits to table offset */
  196. or.u %r12,%r0,%hi16(_ASM_LABEL(r_strat))
  197. or %r12,%r12,%lo16(_ASM_LABEL(r_strat))
  198. addu %r6,%r6,%r7 /* compute final table offset for strategy */
  199. ld %r12,%r12,%r6 /* load the strategy routine */
  200. jmp %r12 /* branch to strategy routine */
  201. /*
  202. * Copy three bytes from src to destination then copy words
  203. */
  204. ASLOCAL(r_3byte_word_copy)
  205. subu SRC,SRC,3 /* decrement source pointer */
  206. subu DEST,DEST,3 /* decrement destination pointer */
  207. ld.bu %r6,SRC,0 /* load byte from source */
  208. ld.bu %r7,SRC,1 /* load byte from source */
  209. ld.bu %r8,SRC,2 /* load byte from source */
  210. st.b %r6,DEST,0 /* store byte to destination */
  211. st.b %r7,DEST,1 /* store byte to destination */
  212. st.b %r8,DEST,2 /* store byte to destination */
  213. br.n _ASM_LABEL(r_word_copy) /* copy full words */
  214. subu LEN,LEN,3 /* decrement length */
  215. /*
  216. * Copy 1 halfword from src to destination then copy words
  217. */
  218. ASLOCAL(r_1half_word_copy)
  219. subu SRC,SRC,2 /* decrement source pointer */
  220. subu DEST,DEST,2 /* decrement destination pointer */
  221. ld.hu %r6,SRC,0 /* load half-word from source */
  222. st.h %r6,DEST,0 /* store half-word to destination */
  223. br.n _ASM_LABEL(r_word_copy) /* copy full words */
  224. subu LEN,LEN,2 /* decrement remaining length */
  225. /*
  226. * Copy 1 byte from src to destination then copy words
  227. */
  228. ASLOCAL(r_1byte_word_copy)
  229. subu SRC,SRC,1 /* decrement source pointer */
  230. subu DEST,DEST,1 /* decrement destination pointer */
  231. ld.bu %r6,SRC,0 /* load 1 byte from source */
  232. st.b %r6,DEST,0 /* store 1 byte to destination */
  233. subu LEN,LEN,1 /* decrement remaining length */
  234. /* FALLTHROUGH */
  235. /*
  236. * Copy as many full words as possible, 4 words per loop
  237. */
  238. ASLOCAL(r_word_copy)
  239. cmp %r10,LEN,16 /* see if we have 16 bytes remaining */
  240. bb1 lo,%r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */
  241. subu SRC,SRC,16 /* decrement source pointer */
  242. subu DEST,DEST,16 /* decrement destination pointer */
  243. ld %r6,SRC,0 /* load first word */
  244. ld %r7,SRC,4 /* load second word */
  245. ld %r8,SRC,8 /* load third word */
  246. ld %r9,SRC,12 /* load fourth word */
  247. st %r6,DEST,0 /* store first word */
  248. st %r7,DEST,4 /* store second word */
  249. st %r8,DEST,8 /* store third word */
  250. st %r9,DEST,12 /* store fourth word */
  251. br.n _ASM_LABEL(r_word_copy) /* branch to copy another block */
  252. subu LEN,LEN,16 /* decrement remaining length */
  253. ASLOCAL(r_1byte_half_copy)
  254. subu SRC,SRC,1 /* decrement source pointer */
  255. subu DEST,DEST,1 /* decrement destination pointer */
  256. ld.bu %r6,SRC,0 /* load 1 byte from source */
  257. st.b %r6,DEST,0 /* store 1 byte to destination */
  258. subu LEN,LEN,1 /* decrement remaining length */
  259. /* FALLTHROUGH */
  260. ASLOCAL(r_half_copy)
  261. cmp %r10,LEN,16 /* see if we have 16 bytes remaining */
  262. bb1 lo,%r10,_ASM_LABEL(r_byte_copy) /* not enough left, copy bytes */
  263. subu SRC,SRC,16 /* decrement source pointer */
  264. subu DEST,DEST,16 /* decrement destination pointer */
  265. ld.hu %r6,SRC,0 /* load first half-word */
  266. ld.hu %r7,SRC,2 /* load second half-word */
  267. ld.hu %r8,SRC,4 /* load third half-word */
  268. ld.hu %r9,SRC,6 /* load fourth half-word */
  269. ld.hu %r10,SRC,8 /* load fifth half-word */
  270. ld.hu %r11,SRC,10 /* load sixth half-word */
  271. ld.hu %r12,SRC,12 /* load seventh half-word */
  272. ld.hu %r13,SRC,14 /* load eighth half-word */
  273. st.h %r6,DEST,0 /* store first half-word */
  274. st.h %r7,DEST,2 /* store second half-word */
  275. st.h %r8,DEST,4 /* store third half-word */
  276. st.h %r9,DEST,6 /* store fourth half-word */
  277. st.h %r10,DEST,8 /* store fifth half-word */
  278. st.h %r11,DEST,10 /* store sixth half-word */
  279. st.h %r12,DEST,12 /* store seventh half-word */
  280. st.h %r13,DEST,14 /* store eighth half-word */
  281. br.n _ASM_LABEL(r_half_copy) /* branch to copy another block */
  282. subu LEN,LEN,16 /* decrement remaining length */
  283. ASLOCAL(r_byte_copy)
  284. bcnd eq0,LEN,_ASM_LABEL(bcopy_out) /* branch if nothing left to copy */
  285. subu SRC,SRC,1 /* decrement source pointer */
  286. subu DEST,DEST,1 /* decrement destination pointer */
  287. ld.bu %r6,SRC,0 /* load byte from source */
  288. st.b %r6,DEST,0 /* store byte in destination */
  289. br.n _ASM_LABEL(r_byte_copy) /* branch for next byte */
  290. subu LEN,LEN,1 /* decrement remaining length */
  291. #endif /* MEMMOVE || OVBCOPY */
  292. ASLOCAL(bcopy_out)
  293. #if defined(MEMCPY) || defined(MEMMOVE)
  294. jmp.n %r1 /* all done, return to caller */
  295. or %r2, SAVE, %r0
  296. #else
  297. jmp %r1 /* all done, return to caller */
  298. #endif
  299. .data
  300. .align 2
  301. ASLOCAL(f_strat)
  302. .word _ASM_LABEL(f_word_copy)
  303. .word _ASM_LABEL(f_byte_copy)
  304. .word _ASM_LABEL(f_half_copy)
  305. .word _ASM_LABEL(f_byte_copy)
  306. .word _ASM_LABEL(f_byte_copy)
  307. .word _ASM_LABEL(f_3byte_word_copy)
  308. .word _ASM_LABEL(f_byte_copy)
  309. .word _ASM_LABEL(f_1byte_half_copy)
  310. .word _ASM_LABEL(f_half_copy)
  311. .word _ASM_LABEL(f_byte_copy)
  312. .word _ASM_LABEL(f_1half_word_copy)
  313. .word _ASM_LABEL(f_byte_copy)
  314. .word _ASM_LABEL(f_byte_copy)
  315. .word _ASM_LABEL(f_1byte_half_copy)
  316. .word _ASM_LABEL(f_byte_copy)
  317. .word _ASM_LABEL(f_1byte_word_copy)
  318. #if defined(MEMMOVE) || defined(OVBCOPY)
  319. ASLOCAL(r_strat)
  320. .word _ASM_LABEL(r_word_copy)
  321. .word _ASM_LABEL(r_byte_copy)
  322. .word _ASM_LABEL(r_half_copy)
  323. .word _ASM_LABEL(r_byte_copy)
  324. .word _ASM_LABEL(r_byte_copy)
  325. .word _ASM_LABEL(r_1byte_word_copy)
  326. .word _ASM_LABEL(r_byte_copy)
  327. .word _ASM_LABEL(r_1byte_half_copy)
  328. .word _ASM_LABEL(r_half_copy)
  329. .word _ASM_LABEL(r_byte_copy)
  330. .word _ASM_LABEL(r_1half_word_copy)
  331. .word _ASM_LABEL(r_byte_copy)
  332. .word _ASM_LABEL(r_byte_copy)
  333. .word _ASM_LABEL(r_1byte_half_copy)
  334. .word _ASM_LABEL(r_byte_copy)
  335. .word _ASM_LABEL(r_3byte_word_copy)
  336. #endif