diff options
Diffstat (limited to 'arch/avr32/lib')
-rw-r--r-- | arch/avr32/lib/Makefile | 10 | ||||
-rw-r--r-- | arch/avr32/lib/__avr32_asr64.S | 31 | ||||
-rw-r--r-- | arch/avr32/lib/__avr32_lsl64.S | 31 | ||||
-rw-r--r-- | arch/avr32/lib/__avr32_lsr64.S | 31 | ||||
-rw-r--r-- | arch/avr32/lib/clear_user.S | 76 | ||||
-rw-r--r-- | arch/avr32/lib/copy_user.S | 119 | ||||
-rw-r--r-- | arch/avr32/lib/csum_partial.S | 47 | ||||
-rw-r--r-- | arch/avr32/lib/csum_partial_copy_generic.S | 99 | ||||
-rw-r--r-- | arch/avr32/lib/delay.c | 55 | ||||
-rw-r--r-- | arch/avr32/lib/findbit.S | 154 | ||||
-rw-r--r-- | arch/avr32/lib/io-readsl.S | 24 | ||||
-rw-r--r-- | arch/avr32/lib/io-readsw.S | 43 | ||||
-rw-r--r-- | arch/avr32/lib/io-writesl.S | 20 | ||||
-rw-r--r-- | arch/avr32/lib/io-writesw.S | 38 | ||||
-rw-r--r-- | arch/avr32/lib/libgcc.h | 33 | ||||
-rw-r--r-- | arch/avr32/lib/longlong.h | 98 | ||||
-rw-r--r-- | arch/avr32/lib/memcpy.S | 62 | ||||
-rw-r--r-- | arch/avr32/lib/memset.S | 72 | ||||
-rw-r--r-- | arch/avr32/lib/strncpy_from_user.S | 60 | ||||
-rw-r--r-- | arch/avr32/lib/strnlen_user.S | 67 |
20 files changed, 1170 insertions, 0 deletions
diff --git a/arch/avr32/lib/Makefile b/arch/avr32/lib/Makefile new file mode 100644 index 000000000000..09ac43e40522 --- /dev/null +++ b/arch/avr32/lib/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for AVR32-specific library files | ||
3 | # | ||
4 | |||
5 | lib-y := copy_user.o clear_user.o | ||
6 | lib-y += strncpy_from_user.o strnlen_user.o | ||
7 | lib-y += delay.o memset.o memcpy.o findbit.o | ||
8 | lib-y += csum_partial.o csum_partial_copy_generic.o | ||
9 | lib-y += io-readsw.o io-readsl.o io-writesw.o io-writesl.o | ||
10 | lib-y += __avr32_lsl64.o __avr32_lsr64.o __avr32_asr64.o | ||
diff --git a/arch/avr32/lib/__avr32_asr64.S b/arch/avr32/lib/__avr32_asr64.S new file mode 100644 index 000000000000..368b6bca4c76 --- /dev/null +++ b/arch/avr32/lib/__avr32_asr64.S | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * DWtype __avr32_asr64(DWtype u, word_type b) | ||
11 | */ | ||
12 | .text | ||
13 | .global __avr32_asr64 | ||
14 | .type __avr32_asr64,@function | ||
15 | __avr32_asr64: | ||
16 | cp.w r12, 0 | ||
17 | reteq r12 | ||
18 | |||
19 | rsub r9, r12, 32 | ||
20 | brle 1f | ||
21 | |||
22 | lsl r8, r11, r9 | ||
23 | lsr r10, r10, r12 | ||
24 | asr r11, r11, r12 | ||
25 | or r10, r8 | ||
26 | retal r12 | ||
27 | |||
28 | 1: neg r9 | ||
29 | asr r10, r11, r9 | ||
30 | asr r11, 31 | ||
31 | retal r12 | ||
diff --git a/arch/avr32/lib/__avr32_lsl64.S b/arch/avr32/lib/__avr32_lsl64.S new file mode 100644 index 000000000000..f1dbc2b36257 --- /dev/null +++ b/arch/avr32/lib/__avr32_lsl64.S | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * DWtype __avr32_lsl64(DWtype u, word_type b) | ||
11 | */ | ||
12 | .text | ||
13 | .global __avr32_lsl64 | ||
14 | .type __avr32_lsl64,@function | ||
15 | __avr32_lsl64: | ||
16 | cp.w r12, 0 | ||
17 | reteq r12 | ||
18 | |||
19 | rsub r9, r12, 32 | ||
20 | brle 1f | ||
21 | |||
22 | lsr r8, r10, r9 | ||
23 | lsl r10, r10, r12 | ||
24 | lsl r11, r11, r12 | ||
25 | or r11, r8 | ||
26 | retal r12 | ||
27 | |||
28 | 1: neg r9 | ||
29 | lsl r11, r10, r9 | ||
30 | mov r10, 0 | ||
31 | retal r12 | ||
diff --git a/arch/avr32/lib/__avr32_lsr64.S b/arch/avr32/lib/__avr32_lsr64.S new file mode 100644 index 000000000000..e65bb7f0d24c --- /dev/null +++ b/arch/avr32/lib/__avr32_lsr64.S | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * DWtype __avr32_lsr64(DWtype u, word_type b) | ||
11 | */ | ||
12 | .text | ||
13 | .global __avr32_lsr64 | ||
14 | .type __avr32_lsr64,@function | ||
15 | __avr32_lsr64: | ||
16 | cp.w r12, 0 | ||
17 | reteq r12 | ||
18 | |||
19 | rsub r9, r12, 32 | ||
20 | brle 1f | ||
21 | |||
22 | lsl r8, r11, r9 | ||
23 | lsr r11, r11, r12 | ||
24 | lsr r10, r10, r12 | ||
25 | or r10, r8 | ||
26 | retal r12 | ||
27 | |||
28 | 1: neg r9 | ||
29 | lsr r10, r11, r9 | ||
30 | mov r11, 0 | ||
31 | retal r12 | ||
diff --git a/arch/avr32/lib/clear_user.S b/arch/avr32/lib/clear_user.S new file mode 100644 index 000000000000..d8991b6f8eb7 --- /dev/null +++ b/arch/avr32/lib/clear_user.S | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Copyright 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #include <asm/page.h> | ||
9 | #include <asm/thread_info.h> | ||
10 | #include <asm/asm.h> | ||
11 | |||
12 | .text | ||
13 | .align 1 | ||
14 | .global clear_user | ||
15 | .type clear_user, "function" | ||
16 | clear_user: | ||
17 | branch_if_kernel r8, __clear_user | ||
18 | ret_if_privileged r8, r12, r11, r11 | ||
19 | |||
20 | .global __clear_user | ||
21 | .type __clear_user, "function" | ||
22 | __clear_user: | ||
23 | mov r9, r12 | ||
24 | mov r8, 0 | ||
25 | andl r9, 3, COH | ||
26 | brne 5f | ||
27 | |||
28 | 1: sub r11, 4 | ||
29 | brlt 2f | ||
30 | |||
31 | 10: st.w r12++, r8 | ||
32 | sub r11, 4 | ||
33 | brge 10b | ||
34 | |||
35 | 2: sub r11, -4 | ||
36 | reteq 0 | ||
37 | |||
38 | /* Unaligned count or address */ | ||
39 | bld r11, 1 | ||
40 | brcc 12f | ||
41 | 11: st.h r12++, r8 | ||
42 | sub r11, 2 | ||
43 | reteq 0 | ||
44 | 12: st.b r12++, r8 | ||
45 | retal 0 | ||
46 | |||
47 | /* Unaligned address */ | ||
48 | 5: cp.w r11, 4 | ||
49 | brlt 2b | ||
50 | |||
51 | lsl r9, 2 | ||
52 | add pc, pc, r9 | ||
53 | 13: st.b r12++, r8 | ||
54 | sub r11, 1 | ||
55 | 14: st.b r12++, r8 | ||
56 | sub r11, 1 | ||
57 | 15: st.b r12++, r8 | ||
58 | sub r11, 1 | ||
59 | rjmp 1b | ||
60 | |||
61 | .size clear_user, . - clear_user | ||
62 | .size __clear_user, . - __clear_user | ||
63 | |||
64 | .section .fixup, "ax" | ||
65 | .align 1 | ||
66 | 18: sub r11, -4 | ||
67 | 19: retal r11 | ||
68 | |||
69 | .section __ex_table, "a" | ||
70 | .align 2 | ||
71 | .long 10b, 18b | ||
72 | .long 11b, 19b | ||
73 | .long 12b, 19b | ||
74 | .long 13b, 19b | ||
75 | .long 14b, 19b | ||
76 | .long 15b, 19b | ||
diff --git a/arch/avr32/lib/copy_user.S b/arch/avr32/lib/copy_user.S new file mode 100644 index 000000000000..ea59c04b07de --- /dev/null +++ b/arch/avr32/lib/copy_user.S | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * Copy to/from userspace with optional address space checking. | ||
3 | * | ||
4 | * Copyright 2004-2006 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <asm/page.h> | ||
11 | #include <asm/thread_info.h> | ||
12 | #include <asm/asm.h> | ||
13 | |||
14 | /* | ||
15 | * __kernel_size_t | ||
16 | * __copy_user(void *to, const void *from, __kernel_size_t n) | ||
17 | * | ||
18 | * Returns the number of bytes not copied. Might be off by | ||
19 | * max 3 bytes if we get a fault in the main loop. | ||
20 | * | ||
21 | * The address-space checking functions simply fall through to | ||
22 | * the non-checking version. | ||
23 | */ | ||
24 | .text | ||
25 | .align 1 | ||
26 | .global copy_from_user | ||
27 | .type copy_from_user, @function | ||
28 | copy_from_user: | ||
29 | branch_if_kernel r8, __copy_user | ||
30 | ret_if_privileged r8, r11, r10, r10 | ||
31 | rjmp __copy_user | ||
32 | .size copy_from_user, . - copy_from_user | ||
33 | |||
34 | .global copy_to_user | ||
35 | .type copy_to_user, @function | ||
36 | copy_to_user: | ||
37 | branch_if_kernel r8, __copy_user | ||
38 | ret_if_privileged r8, r12, r10, r10 | ||
39 | .size copy_to_user, . - copy_to_user | ||
40 | |||
41 | .global __copy_user | ||
42 | .type __copy_user, @function | ||
43 | __copy_user: | ||
44 | mov r9, r11 | ||
45 | andl r9, 3, COH | ||
46 | brne 6f | ||
47 | |||
48 | /* At this point, from is word-aligned */ | ||
49 | 1: sub r10, 4 | ||
50 | brlt 3f | ||
51 | |||
52 | 2: | ||
53 | 10: ld.w r8, r11++ | ||
54 | 11: st.w r12++, r8 | ||
55 | sub r10, 4 | ||
56 | brge 2b | ||
57 | |||
58 | 3: sub r10, -4 | ||
59 | reteq 0 | ||
60 | |||
61 | /* | ||
62 | * Handle unaligned count. Need to be careful with r10 here so | ||
63 | * that we return the correct value even if we get a fault | ||
64 | */ | ||
65 | 4: | ||
66 | 20: ld.ub r8, r11++ | ||
67 | 21: st.b r12++, r8 | ||
68 | sub r10, 1 | ||
69 | reteq 0 | ||
70 | 22: ld.ub r8, r11++ | ||
71 | 23: st.b r12++, r8 | ||
72 | sub r10, 1 | ||
73 | reteq 0 | ||
74 | 24: ld.ub r8, r11++ | ||
75 | 25: st.b r12++, r8 | ||
76 | retal 0 | ||
77 | |||
78 | /* Handle unaligned from-pointer */ | ||
79 | 6: cp.w r10, 4 | ||
80 | brlt 4b | ||
81 | rsub r9, r9, 4 | ||
82 | |||
83 | 30: ld.ub r8, r11++ | ||
84 | 31: st.b r12++, r8 | ||
85 | sub r10, 1 | ||
86 | sub r9, 1 | ||
87 | breq 1b | ||
88 | 32: ld.ub r8, r11++ | ||
89 | 33: st.b r12++, r8 | ||
90 | sub r10, 1 | ||
91 | sub r9, 1 | ||
92 | breq 1b | ||
93 | 34: ld.ub r8, r11++ | ||
94 | 35: st.b r12++, r8 | ||
95 | sub r10, 1 | ||
96 | rjmp 1b | ||
97 | .size __copy_user, . - __copy_user | ||
98 | |||
99 | .section .fixup,"ax" | ||
100 | .align 1 | ||
101 | 19: sub r10, -4 | ||
102 | 29: retal r10 | ||
103 | |||
104 | .section __ex_table,"a" | ||
105 | .align 2 | ||
106 | .long 10b, 19b | ||
107 | .long 11b, 19b | ||
108 | .long 20b, 29b | ||
109 | .long 21b, 29b | ||
110 | .long 22b, 29b | ||
111 | .long 23b, 29b | ||
112 | .long 24b, 29b | ||
113 | .long 25b, 29b | ||
114 | .long 30b, 29b | ||
115 | .long 31b, 29b | ||
116 | .long 32b, 29b | ||
117 | .long 33b, 29b | ||
118 | .long 34b, 29b | ||
119 | .long 35b, 29b | ||
diff --git a/arch/avr32/lib/csum_partial.S b/arch/avr32/lib/csum_partial.S new file mode 100644 index 000000000000..6a262b528eb7 --- /dev/null +++ b/arch/avr32/lib/csum_partial.S | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * unsigned int csum_partial(const unsigned char *buff, | ||
11 | * int len, unsigned int sum) | ||
12 | */ | ||
13 | .text | ||
14 | .global csum_partial | ||
15 | .type csum_partial,"function" | ||
16 | .align 1 | ||
17 | csum_partial: | ||
18 | /* checksum complete words, aligned or not */ | ||
19 | 3: sub r11, 4 | ||
20 | brlt 5f | ||
21 | 4: ld.w r9, r12++ | ||
22 | add r10, r9 | ||
23 | acr r10 | ||
24 | sub r11, 4 | ||
25 | brge 4b | ||
26 | |||
27 | /* return if we had a whole number of words */ | ||
28 | 5: sub r11, -4 | ||
29 | reteq r10 | ||
30 | |||
31 | /* checksum any remaining bytes at the end */ | ||
32 | mov r9, 0 | ||
33 | mov r8, 0 | ||
34 | cp r11, 2 | ||
35 | brlt 6f | ||
36 | ld.uh r9, r12++ | ||
37 | sub r11, 2 | ||
38 | breq 7f | ||
39 | lsl r9, 16 | ||
40 | 6: ld.ub r8, r12++ | ||
41 | lsl r8, 8 | ||
42 | 7: or r9, r8 | ||
43 | add r10, r9 | ||
44 | acr r10 | ||
45 | |||
46 | retal r10 | ||
47 | .size csum_partial, . - csum_partial | ||
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 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #include <asm/errno.h> | ||
9 | #include <asm/asm.h> | ||
10 | |||
11 | /* | ||
12 | * unsigned int csum_partial_copy_generic(const char *src, char *dst, int len | ||
13 | * int sum, int *src_err_ptr, | ||
14 | * int *dst_err_ptr) | ||
15 | * | ||
16 | * Copy src to dst while checksumming, otherwise like csum_partial. | ||
17 | */ | ||
18 | |||
19 | .macro ld_src size, reg, ptr | ||
20 | 9999: ld.\size \reg, \ptr | ||
21 | .section __ex_table, "a" | ||
22 | .long 9999b, fixup_ld_src | ||
23 | .previous | ||
24 | .endm | ||
25 | |||
26 | .macro st_dst size, ptr, reg | ||
27 | 9999: st.\size \ptr, \reg | ||
28 | .section __ex_table, "a" | ||
29 | .long 9999b, fixup_st_dst | ||
30 | .previous | ||
31 | .endm | ||
32 | |||
33 | .text | ||
34 | .global csum_partial_copy_generic | ||
35 | .type csum_partial_copy_generic,"function" | ||
36 | .align 1 | ||
37 | csum_partial_copy_generic: | ||
38 | pushm r4-r7,lr | ||
39 | |||
40 | /* The inner loop */ | ||
41 | 1: sub r10, 4 | ||
42 | brlt 5f | ||
43 | 2: ld_src w, r5, r12++ | ||
44 | st_dst w, r11++, r5 | ||
45 | add r9, r5 | ||
46 | acr r9 | ||
47 | sub r10, 4 | ||
48 | brge 2b | ||
49 | |||
50 | /* return if we had a whole number of words */ | ||
51 | 5: sub r10, -4 | ||
52 | brne 7f | ||
53 | |||
54 | 6: mov r12, r9 | ||
55 | popm r4-r7,pc | ||
56 | |||
57 | /* handle additional bytes at the tail */ | ||
58 | 7: mov r5, 0 | ||
59 | mov r4, 32 | ||
60 | 8: ld_src ub, r6, r12++ | ||
61 | st_dst b, r11++, r6 | ||
62 | lsl r5, 8 | ||
63 | sub r4, 8 | ||
64 | bfins r5, r6, 0, 8 | ||
65 | sub r10, 1 | ||
66 | brne 8b | ||
67 | |||
68 | lsl r5, r5, r4 | ||
69 | add r9, r5 | ||
70 | acr r9 | ||
71 | rjmp 6b | ||
72 | |||
73 | /* Exception handler */ | ||
74 | .section .fixup,"ax" | ||
75 | .align 1 | ||
76 | fixup_ld_src: | ||
77 | mov r9, -EFAULT | ||
78 | cp.w r8, 0 | ||
79 | breq 1f | ||
80 | st.w r8[0], r9 | ||
81 | |||
82 | 1: /* | ||
83 | * TODO: zero the complete destination - computing the rest | ||
84 | * is too much work | ||
85 | */ | ||
86 | |||
87 | mov r9, 0 | ||
88 | rjmp 6b | ||
89 | |||
90 | fixup_st_dst: | ||
91 | mov r9, -EFAULT | ||
92 | lddsp r8, sp[20] | ||
93 | cp.w r8, 0 | ||
94 | breq 1f | ||
95 | st.w r8[0], r9 | ||
96 | 1: mov r9, 0 | ||
97 | rjmp 6b | ||
98 | |||
99 | .previous | ||
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c new file mode 100644 index 000000000000..462c8307b680 --- /dev/null +++ b/arch/avr32/lib/delay.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Precise Delay Loops for avr32 | ||
3 | * | ||
4 | * Copyright (C) 1993 Linus Torvalds | ||
5 | * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> | ||
6 | * Copyright (C) 2005-2006 Atmel Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/delay.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/types.h> | ||
16 | |||
17 | #include <asm/delay.h> | ||
18 | #include <asm/processor.h> | ||
19 | #include <asm/sysreg.h> | ||
20 | |||
21 | int read_current_timer(unsigned long *timer_value) | ||
22 | { | ||
23 | *timer_value = sysreg_read(COUNT); | ||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | void __delay(unsigned long loops) | ||
28 | { | ||
29 | unsigned bclock, now; | ||
30 | |||
31 | bclock = sysreg_read(COUNT); | ||
32 | do { | ||
33 | now = sysreg_read(COUNT); | ||
34 | } while ((now - bclock) < loops); | ||
35 | } | ||
36 | |||
37 | inline void __const_udelay(unsigned long xloops) | ||
38 | { | ||
39 | unsigned long long loops; | ||
40 | |||
41 | asm("mulu.d %0, %1, %2" | ||
42 | : "=r"(loops) | ||
43 | : "r"(current_cpu_data.loops_per_jiffy * HZ), "r"(xloops)); | ||
44 | __delay(loops >> 32); | ||
45 | } | ||
46 | |||
47 | void __udelay(unsigned long usecs) | ||
48 | { | ||
49 | __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ | ||
50 | } | ||
51 | |||
52 | void __ndelay(unsigned long nsecs) | ||
53 | { | ||
54 | __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ | ||
55 | } | ||
diff --git a/arch/avr32/lib/findbit.S b/arch/avr32/lib/findbit.S new file mode 100644 index 000000000000..2b4856f4bf7c --- /dev/null +++ b/arch/avr32/lib/findbit.S | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #include <linux/linkage.h> | ||
9 | |||
10 | .text | ||
11 | /* | ||
12 | * unsigned long find_first_zero_bit(const unsigned long *addr, | ||
13 | * unsigned long size) | ||
14 | */ | ||
15 | ENTRY(find_first_zero_bit) | ||
16 | cp.w r11, 0 | ||
17 | reteq r11 | ||
18 | mov r9, r11 | ||
19 | 1: ld.w r8, r12[0] | ||
20 | com r8 | ||
21 | brne .L_found | ||
22 | sub r12, -4 | ||
23 | sub r9, 32 | ||
24 | brgt 1b | ||
25 | retal r11 | ||
26 | |||
27 | /* | ||
28 | * unsigned long find_next_zero_bit(const unsigned long *addr, | ||
29 | * unsigned long size, | ||
30 | * unsigned long offset) | ||
31 | */ | ||
32 | ENTRY(find_next_zero_bit) | ||
33 | lsr r8, r10, 5 | ||
34 | sub r9, r11, r10 | ||
35 | retle r11 | ||
36 | |||
37 | lsl r8, 2 | ||
38 | add r12, r8 | ||
39 | andl r10, 31, COH | ||
40 | breq 1f | ||
41 | |||
42 | /* offset is not word-aligned. Handle the first (32 - r10) bits */ | ||
43 | ld.w r8, r12[0] | ||
44 | com r8 | ||
45 | sub r12, -4 | ||
46 | lsr r8, r8, r10 | ||
47 | brne .L_found | ||
48 | |||
49 | /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ | ||
50 | add r9, r10 | ||
51 | sub r9, 32 | ||
52 | retle r11 | ||
53 | |||
54 | /* Main loop. offset must be word-aligned */ | ||
55 | 1: ld.w r8, r12[0] | ||
56 | com r8 | ||
57 | brne .L_found | ||
58 | sub r12, -4 | ||
59 | sub r9, 32 | ||
60 | brgt 1b | ||
61 | retal r11 | ||
62 | |||
63 | /* Common return path for when a bit is actually found. */ | ||
64 | .L_found: | ||
65 | brev r8 | ||
66 | clz r10, r8 | ||
67 | rsub r9, r11 | ||
68 | add r10, r9 | ||
69 | |||
70 | /* XXX: If we don't have to return exactly "size" when the bit | ||
71 | is not found, we may drop this "min" thing */ | ||
72 | min r12, r11, r10 | ||
73 | retal r12 | ||
74 | |||
75 | /* | ||
76 | * unsigned long find_first_bit(const unsigned long *addr, | ||
77 | * unsigned long size) | ||
78 | */ | ||
79 | ENTRY(find_first_bit) | ||
80 | cp.w r11, 0 | ||
81 | reteq r11 | ||
82 | mov r9, r11 | ||
83 | 1: ld.w r8, r12[0] | ||
84 | cp.w r8, 0 | ||
85 | brne .L_found | ||
86 | sub r12, -4 | ||
87 | sub r9, 32 | ||
88 | brgt 1b | ||
89 | retal r11 | ||
90 | |||
91 | /* | ||
92 | * unsigned long find_next_bit(const unsigned long *addr, | ||
93 | * unsigned long size, | ||
94 | * unsigned long offset) | ||
95 | */ | ||
96 | ENTRY(find_next_bit) | ||
97 | lsr r8, r10, 5 | ||
98 | sub r9, r11, r10 | ||
99 | retle r11 | ||
100 | |||
101 | lsl r8, 2 | ||
102 | add r12, r8 | ||
103 | andl r10, 31, COH | ||
104 | breq 1f | ||
105 | |||
106 | /* offset is not word-aligned. Handle the first (32 - r10) bits */ | ||
107 | ld.w r8, r12[0] | ||
108 | sub r12, -4 | ||
109 | lsr r8, r8, r10 | ||
110 | brne .L_found | ||
111 | |||
112 | /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ | ||
113 | add r9, r10 | ||
114 | sub r9, 32 | ||
115 | retle r11 | ||
116 | |||
117 | /* Main loop. offset must be word-aligned */ | ||
118 | 1: ld.w r8, r12[0] | ||
119 | cp.w r8, 0 | ||
120 | brne .L_found | ||
121 | sub r12, -4 | ||
122 | sub r9, 32 | ||
123 | brgt 1b | ||
124 | retal r11 | ||
125 | |||
126 | ENTRY(generic_find_next_zero_le_bit) | ||
127 | lsr r8, r10, 5 | ||
128 | sub r9, r11, r10 | ||
129 | retle r11 | ||
130 | |||
131 | lsl r8, 2 | ||
132 | add r12, r8 | ||
133 | andl r10, 31, COH | ||
134 | breq 1f | ||
135 | |||
136 | /* offset is not word-aligned. Handle the first (32 - r10) bits */ | ||
137 | ldswp.w r8, r12[0] | ||
138 | sub r12, -4 | ||
139 | lsr r8, r8, r10 | ||
140 | brne .L_found | ||
141 | |||
142 | /* r9 = r9 - (32 - r10) = r9 + r10 - 32 */ | ||
143 | add r9, r10 | ||
144 | sub r9, 32 | ||
145 | retle r11 | ||
146 | |||
147 | /* Main loop. offset must be word-aligned */ | ||
148 | 1: ldswp.w r8, r12[0] | ||
149 | cp.w r8, 0 | ||
150 | brne .L_found | ||
151 | sub r12, -4 | ||
152 | sub r9, 32 | ||
153 | brgt 1b | ||
154 | retal r11 | ||
diff --git a/arch/avr32/lib/io-readsl.S b/arch/avr32/lib/io-readsl.S new file mode 100644 index 000000000000..b103511ed6c4 --- /dev/null +++ b/arch/avr32/lib/io-readsl.S | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | .global __raw_readsl | ||
10 | .type __raw_readsl,@function | ||
11 | __raw_readsl: | ||
12 | cp.w r10, 0 | ||
13 | reteq r12 | ||
14 | |||
15 | /* | ||
16 | * If r11 isn't properly aligned, we might get an exception on | ||
17 | * some implementations. But there's not much we can do about it. | ||
18 | */ | ||
19 | 1: ld.w r8, r12[0] | ||
20 | sub r10, 1 | ||
21 | st.w r11++, r8 | ||
22 | brne 1b | ||
23 | |||
24 | retal r12 | ||
diff --git a/arch/avr32/lib/io-readsw.S b/arch/avr32/lib/io-readsw.S new file mode 100644 index 000000000000..456be9909027 --- /dev/null +++ b/arch/avr32/lib/io-readsw.S | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | .Lnot_word_aligned: | ||
10 | /* | ||
11 | * Bad alignment will cause a hardware exception, which is as | ||
12 | * good as anything. No need for us to check for proper alignment. | ||
13 | */ | ||
14 | ld.uh r8, r12[0] | ||
15 | sub r10, 1 | ||
16 | st.h r11++, r8 | ||
17 | |||
18 | /* fall through */ | ||
19 | |||
20 | .global __raw_readsw | ||
21 | .type __raw_readsw,@function | ||
22 | __raw_readsw: | ||
23 | cp.w r10, 0 | ||
24 | reteq r12 | ||
25 | mov r9, 3 | ||
26 | tst r11, r9 | ||
27 | brne .Lnot_word_aligned | ||
28 | |||
29 | sub r10, 2 | ||
30 | brlt 2f | ||
31 | |||
32 | 1: ldins.h r8:t, r12[0] | ||
33 | ldins.h r8:b, r12[0] | ||
34 | st.w r11++, r8 | ||
35 | sub r10, 2 | ||
36 | brge 1b | ||
37 | |||
38 | 2: sub r10, -2 | ||
39 | reteq r12 | ||
40 | |||
41 | ld.uh r8, r12[0] | ||
42 | st.h r11++, r8 | ||
43 | retal r12 | ||
diff --git a/arch/avr32/lib/io-writesl.S b/arch/avr32/lib/io-writesl.S new file mode 100644 index 000000000000..22138b3a16e5 --- /dev/null +++ b/arch/avr32/lib/io-writesl.S | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | .global __raw_writesl | ||
10 | .type __raw_writesl,@function | ||
11 | __raw_writesl: | ||
12 | cp.w r10, 0 | ||
13 | reteq r12 | ||
14 | |||
15 | 1: ld.w r8, r11++ | ||
16 | sub r10, 1 | ||
17 | st.w r12[0], r8 | ||
18 | brne 1b | ||
19 | |||
20 | retal r12 | ||
diff --git a/arch/avr32/lib/io-writesw.S b/arch/avr32/lib/io-writesw.S new file mode 100644 index 000000000000..8c4a53f1c52a --- /dev/null +++ b/arch/avr32/lib/io-writesw.S | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | .Lnot_word_aligned: | ||
10 | ld.uh r8, r11++ | ||
11 | sub r10, 1 | ||
12 | st.h r12[0], r8 | ||
13 | |||
14 | .global __raw_writesw | ||
15 | .type __raw_writesw,@function | ||
16 | __raw_writesw: | ||
17 | cp.w r10, 0 | ||
18 | mov r9, 3 | ||
19 | reteq r12 | ||
20 | tst r11, r9 | ||
21 | brne .Lnot_word_aligned | ||
22 | |||
23 | sub r10, 2 | ||
24 | brlt 2f | ||
25 | |||
26 | 1: ld.w r8, r11++ | ||
27 | bfextu r9, r8, 16, 16 | ||
28 | st.h r12[0], r9 | ||
29 | st.h r12[0], r8 | ||
30 | sub r10, 2 | ||
31 | brge 1b | ||
32 | |||
33 | 2: sub r10, -2 | ||
34 | reteq r12 | ||
35 | |||
36 | ld.uh r8, r11++ | ||
37 | st.h r12[0], r8 | ||
38 | retal r12 | ||
diff --git a/arch/avr32/lib/libgcc.h b/arch/avr32/lib/libgcc.h new file mode 100644 index 000000000000..5a091b5e3618 --- /dev/null +++ b/arch/avr32/lib/libgcc.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* Definitions for various functions 'borrowed' from gcc-3.4.3 */ | ||
2 | |||
3 | #define BITS_PER_UNIT 8 | ||
4 | |||
5 | typedef int QItype __attribute__ ((mode (QI))); | ||
6 | typedef unsigned int UQItype __attribute__ ((mode (QI))); | ||
7 | typedef int HItype __attribute__ ((mode (HI))); | ||
8 | typedef unsigned int UHItype __attribute__ ((mode (HI))); | ||
9 | typedef int SItype __attribute__ ((mode (SI))); | ||
10 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
11 | typedef int DItype __attribute__ ((mode (DI))); | ||
12 | typedef unsigned int UDItype __attribute__ ((mode (DI))); | ||
13 | typedef float SFtype __attribute__ ((mode (SF))); | ||
14 | typedef float DFtype __attribute__ ((mode (DF))); | ||
15 | typedef int word_type __attribute__ ((mode (__word__))); | ||
16 | |||
17 | #define W_TYPE_SIZE (4 * BITS_PER_UNIT) | ||
18 | #define Wtype SItype | ||
19 | #define UWtype USItype | ||
20 | #define HWtype SItype | ||
21 | #define UHWtype USItype | ||
22 | #define DWtype DItype | ||
23 | #define UDWtype UDItype | ||
24 | #define __NW(a,b) __ ## a ## si ## b | ||
25 | #define __NDW(a,b) __ ## a ## di ## b | ||
26 | |||
27 | struct DWstruct {Wtype high, low;}; | ||
28 | |||
29 | typedef union | ||
30 | { | ||
31 | struct DWstruct s; | ||
32 | DWtype ll; | ||
33 | } DWunion; | ||
diff --git a/arch/avr32/lib/longlong.h b/arch/avr32/lib/longlong.h new file mode 100644 index 000000000000..cd5e369ac437 --- /dev/null +++ b/arch/avr32/lib/longlong.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /* longlong.h -- definitions for mixed size 32/64 bit arithmetic. | ||
2 | Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000 | ||
3 | Free Software Foundation, Inc. | ||
4 | |||
5 | This definition file is free software; you can redistribute it | ||
6 | and/or modify it under the terms of the GNU General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2, or (at your option) any later version. | ||
9 | |||
10 | This definition file is distributed in the hope that it will be | ||
11 | useful, but WITHOUT ANY WARRANTY; without even the implied | ||
12 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | See the GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. */ | ||
19 | |||
20 | /* Borrowed from gcc-3.4.3 */ | ||
21 | |||
22 | #define __BITS4 (W_TYPE_SIZE / 4) | ||
23 | #define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) | ||
24 | #define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) | ||
25 | #define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) | ||
26 | |||
27 | #define count_leading_zeros(count, x) ((count) = __builtin_clz(x)) | ||
28 | |||
29 | #define __udiv_qrnnd_c(q, r, n1, n0, d) \ | ||
30 | do { \ | ||
31 | UWtype __d1, __d0, __q1, __q0; \ | ||
32 | UWtype __r1, __r0, __m; \ | ||
33 | __d1 = __ll_highpart (d); \ | ||
34 | __d0 = __ll_lowpart (d); \ | ||
35 | \ | ||
36 | __r1 = (n1) % __d1; \ | ||
37 | __q1 = (n1) / __d1; \ | ||
38 | __m = (UWtype) __q1 * __d0; \ | ||
39 | __r1 = __r1 * __ll_B | __ll_highpart (n0); \ | ||
40 | if (__r1 < __m) \ | ||
41 | { \ | ||
42 | __q1--, __r1 += (d); \ | ||
43 | if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ | ||
44 | if (__r1 < __m) \ | ||
45 | __q1--, __r1 += (d); \ | ||
46 | } \ | ||
47 | __r1 -= __m; \ | ||
48 | \ | ||
49 | __r0 = __r1 % __d1; \ | ||
50 | __q0 = __r1 / __d1; \ | ||
51 | __m = (UWtype) __q0 * __d0; \ | ||
52 | __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ | ||
53 | if (__r0 < __m) \ | ||
54 | { \ | ||
55 | __q0--, __r0 += (d); \ | ||
56 | if (__r0 >= (d)) \ | ||
57 | if (__r0 < __m) \ | ||
58 | __q0--, __r0 += (d); \ | ||
59 | } \ | ||
60 | __r0 -= __m; \ | ||
61 | \ | ||
62 | (q) = (UWtype) __q1 * __ll_B | __q0; \ | ||
63 | (r) = __r0; \ | ||
64 | } while (0) | ||
65 | |||
66 | #define udiv_qrnnd __udiv_qrnnd_c | ||
67 | |||
68 | #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ | ||
69 | do { \ | ||
70 | UWtype __x; \ | ||
71 | __x = (al) - (bl); \ | ||
72 | (sh) = (ah) - (bh) - (__x > (al)); \ | ||
73 | (sl) = __x; \ | ||
74 | } while (0) | ||
75 | |||
76 | #define umul_ppmm(w1, w0, u, v) \ | ||
77 | do { \ | ||
78 | UWtype __x0, __x1, __x2, __x3; \ | ||
79 | UHWtype __ul, __vl, __uh, __vh; \ | ||
80 | \ | ||
81 | __ul = __ll_lowpart (u); \ | ||
82 | __uh = __ll_highpart (u); \ | ||
83 | __vl = __ll_lowpart (v); \ | ||
84 | __vh = __ll_highpart (v); \ | ||
85 | \ | ||
86 | __x0 = (UWtype) __ul * __vl; \ | ||
87 | __x1 = (UWtype) __ul * __vh; \ | ||
88 | __x2 = (UWtype) __uh * __vl; \ | ||
89 | __x3 = (UWtype) __uh * __vh; \ | ||
90 | \ | ||
91 | __x1 += __ll_highpart (__x0);/* this can't give carry */ \ | ||
92 | __x1 += __x2; /* but this indeed can */ \ | ||
93 | if (__x1 < __x2) /* did we get it? */ \ | ||
94 | __x3 += __ll_B; /* yes, add it in the proper pos. */ \ | ||
95 | \ | ||
96 | (w1) = __x3 + __ll_highpart (__x1); \ | ||
97 | (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ | ||
98 | } while (0) | ||
diff --git a/arch/avr32/lib/memcpy.S b/arch/avr32/lib/memcpy.S new file mode 100644 index 000000000000..0abb26142b64 --- /dev/null +++ b/arch/avr32/lib/memcpy.S | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * void *memcpy(void *to, const void *from, unsigned long n) | ||
11 | * | ||
12 | * This implementation does word-aligned loads in the main loop, | ||
13 | * possibly sacrificing alignment of stores. | ||
14 | * | ||
15 | * Hopefully, in most cases, both "to" and "from" will be | ||
16 | * word-aligned to begin with. | ||
17 | */ | ||
18 | .text | ||
19 | .global memcpy | ||
20 | .type memcpy, @function | ||
21 | memcpy: | ||
22 | mov r9, r11 | ||
23 | andl r9, 3, COH | ||
24 | brne 1f | ||
25 | |||
26 | /* At this point, "from" is word-aligned */ | ||
27 | 2: sub r10, 4 | ||
28 | mov r9, r12 | ||
29 | brlt 4f | ||
30 | |||
31 | 3: ld.w r8, r11++ | ||
32 | sub r10, 4 | ||
33 | st.w r12++, r8 | ||
34 | brge 3b | ||
35 | |||
36 | 4: neg r10 | ||
37 | reteq r9 | ||
38 | |||
39 | /* Handle unaligned count */ | ||
40 | lsl r10, 2 | ||
41 | add pc, pc, r10 | ||
42 | ld.ub r8, r11++ | ||
43 | st.b r12++, r8 | ||
44 | ld.ub r8, r11++ | ||
45 | st.b r12++, r8 | ||
46 | ld.ub r8, r11++ | ||
47 | st.b r12++, r8 | ||
48 | retal r9 | ||
49 | |||
50 | /* Handle unaligned "from" pointer */ | ||
51 | 1: sub r10, 4 | ||
52 | brlt 4b | ||
53 | add r10, r9 | ||
54 | lsl r9, 2 | ||
55 | add pc, pc, r9 | ||
56 | ld.ub r8, r11++ | ||
57 | st.b r12++, r8 | ||
58 | ld.ub r8, r11++ | ||
59 | st.b r12++, r8 | ||
60 | ld.ub r8, r11++ | ||
61 | st.b r12++, r8 | ||
62 | rjmp 2b | ||
diff --git a/arch/avr32/lib/memset.S b/arch/avr32/lib/memset.S new file mode 100644 index 000000000000..40da32c0480c --- /dev/null +++ b/arch/avr32/lib/memset.S | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * Based on linux/arch/arm/lib/memset.S | ||
5 | * Copyright (C) 1995-2000 Russell King | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * ASM optimised string functions | ||
12 | */ | ||
13 | #include <asm/asm.h> | ||
14 | |||
15 | /* | ||
16 | * r12: void *b | ||
17 | * r11: int c | ||
18 | * r10: size_t len | ||
19 | * | ||
20 | * Returns b in r12 | ||
21 | */ | ||
22 | .text | ||
23 | .global memset | ||
24 | .type memset, @function | ||
25 | .align 5 | ||
26 | memset: | ||
27 | mov r9, r12 | ||
28 | mov r8, r12 | ||
29 | or r11, r11, r11 << 8 | ||
30 | andl r9, 3, COH | ||
31 | brne 1f | ||
32 | |||
33 | 2: or r11, r11, r11 << 16 | ||
34 | sub r10, 4 | ||
35 | brlt 5f | ||
36 | |||
37 | /* Let's do some real work */ | ||
38 | 4: st.w r8++, r11 | ||
39 | sub r10, 4 | ||
40 | brge 4b | ||
41 | |||
42 | /* | ||
43 | * When we get here, we've got less than 4 bytes to set. r10 | ||
44 | * might be negative. | ||
45 | */ | ||
46 | 5: sub r10, -4 | ||
47 | reteq r12 | ||
48 | |||
49 | /* Fastpath ends here, exactly 32 bytes from memset */ | ||
50 | |||
51 | /* Handle unaligned count or pointer */ | ||
52 | bld r10, 1 | ||
53 | brcc 6f | ||
54 | st.b r8++, r11 | ||
55 | st.b r8++, r11 | ||
56 | bld r10, 0 | ||
57 | retcc r12 | ||
58 | 6: st.b r8++, r11 | ||
59 | retal r12 | ||
60 | |||
61 | /* Handle unaligned pointer */ | ||
62 | 1: sub r10, 4 | ||
63 | brlt 5b | ||
64 | add r10, r9 | ||
65 | lsl r9, 1 | ||
66 | add pc, r9 | ||
67 | st.b r8++, r11 | ||
68 | st.b r8++, r11 | ||
69 | st.b r8++, r11 | ||
70 | rjmp 2b | ||
71 | |||
72 | .size memset, . - memset | ||
diff --git a/arch/avr32/lib/strncpy_from_user.S b/arch/avr32/lib/strncpy_from_user.S new file mode 100644 index 000000000000..72bd50599ec6 --- /dev/null +++ b/arch/avr32/lib/strncpy_from_user.S | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Copy to/from userspace with optional address space checking. | ||
3 | * | ||
4 | * Copyright 2004-2006 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/errno.h> | ||
11 | |||
12 | #include <asm/page.h> | ||
13 | #include <asm/thread_info.h> | ||
14 | #include <asm/asm.h> | ||
15 | |||
16 | /* | ||
17 | * long strncpy_from_user(char *dst, const char *src, long count) | ||
18 | * | ||
19 | * On success, returns the length of the string, not including | ||
20 | * the terminating NUL. | ||
21 | * | ||
22 | * If the string is longer than count, returns count | ||
23 | * | ||
24 | * If userspace access fails, returns -EFAULT | ||
25 | */ | ||
26 | .text | ||
27 | .align 1 | ||
28 | .global strncpy_from_user | ||
29 | .type strncpy_from_user, "function" | ||
30 | strncpy_from_user: | ||
31 | mov r9, -EFAULT | ||
32 | branch_if_kernel r8, __strncpy_from_user | ||
33 | ret_if_privileged r8, r11, r10, r9 | ||
34 | |||
35 | .global __strncpy_from_user | ||
36 | .type __strncpy_from_user, "function" | ||
37 | __strncpy_from_user: | ||
38 | cp.w r10, 0 | ||
39 | reteq 0 | ||
40 | |||
41 | mov r9, r10 | ||
42 | |||
43 | 1: ld.ub r8, r11++ | ||
44 | st.b r12++, r8 | ||
45 | cp.w r8, 0 | ||
46 | breq 2f | ||
47 | sub r9, 1 | ||
48 | brne 1b | ||
49 | |||
50 | 2: sub r10, r9 | ||
51 | retal r10 | ||
52 | |||
53 | .section .fixup, "ax" | ||
54 | .align 1 | ||
55 | 3: mov r12, -EFAULT | ||
56 | retal r12 | ||
57 | |||
58 | .section __ex_table, "a" | ||
59 | .align 2 | ||
60 | .long 1b, 3b | ||
diff --git a/arch/avr32/lib/strnlen_user.S b/arch/avr32/lib/strnlen_user.S new file mode 100644 index 000000000000..65ce11afa66a --- /dev/null +++ b/arch/avr32/lib/strnlen_user.S | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copy to/from userspace with optional address space checking. | ||
3 | * | ||
4 | * Copyright 2004-2006 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <asm/page.h> | ||
11 | #include <asm/thread_info.h> | ||
12 | #include <asm/processor.h> | ||
13 | #include <asm/asm.h> | ||
14 | |||
15 | .text | ||
16 | .align 1 | ||
17 | .global strnlen_user | ||
18 | .type strnlen_user, "function" | ||
19 | strnlen_user: | ||
20 | branch_if_kernel r8, __strnlen_user | ||
21 | sub r8, r11, 1 | ||
22 | add r8, r12 | ||
23 | retcs 0 | ||
24 | brmi adjust_length /* do a closer inspection */ | ||
25 | |||
26 | .global __strnlen_user | ||
27 | .type __strnlen_user, "function" | ||
28 | __strnlen_user: | ||
29 | mov r10, r12 | ||
30 | |||
31 | 10: ld.ub r8, r12++ | ||
32 | cp.w r8, 0 | ||
33 | breq 2f | ||
34 | sub r11, 1 | ||
35 | brne 10b | ||
36 | |||
37 | sub r12, -1 | ||
38 | 2: sub r12, r10 | ||
39 | retal r12 | ||
40 | |||
41 | |||
42 | .type adjust_length, "function" | ||
43 | adjust_length: | ||
44 | cp.w r12, 0 /* addr must always be < TASK_SIZE */ | ||
45 | retmi 0 | ||
46 | |||
47 | pushm lr | ||
48 | lddpc lr, _task_size | ||
49 | sub r11, lr, r12 | ||
50 | mov r9, r11 | ||
51 | rcall __strnlen_user | ||
52 | cp.w r12, r9 | ||
53 | brgt 1f | ||
54 | popm pc | ||
55 | 1: popm pc, r12=0 | ||
56 | |||
57 | .align 2 | ||
58 | _task_size: | ||
59 | .long TASK_SIZE | ||
60 | |||
61 | .section .fixup, "ax" | ||
62 | .align 1 | ||
63 | 19: retal 0 | ||
64 | |||
65 | .section __ex_table, "a" | ||
66 | .align 2 | ||
67 | .long 10b, 19b | ||