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