1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * A fast checksum routine using movem 4 * Copyright (c) 1998-2007 Axis Communications AB 5 * 6 * csum_partial(const unsigned char * buff, int len, unsigned int sum) 7 */ 8 9 .globl csum_partial 10 .type csum_partial,@function 11csum_partial: 12 13 ;; r10 - src 14 ;; r11 - length 15 ;; r12 - checksum 16 17 ;; Optimized for large packets 18 subq 10*4, $r11 19 blt _word_loop 20 move.d $r11, $acr 21 22 subq 9*4,$sp 23 clearf c 24 movem $r8,[$sp] 25 26 ;; do a movem checksum 27 28_mloop: movem [$r10+],$r9 ; read 10 longwords 29 ;; Loop count without touching the c flag. 30 addoq -10*4, $acr, $acr 31 ;; perform dword checksumming on the 10 longwords 32 33 addc $r0,$r12 34 addc $r1,$r12 35 addc $r2,$r12 36 addc $r3,$r12 37 addc $r4,$r12 38 addc $r5,$r12 39 addc $r6,$r12 40 addc $r7,$r12 41 addc $r8,$r12 42 addc $r9,$r12 43 44 ;; test $acr without trashing carry. 45 move.d $acr, $acr 46 bpl _mloop 47 ;; r11 <= acr is not really needed in the mloop, just using the dslot 48 ;; to prepare for what is needed after mloop. 49 move.d $acr, $r11 50 51 ;; fold the last carry into r13 52 addc 0, $r12 53 movem [$sp+],$r8 ; restore regs 54 55_word_loop: 56 addq 10*4,$r11 ; compensate for last loop underflowing length 57 58 moveq -1,$r9 ; put 0xffff in r9, faster than move.d 0xffff,r9 59 lsrq 16,$r9 60 61 move.d $r12,$r13 62 lsrq 16,$r13 ; r13 = checksum >> 16 63 and.d $r9,$r12 ; checksum = checksum & 0xffff 64 65_no_fold: 66 subq 2,$r11 67 blt _no_words 68 add.d $r13,$r12 ; checksum += r13 69 70 ;; checksum the rest of the words 71_wloop: subq 2,$r11 72 bge _wloop 73 addu.w [$r10+],$r12 74 75_no_words: 76 addq 2,$r11 77 ;; see if we have one odd byte more 78 bne _do_byte 79 nop 80 ret 81 move.d $r12,$r10 82 83_do_byte: 84 ;; copy and checksum the last byte 85 addu.b [$r10],$r12 86 ret 87 move.d $r12,$r10 88 89 .size csum_partial, .-csum_partial 90