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