^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/arm/lib/csumpartial.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1995-1998 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/assembler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Function: __u32 csum_partial(const char *src, int len, __u32 sum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Params : r0 = buffer, r1 = len, r2 = checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Returns : r0 = new checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) buf .req r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) len .req r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) sum .req r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) td0 .req r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) td1 .req r4 @ save before use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) td2 .req r5 @ save before use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) td3 .req lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .Lzero: mov r0, sum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) add sp, sp, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ldr pc, [sp], #4
^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) * Handle 0 to 7 bytes, with any alignment of source and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * destination pointers. Note that when we get here, C = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .Lless8: teq len, #0 @ check for zero count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) beq .Lzero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* we must have at least one byte. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) tst buf, #1 @ odd address?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) movne sum, sum, ror #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ldrbne td0, [buf], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) subne len, len, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) adcsne sum, sum, td0, put_byte_1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .Lless4: tst len, #6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) beq .Lless8_byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* we are now half-word aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .Lless8_wordlp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #if __LINUX_ARM_ARCH__ >= 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ldrh td0, [buf], #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) sub len, len, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ldrb td0, [buf], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ldrb td3, [buf], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) sub len, len, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #ifndef __ARMEB__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) orr td0, td0, td3, lsl #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) orr td0, td3, td0, lsl #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) adcs sum, sum, td0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) tst len, #6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bne .Lless8_wordlp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .Lless8_byte: tst len, #1 @ odd number of bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ldrbne td0, [buf], #1 @ include last byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) adcsne sum, sum, td0, put_byte_0 @ update checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .Ldone: adc r0, sum, #0 @ collect up the last carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ldr td0, [sp], #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) tst td0, #1 @ check buffer alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) movne r0, r0, ror #8 @ rotate checksum by 8 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ldr pc, [sp], #4 @ return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .Lnot_aligned: tst buf, #1 @ odd address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ldrbne td0, [buf], #1 @ make even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) subne len, len, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) adcsne sum, sum, td0, put_byte_1 @ update checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) tst buf, #2 @ 32-bit aligned?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #if __LINUX_ARM_ARCH__ >= 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ldrhne td0, [buf], #2 @ make 32-bit aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) subne len, len, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ldrbne td0, [buf], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ldrbne ip, [buf], #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) subne len, len, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #ifndef __ARMEB__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) orrne td0, td0, ip, lsl #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) orrne td0, ip, td0, lsl #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) adcsne sum, sum, td0 @ update checksum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ENTRY(csum_partial)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) stmfd sp!, {buf, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) cmp len, #8 @ Ensure that we have at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) blo .Lless8 @ 8 bytes to copy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) tst buf, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) movne sum, sum, ror #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) adds sum, sum, #0 @ C = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) tst buf, #3 @ Test destination alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) blne .Lnot_aligned @ align destination, return here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 1: bics ip, len, #31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) beq 3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) stmfd sp!, {r4 - r5}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 2: ldmia buf!, {td0, td1, td2, td3}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) adcs sum, sum, td0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) adcs sum, sum, td1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) adcs sum, sum, td2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) adcs sum, sum, td3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ldmia buf!, {td0, td1, td2, td3}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) adcs sum, sum, td0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) adcs sum, sum, td1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) adcs sum, sum, td2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) adcs sum, sum, td3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) sub ip, ip, #32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) teq ip, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bne 2b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ldmfd sp!, {r4 - r5}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 3: tst len, #0x1c @ should not change C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) beq .Lless4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 4: ldr td0, [buf], #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) sub len, len, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) adcs sum, sum, td0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) tst len, #0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) bne 4b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) b .Lless4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ENDPROC(csum_partial)