checksum.S 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * INET An implementation of the TCP/IP protocol suite for the LINUX
  4. * operating system. INET is implemented using the BSD Socket
  5. * interface as the means of communication with the user level.
  6. *
  7. * IP/TCP/UDP checksumming routines
  8. *
  9. * Xtensa version: Copyright (C) 2001 Tensilica, Inc. by Kevin Chea
  10. * Optimized by Joe Taylor
  11. */
  12. #include <linux/errno.h>
  13. #include <linux/linkage.h>
  14. #include <asm/asmmacro.h>
  15. #include <asm/core.h>
  16. /*
  17. * computes a partial checksum, e.g. for TCP/UDP fragments
  18. */
  19. /*
  20. * unsigned int csum_partial(const unsigned char *buf, int len,
  21. * unsigned int sum);
  22. * a2 = buf
  23. * a3 = len
  24. * a4 = sum
  25. *
  26. * This function assumes 2- or 4-byte alignment. Other alignments will fail!
  27. */
  28. /* ONES_ADD converts twos-complement math to ones-complement. */
  29. #define ONES_ADD(sum, val) \
  30. add sum, sum, val ; \
  31. bgeu sum, val, 99f ; \
  32. addi sum, sum, 1 ; \
  33. 99: ;
  34. .text
  35. ENTRY(csum_partial)
  36. /*
  37. * Experiments with Ethernet and SLIP connections show that buf
  38. * is aligned on either a 2-byte or 4-byte boundary.
  39. */
  40. abi_entry_default
  41. extui a5, a2, 0, 2
  42. bnez a5, 8f /* branch if 2-byte aligned */
  43. /* Fall-through on common case, 4-byte alignment */
  44. 1:
  45. srli a5, a3, 5 /* 32-byte chunks */
  46. #if XCHAL_HAVE_LOOPS
  47. loopgtz a5, 2f
  48. #else
  49. beqz a5, 2f
  50. slli a5, a5, 5
  51. add a5, a5, a2 /* a5 = end of last 32-byte chunk */
  52. .Loop1:
  53. #endif
  54. l32i a6, a2, 0
  55. l32i a7, a2, 4
  56. ONES_ADD(a4, a6)
  57. ONES_ADD(a4, a7)
  58. l32i a6, a2, 8
  59. l32i a7, a2, 12
  60. ONES_ADD(a4, a6)
  61. ONES_ADD(a4, a7)
  62. l32i a6, a2, 16
  63. l32i a7, a2, 20
  64. ONES_ADD(a4, a6)
  65. ONES_ADD(a4, a7)
  66. l32i a6, a2, 24
  67. l32i a7, a2, 28
  68. ONES_ADD(a4, a6)
  69. ONES_ADD(a4, a7)
  70. addi a2, a2, 4*8
  71. #if !XCHAL_HAVE_LOOPS
  72. blt a2, a5, .Loop1
  73. #endif
  74. 2:
  75. extui a5, a3, 2, 3 /* remaining 4-byte chunks */
  76. #if XCHAL_HAVE_LOOPS
  77. loopgtz a5, 3f
  78. #else
  79. beqz a5, 3f
  80. slli a5, a5, 2
  81. add a5, a5, a2 /* a5 = end of last 4-byte chunk */
  82. .Loop2:
  83. #endif
  84. l32i a6, a2, 0
  85. ONES_ADD(a4, a6)
  86. addi a2, a2, 4
  87. #if !XCHAL_HAVE_LOOPS
  88. blt a2, a5, .Loop2
  89. #endif
  90. 3:
  91. _bbci.l a3, 1, 5f /* remaining 2-byte chunk */
  92. l16ui a6, a2, 0
  93. ONES_ADD(a4, a6)
  94. addi a2, a2, 2
  95. 5:
  96. _bbci.l a3, 0, 7f /* remaining 1-byte chunk */
  97. 6: l8ui a6, a2, 0
  98. #ifdef __XTENSA_EB__
  99. slli a6, a6, 8 /* load byte into bits 8..15 */
  100. #endif
  101. ONES_ADD(a4, a6)
  102. 7:
  103. mov a2, a4
  104. abi_ret_default
  105. /* uncommon case, buf is 2-byte aligned */
  106. 8:
  107. beqz a3, 7b /* branch if len == 0 */
  108. beqi a3, 1, 6b /* branch if len == 1 */
  109. extui a5, a2, 0, 1
  110. bnez a5, 8f /* branch if 1-byte aligned */
  111. l16ui a6, a2, 0 /* common case, len >= 2 */
  112. ONES_ADD(a4, a6)
  113. addi a2, a2, 2 /* adjust buf */
  114. addi a3, a3, -2 /* adjust len */
  115. j 1b /* now buf is 4-byte aligned */
  116. /* case: odd-byte aligned, len > 1
  117. * This case is dog slow, so don't give us an odd address.
  118. * (I don't think this ever happens, but just in case.)
  119. */
  120. 8:
  121. srli a5, a3, 2 /* 4-byte chunks */
  122. #if XCHAL_HAVE_LOOPS
  123. loopgtz a5, 2f
  124. #else
  125. beqz a5, 2f
  126. slli a5, a5, 2
  127. add a5, a5, a2 /* a5 = end of last 4-byte chunk */
  128. .Loop3:
  129. #endif
  130. l8ui a6, a2, 0 /* bits 24..31 */
  131. l16ui a7, a2, 1 /* bits 8..23 */
  132. l8ui a8, a2, 3 /* bits 0.. 8 */
  133. #ifdef __XTENSA_EB__
  134. slli a6, a6, 24
  135. #else
  136. slli a8, a8, 24
  137. #endif
  138. slli a7, a7, 8
  139. or a7, a7, a6
  140. or a7, a7, a8
  141. ONES_ADD(a4, a7)
  142. addi a2, a2, 4
  143. #if !XCHAL_HAVE_LOOPS
  144. blt a2, a5, .Loop3
  145. #endif
  146. 2:
  147. _bbci.l a3, 1, 3f /* remaining 2-byte chunk, still odd addr */
  148. l8ui a6, a2, 0
  149. l8ui a7, a2, 1
  150. #ifdef __XTENSA_EB__
  151. slli a6, a6, 8
  152. #else
  153. slli a7, a7, 8
  154. #endif
  155. or a7, a7, a6
  156. ONES_ADD(a4, a7)
  157. addi a2, a2, 2
  158. 3:
  159. j 5b /* branch to handle the remaining byte */
  160. ENDPROC(csum_partial)
  161. EXPORT_SYMBOL(csum_partial)
  162. /*
  163. * Copy from ds while checksumming, otherwise like csum_partial
  164. */
  165. /*
  166. unsigned int csum_partial_copy_generic (const char *src, char *dst, int len)
  167. a2 = src
  168. a3 = dst
  169. a4 = len
  170. a5 = sum
  171. a8 = temp
  172. a9 = temp
  173. a10 = temp
  174. This function is optimized for 4-byte aligned addresses. Other
  175. alignments work, but not nearly as efficiently.
  176. */
  177. ENTRY(csum_partial_copy_generic)
  178. abi_entry_default
  179. movi a5, -1
  180. or a10, a2, a3
  181. /* We optimize the following alignment tests for the 4-byte
  182. aligned case. Two bbsi.l instructions might seem more optimal
  183. (commented out below). However, both labels 5: and 3: are out
  184. of the imm8 range, so the assembler relaxes them into
  185. equivalent bbci.l, j combinations, which is actually
  186. slower. */
  187. extui a9, a10, 0, 2
  188. beqz a9, 1f /* branch if both are 4-byte aligned */
  189. bbsi.l a10, 0, 5f /* branch if one address is odd */
  190. j 3f /* one address is 2-byte aligned */
  191. /* _bbsi.l a10, 0, 5f */ /* branch if odd address */
  192. /* _bbsi.l a10, 1, 3f */ /* branch if 2-byte-aligned address */
  193. 1:
  194. /* src and dst are both 4-byte aligned */
  195. srli a10, a4, 5 /* 32-byte chunks */
  196. #if XCHAL_HAVE_LOOPS
  197. loopgtz a10, 2f
  198. #else
  199. beqz a10, 2f
  200. slli a10, a10, 5
  201. add a10, a10, a2 /* a10 = end of last 32-byte src chunk */
  202. .Loop5:
  203. #endif
  204. EX(10f) l32i a9, a2, 0
  205. EX(10f) l32i a8, a2, 4
  206. EX(10f) s32i a9, a3, 0
  207. EX(10f) s32i a8, a3, 4
  208. ONES_ADD(a5, a9)
  209. ONES_ADD(a5, a8)
  210. EX(10f) l32i a9, a2, 8
  211. EX(10f) l32i a8, a2, 12
  212. EX(10f) s32i a9, a3, 8
  213. EX(10f) s32i a8, a3, 12
  214. ONES_ADD(a5, a9)
  215. ONES_ADD(a5, a8)
  216. EX(10f) l32i a9, a2, 16
  217. EX(10f) l32i a8, a2, 20
  218. EX(10f) s32i a9, a3, 16
  219. EX(10f) s32i a8, a3, 20
  220. ONES_ADD(a5, a9)
  221. ONES_ADD(a5, a8)
  222. EX(10f) l32i a9, a2, 24
  223. EX(10f) l32i a8, a2, 28
  224. EX(10f) s32i a9, a3, 24
  225. EX(10f) s32i a8, a3, 28
  226. ONES_ADD(a5, a9)
  227. ONES_ADD(a5, a8)
  228. addi a2, a2, 32
  229. addi a3, a3, 32
  230. #if !XCHAL_HAVE_LOOPS
  231. blt a2, a10, .Loop5
  232. #endif
  233. 2:
  234. extui a10, a4, 2, 3 /* remaining 4-byte chunks */
  235. extui a4, a4, 0, 2 /* reset len for general-case, 2-byte chunks */
  236. #if XCHAL_HAVE_LOOPS
  237. loopgtz a10, 3f
  238. #else
  239. beqz a10, 3f
  240. slli a10, a10, 2
  241. add a10, a10, a2 /* a10 = end of last 4-byte src chunk */
  242. .Loop6:
  243. #endif
  244. EX(10f) l32i a9, a2, 0
  245. EX(10f) s32i a9, a3, 0
  246. ONES_ADD(a5, a9)
  247. addi a2, a2, 4
  248. addi a3, a3, 4
  249. #if !XCHAL_HAVE_LOOPS
  250. blt a2, a10, .Loop6
  251. #endif
  252. 3:
  253. /*
  254. Control comes to here in two cases: (1) It may fall through
  255. to here from the 4-byte alignment case to process, at most,
  256. one 2-byte chunk. (2) It branches to here from above if
  257. either src or dst is 2-byte aligned, and we process all bytes
  258. here, except for perhaps a trailing odd byte. It's
  259. inefficient, so align your addresses to 4-byte boundaries.
  260. a2 = src
  261. a3 = dst
  262. a4 = len
  263. a5 = sum
  264. */
  265. srli a10, a4, 1 /* 2-byte chunks */
  266. #if XCHAL_HAVE_LOOPS
  267. loopgtz a10, 4f
  268. #else
  269. beqz a10, 4f
  270. slli a10, a10, 1
  271. add a10, a10, a2 /* a10 = end of last 2-byte src chunk */
  272. .Loop7:
  273. #endif
  274. EX(10f) l16ui a9, a2, 0
  275. EX(10f) s16i a9, a3, 0
  276. ONES_ADD(a5, a9)
  277. addi a2, a2, 2
  278. addi a3, a3, 2
  279. #if !XCHAL_HAVE_LOOPS
  280. blt a2, a10, .Loop7
  281. #endif
  282. 4:
  283. /* This section processes a possible trailing odd byte. */
  284. _bbci.l a4, 0, 8f /* 1-byte chunk */
  285. EX(10f) l8ui a9, a2, 0
  286. EX(10f) s8i a9, a3, 0
  287. #ifdef __XTENSA_EB__
  288. slli a9, a9, 8 /* shift byte to bits 8..15 */
  289. #endif
  290. ONES_ADD(a5, a9)
  291. 8:
  292. mov a2, a5
  293. abi_ret_default
  294. 5:
  295. /* Control branch to here when either src or dst is odd. We
  296. process all bytes using 8-bit accesses. Grossly inefficient,
  297. so don't feed us an odd address. */
  298. srli a10, a4, 1 /* handle in pairs for 16-bit csum */
  299. #if XCHAL_HAVE_LOOPS
  300. loopgtz a10, 6f
  301. #else
  302. beqz a10, 6f
  303. slli a10, a10, 1
  304. add a10, a10, a2 /* a10 = end of last odd-aligned, 2-byte src chunk */
  305. .Loop8:
  306. #endif
  307. EX(10f) l8ui a9, a2, 0
  308. EX(10f) l8ui a8, a2, 1
  309. EX(10f) s8i a9, a3, 0
  310. EX(10f) s8i a8, a3, 1
  311. #ifdef __XTENSA_EB__
  312. slli a9, a9, 8 /* combine into a single 16-bit value */
  313. #else /* for checksum computation */
  314. slli a8, a8, 8
  315. #endif
  316. or a9, a9, a8
  317. ONES_ADD(a5, a9)
  318. addi a2, a2, 2
  319. addi a3, a3, 2
  320. #if !XCHAL_HAVE_LOOPS
  321. blt a2, a10, .Loop8
  322. #endif
  323. 6:
  324. j 4b /* process the possible trailing odd byte */
  325. ENDPROC(csum_partial_copy_generic)
  326. EXPORT_SYMBOL(csum_partial_copy_generic)
  327. # Exception handler:
  328. .section .fixup, "ax"
  329. 10:
  330. movi a2, 0
  331. abi_ret_default
  332. .previous