csum-copy_64.S 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * Copyright 2002, 2003 Andi Kleen, SuSE Labs.
  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. #include <asm/asm.h>
  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. *
  21. * Output
  22. * eax 64bit sum. undefined in case of exception.
  23. *
  24. * Wrappers need to take care of valid exception sum and zeroing.
  25. * They also should align source or destination to 8 bytes.
  26. */
  27. .macro source
  28. 10:
  29. _ASM_EXTABLE_UA(10b, .Lfault)
  30. .endm
  31. .macro dest
  32. 20:
  33. _ASM_EXTABLE_UA(20b, .Lfault)
  34. .endm
  35. SYM_FUNC_START(csum_partial_copy_generic)
  36. subq $5*8, %rsp
  37. movq %rbx, 0*8(%rsp)
  38. movq %r12, 1*8(%rsp)
  39. movq %r14, 2*8(%rsp)
  40. movq %r13, 3*8(%rsp)
  41. movq %r15, 4*8(%rsp)
  42. movl $-1, %eax
  43. xorl %r9d, %r9d
  44. movl %edx, %ecx
  45. cmpl $8, %ecx
  46. jb .Lshort
  47. testb $7, %sil
  48. jne .Lunaligned
  49. .Laligned:
  50. movl %ecx, %r12d
  51. shrq $6, %r12
  52. jz .Lhandle_tail /* < 64 */
  53. clc
  54. /* main loop. clear in 64 byte blocks */
  55. /* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
  56. /* r11: temp3, rdx: temp4, r12 loopcnt */
  57. /* r10: temp5, r15: temp6, r14 temp7, r13 temp8 */
  58. .p2align 4
  59. .Lloop:
  60. source
  61. movq (%rdi), %rbx
  62. source
  63. movq 8(%rdi), %r8
  64. source
  65. movq 16(%rdi), %r11
  66. source
  67. movq 24(%rdi), %rdx
  68. source
  69. movq 32(%rdi), %r10
  70. source
  71. movq 40(%rdi), %r15
  72. source
  73. movq 48(%rdi), %r14
  74. source
  75. movq 56(%rdi), %r13
  76. 30:
  77. /*
  78. * No _ASM_EXTABLE_UA; this is used for intentional prefetch on a
  79. * potentially unmapped kernel address.
  80. */
  81. _ASM_EXTABLE(30b, 2f)
  82. prefetcht0 5*64(%rdi)
  83. 2:
  84. adcq %rbx, %rax
  85. adcq %r8, %rax
  86. adcq %r11, %rax
  87. adcq %rdx, %rax
  88. adcq %r10, %rax
  89. adcq %r15, %rax
  90. adcq %r14, %rax
  91. adcq %r13, %rax
  92. decl %r12d
  93. dest
  94. movq %rbx, (%rsi)
  95. dest
  96. movq %r8, 8(%rsi)
  97. dest
  98. movq %r11, 16(%rsi)
  99. dest
  100. movq %rdx, 24(%rsi)
  101. dest
  102. movq %r10, 32(%rsi)
  103. dest
  104. movq %r15, 40(%rsi)
  105. dest
  106. movq %r14, 48(%rsi)
  107. dest
  108. movq %r13, 56(%rsi)
  109. leaq 64(%rdi), %rdi
  110. leaq 64(%rsi), %rsi
  111. jnz .Lloop
  112. adcq %r9, %rax
  113. /* do last up to 56 bytes */
  114. .Lhandle_tail:
  115. /* ecx: count, rcx.63: the end result needs to be rol8 */
  116. movq %rcx, %r10
  117. andl $63, %ecx
  118. shrl $3, %ecx
  119. jz .Lfold
  120. clc
  121. .p2align 4
  122. .Lloop_8:
  123. source
  124. movq (%rdi), %rbx
  125. adcq %rbx, %rax
  126. decl %ecx
  127. dest
  128. movq %rbx, (%rsi)
  129. leaq 8(%rsi), %rsi /* preserve carry */
  130. leaq 8(%rdi), %rdi
  131. jnz .Lloop_8
  132. adcq %r9, %rax /* add in carry */
  133. .Lfold:
  134. /* reduce checksum to 32bits */
  135. movl %eax, %ebx
  136. shrq $32, %rax
  137. addl %ebx, %eax
  138. adcl %r9d, %eax
  139. /* do last up to 6 bytes */
  140. .Lhandle_7:
  141. movl %r10d, %ecx
  142. andl $7, %ecx
  143. .L1: /* .Lshort rejoins the common path here */
  144. shrl $1, %ecx
  145. jz .Lhandle_1
  146. movl $2, %edx
  147. xorl %ebx, %ebx
  148. clc
  149. .p2align 4
  150. .Lloop_1:
  151. source
  152. movw (%rdi), %bx
  153. adcl %ebx, %eax
  154. decl %ecx
  155. dest
  156. movw %bx, (%rsi)
  157. leaq 2(%rdi), %rdi
  158. leaq 2(%rsi), %rsi
  159. jnz .Lloop_1
  160. adcl %r9d, %eax /* add in carry */
  161. /* handle last odd byte */
  162. .Lhandle_1:
  163. testb $1, %r10b
  164. jz .Lende
  165. xorl %ebx, %ebx
  166. source
  167. movb (%rdi), %bl
  168. dest
  169. movb %bl, (%rsi)
  170. addl %ebx, %eax
  171. adcl %r9d, %eax /* carry */
  172. .Lende:
  173. testq %r10, %r10
  174. js .Lwas_odd
  175. .Lout:
  176. movq 0*8(%rsp), %rbx
  177. movq 1*8(%rsp), %r12
  178. movq 2*8(%rsp), %r14
  179. movq 3*8(%rsp), %r13
  180. movq 4*8(%rsp), %r15
  181. addq $5*8, %rsp
  182. RET
  183. .Lshort:
  184. movl %ecx, %r10d
  185. jmp .L1
  186. .Lunaligned:
  187. xorl %ebx, %ebx
  188. testb $1, %sil
  189. jne .Lodd
  190. 1: testb $2, %sil
  191. je 2f
  192. source
  193. movw (%rdi), %bx
  194. dest
  195. movw %bx, (%rsi)
  196. leaq 2(%rdi), %rdi
  197. subq $2, %rcx
  198. leaq 2(%rsi), %rsi
  199. addq %rbx, %rax
  200. 2: testb $4, %sil
  201. je .Laligned
  202. source
  203. movl (%rdi), %ebx
  204. dest
  205. movl %ebx, (%rsi)
  206. leaq 4(%rdi), %rdi
  207. subq $4, %rcx
  208. leaq 4(%rsi), %rsi
  209. addq %rbx, %rax
  210. jmp .Laligned
  211. .Lodd:
  212. source
  213. movb (%rdi), %bl
  214. dest
  215. movb %bl, (%rsi)
  216. leaq 1(%rdi), %rdi
  217. leaq 1(%rsi), %rsi
  218. /* decrement, set MSB */
  219. leaq -1(%rcx, %rcx), %rcx
  220. rorq $1, %rcx
  221. shll $8, %ebx
  222. addq %rbx, %rax
  223. jmp 1b
  224. .Lwas_odd:
  225. roll $8, %eax
  226. jmp .Lout
  227. /* Exception: just return 0 */
  228. .Lfault:
  229. xorl %eax, %eax
  230. jmp .Lout
  231. SYM_FUNC_END(csum_partial_copy_generic)