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