/*1* linux/arch/arm/lib/csumpartial.S2*3* Copyright (C) 1995-1998 Russell King4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License version 2 as7* published by the Free Software Foundation.8*/9#include <linux/linkage.h>10#include <asm/assembler.h>1112.text1314/*15* Function: __u32 csum_partial(const char *src, int len, __u32 sum)16* Params : r0 = buffer, r1 = len, r2 = checksum17* Returns : r0 = new checksum18*/1920buf .req r021len .req r122sum .req r223td0 .req r324td1 .req r4 @ save before use25td2 .req r5 @ save before use26td3 .req lr2728.Lzero: mov r0, sum29add sp, sp, #430ldr pc, [sp], #43132/*33* Handle 0 to 7 bytes, with any alignment of source and34* destination pointers. Note that when we get here, C = 035*/36.Lless8: teq len, #0 @ check for zero count37beq .Lzero3839/* we must have at least one byte. */40tst buf, #1 @ odd address?41movne sum, sum, ror #842ldrneb td0, [buf], #143subne len, len, #144adcnes sum, sum, td0, put_byte_14546.Lless4: tst len, #647beq .Lless8_byte4849/* we are now half-word aligned */5051.Lless8_wordlp:52#if __LINUX_ARM_ARCH__ >= 453ldrh td0, [buf], #254sub len, len, #255#else56ldrb td0, [buf], #157ldrb td3, [buf], #158sub len, len, #259#ifndef __ARMEB__60orr td0, td0, td3, lsl #861#else62orr td0, td3, td0, lsl #863#endif64#endif65adcs sum, sum, td066tst len, #667bne .Lless8_wordlp6869.Lless8_byte: tst len, #1 @ odd number of bytes70ldrneb td0, [buf], #1 @ include last byte71adcnes sum, sum, td0, put_byte_0 @ update checksum7273.Ldone: adc r0, sum, #0 @ collect up the last carry74ldr td0, [sp], #475tst td0, #1 @ check buffer alignment76movne r0, r0, ror #8 @ rotate checksum by 8 bits77ldr pc, [sp], #4 @ return7879.Lnot_aligned: tst buf, #1 @ odd address80ldrneb td0, [buf], #1 @ make even81subne len, len, #182adcnes sum, sum, td0, put_byte_1 @ update checksum8384tst buf, #2 @ 32-bit aligned?85#if __LINUX_ARM_ARCH__ >= 486ldrneh td0, [buf], #2 @ make 32-bit aligned87subne len, len, #288#else89ldrneb td0, [buf], #190ldrneb ip, [buf], #191subne len, len, #292#ifndef __ARMEB__93orrne td0, td0, ip, lsl #894#else95orrne td0, ip, td0, lsl #896#endif97#endif98adcnes sum, sum, td0 @ update checksum99mov pc, lr100101ENTRY(csum_partial)102stmfd sp!, {buf, lr}103cmp len, #8 @ Ensure that we have at least104blo .Lless8 @ 8 bytes to copy.105106tst buf, #1107movne sum, sum, ror #8108109adds sum, sum, #0 @ C = 0110tst buf, #3 @ Test destination alignment111blne .Lnot_aligned @ align destination, return here1121131: bics ip, len, #31114beq 3f115116stmfd sp!, {r4 - r5}1172: ldmia buf!, {td0, td1, td2, td3}118adcs sum, sum, td0119adcs sum, sum, td1120adcs sum, sum, td2121adcs sum, sum, td3122ldmia buf!, {td0, td1, td2, td3}123adcs sum, sum, td0124adcs sum, sum, td1125adcs sum, sum, td2126adcs sum, sum, td3127sub ip, ip, #32128teq ip, #0129bne 2b130ldmfd sp!, {r4 - r5}1311323: tst len, #0x1c @ should not change C133beq .Lless41341354: ldr td0, [buf], #4136sub len, len, #4137adcs sum, sum, td0138tst len, #0x1c139bne 4b140b .Lless4141ENDPROC(csum_partial)142143144