| /* |
| * Copyright (C) 2004-2006 Atmel Corporation |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| */ |
| #include <asm/errno.h> |
| #include <asm/asm.h> |
| |
| /* |
| * unsigned int csum_partial_copy_generic(const char *src, char *dst, int len |
| * int sum, int *src_err_ptr, |
| * int *dst_err_ptr) |
| * |
| * Copy src to dst while checksumming, otherwise like csum_partial. |
| */ |
| |
| .macro ld_src size, reg, ptr |
| 9999: ld.\size \reg, \ptr |
| .section __ex_table, "a" |
| .long 9999b, fixup_ld_src |
| .previous |
| .endm |
| |
| .macro st_dst size, ptr, reg |
| 9999: st.\size \ptr, \reg |
| .section __ex_table, "a" |
| .long 9999b, fixup_st_dst |
| .previous |
| .endm |
| |
| .text |
| .global csum_partial_copy_generic |
| .type csum_partial_copy_generic,"function" |
| .align 1 |
| csum_partial_copy_generic: |
| pushm r4-r7,lr |
| |
| /* The inner loop */ |
| 1: sub r10, 4 |
| brlt 5f |
| 2: ld_src w, r5, r12++ |
| st_dst w, r11++, r5 |
| add r9, r5 |
| acr r9 |
| sub r10, 4 |
| brge 2b |
| |
| /* return if we had a whole number of words */ |
| 5: sub r10, -4 |
| brne 7f |
| |
| 6: mov r12, r9 |
| popm r4-r7,pc |
| |
| /* handle additional bytes at the tail */ |
| 7: mov r5, 0 |
| mov r4, 32 |
| 8: ld_src ub, r6, r12++ |
| st_dst b, r11++, r6 |
| lsl r5, 8 |
| sub r4, 8 |
| bfins r5, r6, 0, 8 |
| sub r10, 1 |
| brne 8b |
| |
| lsl r5, r5, r4 |
| add r9, r5 |
| acr r9 |
| rjmp 6b |
| |
| /* Exception handler */ |
| .section .fixup,"ax" |
| .align 1 |
| fixup_ld_src: |
| mov r9, -EFAULT |
| cp.w r8, 0 |
| breq 1f |
| st.w r8[0], r9 |
| |
| 1: /* |
| * TODO: zero the complete destination - computing the rest |
| * is too much work |
| */ |
| |
| mov r9, 0 |
| rjmp 6b |
| |
| fixup_st_dst: |
| mov r9, -EFAULT |
| lddsp r8, sp[20] |
| cp.w r8, 0 |
| breq 1f |
| st.w r8[0], r9 |
| 1: mov r9, 0 |
| rjmp 6b |
| |
| .previous |