1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * A fast checksum routine using movem 4 * Copyright (c) 1998-2001 Axis Communications AB 5 * 6 * csum_partial(const unsigned char * buff, int len, unsigned int sum) 7 */ 8 9 .globl csum_partial 10csum_partial: 11 12 ;; r10 - src 13 ;; r11 - length 14 ;; r12 - checksum 15 16 ;; check for breakeven length between movem and normal word looping versions 17 ;; we also do _NOT_ want to compute a checksum over more than the 18 ;; actual length when length < 40 19 20 cmpu.w 80,$r11 21 blo _word_loop 22 nop 23 24 ;; need to save the registers we use below in the movem loop 25 ;; this overhead is why we have a check above for breakeven length 26 ;; only r0 - r8 have to be saved, the other ones are clobber-able 27 ;; according to the ABI 28 29 subq 9*4,$sp 30 movem $r8,[$sp] 31 32 ;; do a movem checksum 33 34 subq 10*4,$r11 ; update length for the first loop 35 36_mloop: movem [$r10+],$r9 ; read 10 longwords 37 38 ;; perform dword checksumming on the 10 longwords 39 40 add.d $r0,$r12 41 ax 42 add.d $r1,$r12 43 ax 44 add.d $r2,$r12 45 ax 46 add.d $r3,$r12 47 ax 48 add.d $r4,$r12 49 ax 50 add.d $r5,$r12 51 ax 52 add.d $r6,$r12 53 ax 54 add.d $r7,$r12 55 ax 56 add.d $r8,$r12 57 ax 58 add.d $r9,$r12 59 60 ;; fold the carry into the checksum, to avoid having to loop the carry 61 ;; back into the top 62 63 ax 64 addq 0,$r12 65 66 subq 10*4,$r11 67 bge _mloop 68 nop 69 70 addq 10*4,$r11 ; compensate for last loop underflowing length 71 72 movem [$sp+],$r8 ; restore regs 73 74_word_loop: 75 ;; only fold if there is anything to fold. 76 77 cmpq 0,$r12 78 beq _no_fold 79 80 ;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below. 81 ;; r9 and r13 can be used as temporaries. 82 83 moveq -1,$r9 ; put 0xffff in r9, faster than move.d 0xffff,r9 84 lsrq 16,$r9 85 86 move.d $r12,$r13 87 lsrq 16,$r13 ; r13 = checksum >> 16 88 and.d $r9,$r12 ; checksum = checksum & 0xffff 89 add.d $r13,$r12 ; checksum += r13 90 91_no_fold: 92 cmpq 2,$r11 93 blt _no_words 94 nop 95 96 ;; checksum the rest of the words 97 98 subq 2,$r11 99 100_wloop: subq 2,$r11 101 bge _wloop 102 addu.w [$r10+],$r12 103 104 addq 2,$r11 105 106_no_words: 107 ;; see if we have one odd byte more 108 cmpq 1,$r11 109 beq _do_byte 110 nop 111 ret 112 move.d $r12, $r10 113 114_do_byte: 115 ;; copy and checksum the last byte 116 addu.b [$r10],$r12 117 ret 118 move.d $r12, $r10 119 120