/* SPDX-License-Identifier: GPL-2.0-only */1/*2* linux/arch/arm/lib/csumpartial.S3*4* Copyright (C) 1995-1998 Russell King5*/6#include <linux/linkage.h>7#include <asm/assembler.h>89.text1011/*12* Function: __u32 csum_partial(const char *src, int len, __u32 sum)13* Params : r0 = buffer, r1 = len, r2 = checksum14* Returns : r0 = new checksum15*/1617buf .req r018len .req r119sum .req r220td0 .req r321td1 .req r4 @ save before use22td2 .req r5 @ save before use23td3 .req lr2425.Lzero: mov r0, sum26add sp, sp, #427ldr pc, [sp], #42829/*30* Handle 0 to 7 bytes, with any alignment of source and31* destination pointers. Note that when we get here, C = 032*/33.Lless8: teq len, #0 @ check for zero count34beq .Lzero3536/* we must have at least one byte. */37tst buf, #1 @ odd address?38movne sum, sum, ror #839ldrbne td0, [buf], #140subne len, len, #141adcsne sum, sum, td0, put_byte_14243.Lless4: tst len, #644beq .Lless8_byte4546/* we are now half-word aligned */4748.Lless8_wordlp:49#if __LINUX_ARM_ARCH__ >= 450ldrh td0, [buf], #251sub len, len, #252#else53ldrb td0, [buf], #154ldrb td3, [buf], #155sub len, len, #256#ifndef __ARMEB__57orr td0, td0, td3, lsl #858#else59orr td0, td3, td0, lsl #860#endif61#endif62adcs sum, sum, td063tst len, #664bne .Lless8_wordlp6566.Lless8_byte: tst len, #1 @ odd number of bytes67ldrbne td0, [buf], #1 @ include last byte68adcsne sum, sum, td0, put_byte_0 @ update checksum6970.Ldone: adc r0, sum, #0 @ collect up the last carry71ldr td0, [sp], #472tst td0, #1 @ check buffer alignment73movne r0, r0, ror #8 @ rotate checksum by 8 bits74ldr pc, [sp], #4 @ return7576.Lnot_aligned: tst buf, #1 @ odd address77ldrbne td0, [buf], #1 @ make even78subne len, len, #179adcsne sum, sum, td0, put_byte_1 @ update checksum8081tst buf, #2 @ 32-bit aligned?82#if __LINUX_ARM_ARCH__ >= 483ldrhne td0, [buf], #2 @ make 32-bit aligned84subne len, len, #285#else86ldrbne td0, [buf], #187ldrbne ip, [buf], #188subne len, len, #289#ifndef __ARMEB__90orrne td0, td0, ip, lsl #891#else92orrne td0, ip, td0, lsl #893#endif94#endif95adcsne sum, sum, td0 @ update checksum96ret lr9798ENTRY(csum_partial)99stmfd sp!, {buf, lr}100cmp len, #8 @ Ensure that we have at least101blo .Lless8 @ 8 bytes to copy.102103tst buf, #1104movne sum, sum, ror #8105106adds sum, sum, #0 @ C = 0107tst buf, #3 @ Test destination alignment108blne .Lnot_aligned @ align destination, return here1091101: bics ip, len, #31111beq 3f112113stmfd sp!, {r4 - r5}1142: ldmia buf!, {td0, td1, td2, td3}115adcs sum, sum, td0116adcs sum, sum, td1117adcs sum, sum, td2118adcs sum, sum, td3119ldmia buf!, {td0, td1, td2, td3}120adcs sum, sum, td0121adcs sum, sum, td1122adcs sum, sum, td2123adcs sum, sum, td3124sub ip, ip, #32125teq ip, #0126bne 2b127ldmfd sp!, {r4 - r5}1281293: tst len, #0x1c @ should not change C130beq .Lless41311324: ldr td0, [buf], #4133sub len, len, #4134adcs sum, sum, td0135tst len, #0x1c136bne 4b137b .Lless4138ENDPROC(csum_partial)139140141