Path: blob/master/arch/cris/arch-v10/lib/checksumcopy.S
15126 views
/*1* A fast checksum+copy routine using movem2* Copyright (c) 1998, 2001 Axis Communications AB3*4* Authors: Bjorn Wesen5*6* csum_partial_copy_nocheck(const char *src, char *dst,7* int len, unsigned int sum)8*/910.globl csum_partial_copy_nocheck11csum_partial_copy_nocheck:1213;; r10 - src14;; r11 - dst15;; r12 - length16;; r13 - checksum1718;; check for breakeven length between movem and normal word looping versions19;; we also do _NOT_ want to compute a checksum over more than the20;; actual length when length < 402122cmpu.w 80, $r1223blo _word_loop24nop2526;; need to save the registers we use below in the movem loop27;; this overhead is why we have a check above for breakeven length28;; only r0 - r8 have to be saved, the other ones are clobber-able29;; according to the ABI3031subq 9*4, $sp32movem $r8, [$sp]3334;; do a movem copy and checksum3536subq 10*4, $r12 ; update length for the first loop3738_mloop: movem [$r10+],$r9 ; read 10 longwords391: ;; A failing userspace access will have this as PC.40movem $r9,[$r11+] ; write 10 longwords4142;; perform dword checksumming on the 10 longwords4344add.d $r0,$r1345ax46add.d $r1,$r1347ax48add.d $r2,$r1349ax50add.d $r3,$r1351ax52add.d $r4,$r1353ax54add.d $r5,$r1355ax56add.d $r6,$r1357ax58add.d $r7,$r1359ax60add.d $r8,$r1361ax62add.d $r9,$r136364;; fold the carry into the checksum, to avoid having to loop the carry65;; back into the top6667ax68addq 0,$r136970subq 10*4,$r1271bge _mloop72nop7374addq 10*4,$r12 ; compensate for last loop underflowing length7576movem [$sp+],$r8 ; restore regs7778_word_loop:79;; only fold if there is anything to fold.8081cmpq 0,$r1382beq _no_fold8384;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below85;; r9 can be used as temporary.8687move.d $r13,$r988lsrq 16,$r9 ; r0 = checksum >> 1689and.d 0xffff,$r13 ; checksum = checksum & 0xffff90add.d $r9,$r13 ; checksum += r09192_no_fold:93cmpq 2,$r1294blt _no_words95nop9697;; copy and checksum the rest of the words9899subq 2,$r12100101_wloop: move.w [$r10+],$r91022: ;; A failing userspace access will have this as PC.103addu.w $r9,$r13104subq 2,$r12105bge _wloop106move.w $r9,[$r11+]107108addq 2,$r12109110_no_words:111;; see if we have one odd byte more112cmpq 1,$r12113beq _do_byte114nop115ret116move.d $r13, $r10117118_do_byte:119;; copy and checksum the last byte120move.b [$r10],$r91213: ;; A failing userspace access will have this as PC.122addu.b $r9,$r13123move.b $r9,[$r11]124ret125move.d $r13, $r10126127128