csum-copy.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright 2002 Andi Kleen
  3.  *
  4.  * This file is subject to the terms and conditions of the GNU General Public
  5.  * License.  See the file COPYING in the main directory of this archive
  6.  * for more details. No warranty for anything given at all.
  7.  */
  8.   #include <linux/linkage.h>
  9. #include <asm/errno.h>
  10. // #define FIX_ALIGNMENT 1
  11. /*
  12.  * Checksum copy with exception handling.
  13.  * On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the 
  14.  * destination is zeroed.
  15.  * 
  16.  * Input
  17.  * rdi  source
  18.  * rsi  destination
  19.  * edx  len (32bit)
  20.  * ecx  sum (32bit) 
  21.  * r8   src_err_ptr (int)
  22.  * r9   dst_err_ptr (int)
  23.  *
  24.  * Output
  25.  * eax  64bit sum. undefined in case of exception.
  26.  * 
  27.  * Wrappers need to take care of valid exception sum and zeroing.  
  28.  */
  29. /* for now - should vary this based on direction */
  30.  #define prefetch prefetcht2
  31.  #define movnti   movq
  32. .macro source
  33. 10:
  34. .section __ex_table,"a"
  35. .align 8
  36. .quad 10b,bad_source
  37. .previous
  38. .endm
  39. .macro dest
  40. 20:
  41. .section __ex_table,"a"
  42. .align 8
  43. .quad 20b,bad_dest
  44. .previous
  45. .endm
  46. .globl csum_partial_copy_generic
  47. .p2align
  48. csum_partial_copy_generic:
  49. prefetchnta (%rdi)
  50. pushq %rbx
  51. pushq %r12
  52. pushq %r14
  53. pushq %r15
  54. movq %r8,%r14
  55. movq %r9,%r15
  56. movl  %ecx,%eax
  57. movl  %edx,%ecx
  58. #ifdef FIX_ALIGNMENT
  59. /* align source to 8 bytes */
  60. movl %edi,%r8d
  61. andl $7,%r8d
  62. jnz  bad_alignment
  63. after_bad_alignment:
  64. #endif
  65. movl  $64,%r10d
  66. xorl  %r9d,%r9d
  67. movq  %rcx,%r12
  68. shrq  $6,%r12
  69. /* loopcounter is maintained as one less to test efficiently for the
  70.    previous to last iteration. This is needed to stop the prefetching. */
  71. decq  %r12
  72. js    handle_tail       /* < 64 */
  73. jz    loop_no_prefetch  /* = 64 + X */ 
  74. /* main loop. clear in 64 byte blocks */
  75. /* tries hard not to prefetch over the boundary */
  76. /* r10: 64, r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
  77. /* r11: temp3, rdx: temp4, r12 loopcnt */
  78. .p2align
  79. loop:
  80. /* Could prefetch more than one loop, but then it would be even
  81.    trickier to avoid prefetching over the boundary. The hardware prefetch
  82.    should take care of this anyways. The reason for this prefetch is
  83.    just the non temporal hint to avoid cache pollution. Hopefully this
  84.    will be handled properly by the hardware. */
  85. prefetchnta 64(%rdi) 
  86. loop_no_prefetch:
  87. source
  88. movq  (%rdi),%rbx
  89. source
  90. movq  8(%rdi),%r8
  91. source
  92. movq  16(%rdi),%r11
  93. source
  94. movq  24(%rdi),%rdx
  95. dest
  96. movnti %rbx,(%rsi)
  97. dest
  98. movnti %r8,8(%rsi)
  99. dest
  100. movnti %r11,16(%rsi)
  101. dest
  102. movnti %rdx,24(%rsi)
  103. addq  %rbx,%rax
  104. adcq  %r8,%rax
  105. adcq  %r11,%rax
  106. adcq  %rdx,%rax
  107. source
  108. movq  32(%rdi),%rbx
  109. source
  110. movq  40(%rdi),%r8
  111. source
  112. movq  48(%rdi),%r11
  113. source
  114. movq  56(%rdi),%rdx
  115. dest
  116. movnti %rbx,32(%rsi)
  117. dest
  118. movnti %r8,40(%rsi)
  119. dest
  120. movnti %r11,48(%rsi)
  121. dest
  122. movnti %rdx,56(%rsi)
  123. adcq %rbx,%rax
  124. adcq %r8,%rax
  125. adcq %r11,%rax
  126. adcq %rdx,%rax
  127. adcq %r9,%rax /* add in carry */
  128. addq %r10,%rdi
  129. addq %r10,%rsi
  130. decq %r12
  131. jz   loop_no_prefetch /* previous to last iteration? */
  132. jns  loop
  133. /* do last upto 56 bytes */
  134. handle_tail:
  135. /* ecx: count */
  136. movl %ecx,%r10d
  137. andl $63,%ecx
  138. shrl $3,%ecx
  139. jz   fold
  140. clc
  141. movl $8,%edx
  142. loop_8:
  143. source
  144. movq (%rdi),%rbx
  145. adcq %rbx,%rax
  146. dest
  147. movnti %rbx,(%rsi)
  148. leaq (%rsi,%rdx),%rsi /* preserve carry */
  149. leaq (%rdi,%rdx),%rdi
  150. decl %ecx
  151. jnz loop_8
  152. adcq %r9,%rax /* add in carry */
  153. fold:
  154. movl %eax,%ebx
  155. shrq $32,%rax
  156. addq %rbx,%rax
  157. /* do last upto 6 bytes */
  158. handle_7:
  159. movl %r10d,%ecx
  160. andl $7,%ecx
  161. shrl $1,%ecx
  162. jz   handle_1
  163. movl $2,%edx
  164. xorl %ebx,%ebx
  165. clc  
  166. loop_1:
  167. source
  168. movw (%rdi),%bx
  169. adcq %rbx,%rax
  170. dest
  171. movw %bx,(%rsi)
  172. addq %rdx,%rdi
  173. addq %rdx,%rsi
  174. decl %ecx
  175. jnz loop_1
  176. adcw %r9w,%ax /* add in carry */
  177. /* handle last odd byte */
  178. handle_1:
  179. testl $1,%r10d
  180. jz    ende
  181. xorl  %ebx,%ebx
  182. source
  183. movb (%rdi),%bl
  184. dest
  185. movb %bl,(%rsi)
  186. addw %bx,%ax
  187. adcw %r9w,%ax /* carry */
  188. ende:
  189. sfence
  190. popq %r15
  191. popq %r14
  192. popq %r12
  193. popq %rbx
  194. ret
  195. #ifdef FIX_ALIGNMENT
  196. /* align source to 8 bytes. */
  197. /* r8d: unalignedness, ecx len */
  198. bad_alignment:
  199. testl $1,%edi
  200. jnz   odd_source
  201. /* compute distance to next aligned position */
  202. movl $8,%r8d
  203. xchgl %r8d,%ecx
  204. subl %r8d,%ecx
  205. /* handle unaligned part */
  206. shrl $1,%ecx
  207. xorl %ebx,%ebx
  208. movl $2,%r10d
  209. align_loop:
  210. source
  211. movw (%rdi),%bx
  212. addq %rbx,%rax /* carry cannot happen */
  213. dest
  214. movw %bx,(%rsi)
  215. addq %r10,%rdi
  216. addq %r10,%rsi
  217. decl %ecx
  218. jnz align_loop
  219. jmp after_bad_alignment
  220. /* weird case. need to swap the sum at the end because the spec requires
  221.    16 bit words of the sum to be always paired. 
  222.    handle it recursively because it should be rather rare. */
  223. odd_source:
  224. /* copy odd byte */
  225. xorl %ebx,%ebx
  226. source
  227. movb (%rdi),%bl
  228. addl %ebx,%eax       /* add to old checksum */
  229. adcl $0,%ecx
  230. dest
  231. movb %al,(%rsi)
  232. /* fix arguments */
  233. movl %eax,%ecx
  234. incq %rsi
  235. incq %rdi
  236. decq %rdx 
  237. call csum_partial_copy_generic
  238. bswap %eax        /* this should work, but check */
  239. jmp ende
  240. #endif
  241. /* Exception handlers. Very simple, zeroing is done in the wrappers */
  242. bad_source:
  243. movl $-EFAULT,(%r14)
  244. jmp  ende
  245. bad_dest:
  246. movl $-EFAULT,(%r15)
  247. jmp ende