summaryrefslogtreecommitdiff
path: root/arch/avr32/lib/csum_partial_copy_generic.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/lib/csum_partial_copy_generic.S')
-rw-r--r--arch/avr32/lib/csum_partial_copy_generic.S99
1 files changed, 99 insertions, 0 deletions
diff --git a/arch/avr32/lib/csum_partial_copy_generic.S b/arch/avr32/lib/csum_partial_copy_generic.S
new file mode 100644
index 000000000000..a3a0f9b8929c
--- /dev/null
+++ b/arch/avr32/lib/csum_partial_copy_generic.S
@@ -0,0 +1,99 @@
+/*
+ * 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