Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
[pandora-kernel.git] / arch / openrisc / lib / string.S
1 /*
2  * OpenRISC string.S
3  *
4  * Linux architectural port borrowing liberally from similar works of
5  * others.  All original copyrights apply as per the original source
6  * declaration.
7  *
8  * Modifications for the OpenRISC architecture:
9  * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10  * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11  *
12  *      This program is free software; you can redistribute it and/or
13  *      modify it under the terms of the GNU General Public License
14  *      as published by the Free Software Foundation; either version
15  *      2 of the License, or (at your option) any later version.
16  */
17
18 #include <linux/linkage.h>
19 #include <asm/errno.h>
20
21         /*
22          * this can be optimized by doing gcc inline assemlby with
23          * proper constraints (no need to save args registers...)
24          *
25          */
26
27
28 /*
29  *
30  * int __copy_tofrom_user(void *to, const void *from, unsigned long size);
31  *
32  * NOTE: it returns number of bytes NOT copied !!!
33  *
34  */
35         .global __copy_tofrom_user
36 __copy_tofrom_user:
37         l.addi  r1,r1,-12
38         l.sw    0(r1),r6
39         l.sw    4(r1),r4
40         l.sw    8(r1),r3
41
42         l.addi  r11,r5,0
43 2:      l.sfeq  r11,r0
44         l.bf    1f
45         l.addi  r11,r11,-1
46 8:      l.lbz   r6,0(r4)
47 9:      l.sb    0(r3),r6
48         l.addi  r3,r3,1
49         l.j     2b
50         l.addi  r4,r4,1
51 1:
52         l.addi  r11,r11,1               // r11 holds the return value
53
54         l.lwz   r6,0(r1)
55         l.lwz   r4,4(r1)
56         l.lwz   r3,8(r1)
57         l.jr    r9
58         l.addi  r1,r1,12
59
60         .section .fixup, "ax"
61 99:
62                 l.j     1b
63                 l.nop
64         .previous
65
66         .section __ex_table, "a"
67                 .long 8b, 99b           // read fault
68                 .long 9b, 99b           // write fault
69         .previous
70
71 /*
72  * unsigned long clear_user(void *addr, unsigned long size) ;
73  *
74  * NOTE: it returns number of bytes NOT cleared !!!
75  */
76         .global __clear_user
77 __clear_user:
78         l.addi  r1,r1,-8
79         l.sw    0(r1),r4
80         l.sw    4(r1),r3
81
82 2:      l.sfeq  r4,r0
83         l.bf    1f
84         l.addi  r4,r4,-1
85 9:      l.sb    0(r3),r0
86         l.j     2b
87         l.addi  r3,r3,1
88
89 1:
90         l.addi  r11,r4,1
91
92         l.lwz   r4,0(r1)
93         l.lwz   r3,4(r1)
94         l.jr    r9
95         l.addi  r1,r1,8
96
97         .section .fixup, "ax"
98 99:
99                 l.j     1b
100                 l.nop
101         .previous
102
103         .section __ex_table, "a"
104                 .long 9b, 99b           // write fault
105         .previous
106
107 /*
108  * long strncpy_from_user(char *dst, const char *src, long count)
109  *
110  *
111  */
112         .global __strncpy_from_user
113 __strncpy_from_user:
114         l.addi  r1,r1,-16
115         l.sw    0(r1),r6
116         l.sw    4(r1),r5
117         l.sw    8(r1),r4
118         l.sw    12(r1),r3
119
120         l.addi  r11,r5,0
121 2:      l.sfeq  r5,r0
122         l.bf    1f
123         l.addi  r5,r5,-1
124 8:      l.lbz   r6,0(r4)
125         l.sfeq  r6,r0
126         l.bf    1f
127 9:      l.sb    0(r3),r6
128         l.addi  r3,r3,1
129         l.j     2b
130         l.addi  r4,r4,1
131 1:
132         l.lwz   r6,0(r1)
133         l.addi  r5,r5,1
134         l.sub   r11,r11,r5              // r11 holds the return value
135
136         l.lwz   r6,0(r1)
137         l.lwz   r5,4(r1)
138         l.lwz   r4,8(r1)
139         l.lwz   r3,12(r1)
140         l.jr    r9
141         l.addi  r1,r1,16
142
143         .section .fixup, "ax"
144 99:
145                 l.movhi r11,hi(-EFAULT)
146                 l.ori   r11,r11,lo(-EFAULT)
147
148                 l.lwz   r6,0(r1)
149                 l.lwz   r5,4(r1)
150                 l.lwz   r4,8(r1)
151                 l.lwz   r3,12(r1)
152                 l.jr    r9
153                 l.addi  r1,r1,16
154         .previous
155
156         .section __ex_table, "a"
157                 .long 8b, 99b           // read fault
158         .previous
159
160 /*
161  * extern int __strnlen_user(const char *str, long len, unsigned long top);
162  *
163  *
164  * RTRN: - length of a string including NUL termination character
165  *       - on page fault 0
166  */
167
168         .global __strnlen_user
169 __strnlen_user:
170         l.addi  r1,r1,-8
171         l.sw    0(r1),r6
172         l.sw    4(r1),r3
173
174         l.addi  r11,r0,0
175 2:      l.sfeq  r11,r4
176         l.bf    1f
177         l.addi  r11,r11,1
178 8:      l.lbz   r6,0(r3)
179         l.sfeq  r6,r0
180         l.bf    1f
181         l.sfgeu r3,r5                  // are we over the top ?
182         l.bf    99f
183         l.j     2b
184         l.addi  r3,r3,1
185
186 1:
187         l.lwz   r6,0(r1)
188         l.lwz   r3,4(r1)
189         l.jr    r9
190         l.addi  r1,r1,8
191
192         .section .fixup, "ax"
193 99:
194                 l.addi  r11,r0,0
195
196                 l.lwz   r6,0(r1)
197                 l.lwz   r3,4(r1)
198                 l.jr    r9
199                 l.addi  r1,r1,8
200         .previous
201
202         .section __ex_table, "a"
203                 .long 8b, 99b           // read fault
204         .previous