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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * INET An implementation of the TCP/IP protocol suite for the LINUX
  3.  * operating system.  INET is implemented using the  BSD Socket
  4.  * interface as the means of communication with the user level.
  5.  *
  6.  * IP/TCP/UDP checksumming routines
  7.  *
  8.  * Authors: Jorge Cwik, <jorge@laser.satlink.net>
  9.  * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  10.  * Tom May, <ftom@netcom.com>
  11.  *              Pentium Pro/II routines:
  12.  *              Alexander Kjeldaas <astor@guardian.no>
  13.  *              Finn Arne Gangstad <finnag@guardian.no>
  14.  * Lots of code moved from tcp.c and ip.c; see those files
  15.  * for more names.
  16.  *
  17.  * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
  18.  *      handling.
  19.  * Andi Kleen,  add zeroing on error
  20.  *                   converted to pure assembler
  21.  *
  22.  * This program is free software; you can redistribute it and/or
  23.  * modify it under the terms of the GNU General Public License
  24.  * as published by the Free Software Foundation; either version
  25.  * 2 of the License, or (at your option) any later version.
  26.  */
  27. #include <linux/config.h>
  28. #include <asm/errno.h>
  29. /*
  30.  * computes a partial checksum, e.g. for TCP/UDP fragments
  31.  */
  32. /*
  33. unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
  34.  */
  35. .text
  36. .align 4
  37. .globl csum_partial
  38. #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
  39.   /*
  40.    * Experiments with Ethernet and SLIP connections show that buff
  41.    * is aligned on either a 2-byte or 4-byte boundary.  We get at
  42.    * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
  43.    * Fortunately, it is easy to convert 2-byte alignment to 4-byte
  44.    * alignment for the unrolled loop.
  45.    */
  46. csum_partial:
  47. pushl %esi
  48. pushl %ebx
  49. movl 20(%esp),%eax # Function arg: unsigned int sum
  50. movl 16(%esp),%ecx # Function arg: int len
  51. movl 12(%esp),%esi # Function arg: unsigned char *buff
  52. testl $3, %esi # Check alignment.
  53. jz 2f # Jump if alignment is ok.
  54. testl $1, %esi # Check alignment.
  55. jz 10f # Jump if alignment is boundary of 2bytes.
  56. # buf is odd
  57. dec %ecx
  58. jl 8f
  59. movzbl (%esi), %ebx
  60. adcl %ebx, %eax
  61. roll $8, %eax
  62. inc %esi
  63. testl $2, %esi
  64. jz 2f
  65. 10:
  66. subl $2, %ecx # Alignment uses up two bytes.
  67. jae 1f # Jump if we had at least two bytes.
  68. addl $2, %ecx # ecx was < 2.  Deal with it.
  69. jmp 4f
  70. 1: movw (%esi), %bx
  71. addl $2, %esi
  72. addw %bx, %ax
  73. adcl $0, %eax
  74. 2:
  75. movl %ecx, %edx
  76. shrl $5, %ecx
  77. jz 2f
  78. testl %esi, %esi
  79. 1: movl (%esi), %ebx
  80. adcl %ebx, %eax
  81. movl 4(%esi), %ebx
  82. adcl %ebx, %eax
  83. movl 8(%esi), %ebx
  84. adcl %ebx, %eax
  85. movl 12(%esi), %ebx
  86. adcl %ebx, %eax
  87. movl 16(%esi), %ebx
  88. adcl %ebx, %eax
  89. movl 20(%esi), %ebx
  90. adcl %ebx, %eax
  91. movl 24(%esi), %ebx
  92. adcl %ebx, %eax
  93. movl 28(%esi), %ebx
  94. adcl %ebx, %eax
  95. lea 32(%esi), %esi
  96. dec %ecx
  97. jne 1b
  98. adcl $0, %eax
  99. 2: movl %edx, %ecx
  100. andl $0x1c, %edx
  101. je 4f
  102. shrl $2, %edx # This clears CF
  103. 3: adcl (%esi), %eax
  104. lea 4(%esi), %esi
  105. dec %edx
  106. jne 3b
  107. adcl $0, %eax
  108. 4: andl $3, %ecx
  109. jz 7f
  110. cmpl $2, %ecx
  111. jb 5f
  112. movw (%esi),%cx
  113. leal 2(%esi),%esi
  114. je 6f
  115. shll $16,%ecx
  116. 5: movb (%esi),%cl
  117. 6: addl %ecx,%eax
  118. adcl $0, %eax 
  119. 7:
  120. testl $1, 12(%esp)
  121. jz 8f
  122. roll $8, %eax
  123. 8:
  124. popl %ebx
  125. popl %esi
  126. ret
  127. #else
  128. /* Version for PentiumII/PPro */
  129. csum_partial:
  130. pushl %esi
  131. pushl %ebx
  132. movl 20(%esp),%eax # Function arg: unsigned int sum
  133. movl 16(%esp),%ecx # Function arg: int len
  134. movl 12(%esp),%esi # Function arg: const unsigned char *buf
  135. testl $3, %esi         
  136. jnz 25f                 
  137. 10:
  138. movl %ecx, %edx
  139. movl %ecx, %ebx
  140. andl $0x7c, %ebx
  141. shrl $7, %ecx
  142. addl %ebx,%esi
  143. shrl $2, %ebx  
  144. negl %ebx
  145. lea 45f(%ebx,%ebx,2), %ebx
  146. testl %esi, %esi
  147. jmp *%ebx
  148. # Handle 2-byte-aligned regions
  149. 20: addw (%esi), %ax
  150. lea 2(%esi), %esi
  151. adcl $0, %eax
  152. jmp 10b
  153. 25:
  154. testl $1, %esi         
  155. jz 30f                 
  156. # buf is odd
  157. dec %ecx
  158. jl 90f
  159. movzbl (%esi), %ebx
  160. addl %ebx, %eax
  161. adcl $0, %eax
  162. roll $8, %eax
  163. inc %esi
  164. testl $2, %esi
  165. jz 10b
  166. 30: subl $2, %ecx          
  167. ja 20b                 
  168. je 32f
  169. addl $2, %ecx
  170. jz 80f
  171. movzbl (%esi),%ebx # csumming 1 byte, 2-aligned
  172. addl %ebx, %eax
  173. adcl $0, %eax
  174. jmp 80f
  175. 32:
  176. addw (%esi), %ax # csumming 2 bytes, 2-aligned
  177. adcl $0, %eax
  178. jmp 80f
  179. 40: 
  180. addl -128(%esi), %eax
  181. adcl -124(%esi), %eax
  182. adcl -120(%esi), %eax
  183. adcl -116(%esi), %eax   
  184. adcl -112(%esi), %eax   
  185. adcl -108(%esi), %eax
  186. adcl -104(%esi), %eax
  187. adcl -100(%esi), %eax
  188. adcl -96(%esi), %eax
  189. adcl -92(%esi), %eax
  190. adcl -88(%esi), %eax
  191. adcl -84(%esi), %eax
  192. adcl -80(%esi), %eax
  193. adcl -76(%esi), %eax
  194. adcl -72(%esi), %eax
  195. adcl -68(%esi), %eax
  196. adcl -64(%esi), %eax     
  197. adcl -60(%esi), %eax     
  198. adcl -56(%esi), %eax     
  199. adcl -52(%esi), %eax   
  200. adcl -48(%esi), %eax   
  201. adcl -44(%esi), %eax
  202. adcl -40(%esi), %eax
  203. adcl -36(%esi), %eax
  204. adcl -32(%esi), %eax
  205. adcl -28(%esi), %eax
  206. adcl -24(%esi), %eax
  207. adcl -20(%esi), %eax
  208. adcl -16(%esi), %eax
  209. adcl -12(%esi), %eax
  210. adcl -8(%esi), %eax
  211. adcl -4(%esi), %eax
  212. 45:
  213. lea 128(%esi), %esi
  214. adcl $0, %eax
  215. dec %ecx
  216. jge 40b
  217. movl %edx, %ecx
  218. 50: andl $3, %ecx
  219. jz 80f
  220. # Handle the last 1-3 bytes without jumping
  221. notl %ecx # 1->2, 2->1, 3->0, higher bits are masked
  222. movl $0xffffff,%ebx # by the shll and shrl instructions
  223. shll $3,%ecx
  224. shrl %cl,%ebx
  225. andl -128(%esi),%ebx # esi is 4-aligned so should be ok
  226. addl %ebx,%eax
  227. adcl $0,%eax
  228. 80: 
  229. testl $1, 12(%esp)
  230. jz 90f
  231. roll $8, %eax
  232. 90: 
  233. popl %ebx
  234. popl %esi
  235. ret
  236. #endif
  237. /*
  238. unsigned int csum_partial_copy_generic (const char *src, char *dst,
  239.   int len, int sum, int *src_err_ptr, int *dst_err_ptr)
  240.  */ 
  241. /*
  242.  * Copy from ds while checksumming, otherwise like csum_partial
  243.  *
  244.  * The macros SRC and DST specify the type of access for the instruction.
  245.  * thus we can call a custom exception handler for all access types.
  246.  *
  247.  * FIXME: could someone double-check whether I haven't mixed up some SRC and
  248.  *   DST definitions? It's damn hard to trigger all cases.  I hope I got
  249.  *   them all but there's no guarantee.
  250.  */
  251. #define SRC(y...)
  252. 9999: y;
  253. .section __ex_table, "a";
  254. .long 9999b, 6001f ;
  255. .previous
  256. #define DST(y...)
  257. 9999: y;
  258. .section __ex_table, "a";
  259. .long 9999b, 6002f ;
  260. .previous
  261. .align 4
  262. .globl csum_partial_copy_generic
  263. #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
  264. #define ARGBASE 16
  265. #define FP 12
  266. csum_partial_copy_generic:
  267. subl  $4,%esp
  268. pushl %edi
  269. pushl %esi
  270. pushl %ebx
  271. movl ARGBASE+16(%esp),%eax # sum
  272. movl ARGBASE+12(%esp),%ecx # len
  273. movl ARGBASE+4(%esp),%esi # src
  274. movl ARGBASE+8(%esp),%edi # dst
  275. testl $2, %edi # Check alignment. 
  276. jz 2f # Jump if alignment is ok.
  277. subl $2, %ecx # Alignment uses up two bytes.
  278. jae 1f # Jump if we had at least two bytes.
  279. addl $2, %ecx # ecx was < 2.  Deal with it.
  280. jmp 4f
  281. SRC(1: movw (%esi), %bx )
  282. addl $2, %esi
  283. DST( movw %bx, (%edi) )
  284. addl $2, %edi
  285. addw %bx, %ax
  286. adcl $0, %eax
  287. 2:
  288. movl %ecx, FP(%esp)
  289. shrl $5, %ecx
  290. jz 2f
  291. testl %esi, %esi
  292. SRC(1: movl (%esi), %ebx )
  293. SRC( movl 4(%esi), %edx )
  294. adcl %ebx, %eax
  295. DST( movl %ebx, (%edi) )
  296. adcl %edx, %eax
  297. DST( movl %edx, 4(%edi) )
  298. SRC( movl 8(%esi), %ebx )
  299. SRC( movl 12(%esi), %edx )
  300. adcl %ebx, %eax
  301. DST( movl %ebx, 8(%edi) )
  302. adcl %edx, %eax
  303. DST( movl %edx, 12(%edi) )
  304. SRC( movl 16(%esi), %ebx  )
  305. SRC( movl 20(%esi), %edx )
  306. adcl %ebx, %eax
  307. DST( movl %ebx, 16(%edi) )
  308. adcl %edx, %eax
  309. DST( movl %edx, 20(%edi) )
  310. SRC( movl 24(%esi), %ebx )
  311. SRC( movl 28(%esi), %edx )
  312. adcl %ebx, %eax
  313. DST( movl %ebx, 24(%edi) )
  314. adcl %edx, %eax
  315. DST( movl %edx, 28(%edi) )
  316. lea 32(%esi), %esi
  317. lea 32(%edi), %edi
  318. dec %ecx
  319. jne 1b
  320. adcl $0, %eax
  321. 2: movl FP(%esp), %edx
  322. movl %edx, %ecx
  323. andl $0x1c, %edx
  324. je 4f
  325. shrl $2, %edx # This clears CF
  326. SRC(3: movl (%esi), %ebx )
  327. adcl %ebx, %eax
  328. DST( movl %ebx, (%edi) )
  329. lea 4(%esi), %esi
  330. lea 4(%edi), %edi
  331. dec %edx
  332. jne 3b
  333. adcl $0, %eax
  334. 4: andl $3, %ecx
  335. jz 7f
  336. cmpl $2, %ecx
  337. jb 5f
  338. SRC( movw (%esi), %cx )
  339. leal 2(%esi), %esi
  340. DST( movw %cx, (%edi) )
  341. leal 2(%edi), %edi
  342. je 6f
  343. shll $16,%ecx
  344. SRC(5: movb (%esi), %cl )
  345. DST( movb %cl, (%edi) )
  346. 6: addl %ecx, %eax
  347. adcl $0, %eax
  348. 7:
  349. 5000:
  350. # Exception handler:
  351. .section .fixup, "ax"
  352. 6001:
  353. movl ARGBASE+20(%esp), %ebx # src_err_ptr
  354. movl $-EFAULT, (%ebx)
  355. # zero the complete destination - computing the rest
  356. # is too much work 
  357. movl ARGBASE+8(%esp), %edi # dst
  358. movl ARGBASE+12(%esp), %ecx # len
  359. xorl %eax,%eax
  360. rep ; stosb
  361. jmp 5000b
  362. 6002:
  363. movl ARGBASE+24(%esp), %ebx # dst_err_ptr
  364. movl $-EFAULT,(%ebx)
  365. jmp 5000b
  366. .previous
  367. popl %ebx
  368. popl %esi
  369. popl %edi
  370. popl %ecx # equivalent to addl $4,%esp
  371. ret
  372. #else
  373. /* Version for PentiumII/PPro */
  374. #define ROUND1(x) 
  375. SRC(movl x(%esi), %ebx ) ;
  376. addl %ebx, %eax ;
  377. DST(movl %ebx, x(%edi) ) ; 
  378. #define ROUND(x) 
  379. SRC(movl x(%esi), %ebx ) ;
  380. adcl %ebx, %eax ;
  381. DST(movl %ebx, x(%edi) ) ;
  382. #define ARGBASE 12
  383. csum_partial_copy_generic:
  384. pushl %ebx
  385. pushl %edi
  386. pushl %esi
  387. movl ARGBASE+4(%esp),%esi #src
  388. movl ARGBASE+8(%esp),%edi #dst
  389. movl ARGBASE+12(%esp),%ecx #len
  390. movl ARGBASE+16(%esp),%eax #sum
  391. # movl %ecx, %edx  
  392. movl %ecx, %ebx  
  393. movl %esi, %edx
  394. shrl $6, %ecx     
  395. andl $0x3c, %ebx  
  396. negl %ebx
  397. subl %ebx, %esi  
  398. subl %ebx, %edi  
  399. lea  -1(%esi),%edx
  400. andl $-32,%edx
  401. lea 3f(%ebx,%ebx), %ebx
  402. testl %esi, %esi 
  403. jmp *%ebx
  404. 1: addl $64,%esi
  405. addl $64,%edi 
  406. SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl)
  407. ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)
  408. ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)
  409. ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)
  410. ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)
  411. 3: adcl $0,%eax
  412. addl $64, %edx
  413. dec %ecx
  414. jge 1b
  415. 4: movl ARGBASE+12(%esp),%edx #len
  416. andl $3, %edx
  417. jz 7f
  418. cmpl $2, %edx
  419. jb 5f
  420. SRC( movw (%esi), %dx         )
  421. leal 2(%esi), %esi
  422. DST( movw %dx, (%edi)         )
  423. leal 2(%edi), %edi
  424. je 6f
  425. shll $16,%edx
  426. 5:
  427. SRC( movb (%esi), %dl         )
  428. DST( movb %dl, (%edi)         )
  429. 6: addl %edx, %eax
  430. adcl $0, %eax
  431. 7:
  432. .section .fixup, "ax"
  433. 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
  434. movl $-EFAULT, (%ebx)
  435. # zero the complete destination (computing the rest is too much work)
  436. movl ARGBASE+8(%esp),%edi # dst
  437. movl ARGBASE+12(%esp),%ecx # len
  438. xorl %eax,%eax
  439. rep; stosb
  440. jmp 7b
  441. 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
  442. movl $-EFAULT, (%ebx)
  443. jmp  7b
  444. .previous
  445. popl %esi
  446. popl %edi
  447. popl %ebx
  448. ret
  449. #undef ROUND
  450. #undef ROUND1
  451. #endif