Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / arch / openrisc / lib / string.S
blob465f04bc7deb1cc7a3413a6e0001a41f16f28641
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  */
18 #include <linux/linkage.h>
19 #include <asm/errno.h>
21         /*
22          * this can be optimized by doing gcc inline assemlby with
23          * proper constraints (no need to save args registers...)
24          *
25          */
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
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
52         l.addi  r11,r11,1               // r11 holds the return value
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
60         .section .fixup, "ax"
61 99:
62                 l.j     1b
63                 l.nop
64         .previous
66         .section __ex_table, "a"
67                 .long 8b, 99b           // read fault
68                 .long 9b, 99b           // write fault
69         .previous
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
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
90         l.addi  r11,r4,1
92         l.lwz   r4,0(r1)
93         l.lwz   r3,4(r1)
94         l.jr    r9
95         l.addi  r1,r1,8
97         .section .fixup, "ax"
98 99:
99                 l.j     1b
100                 l.nop
101         .previous
103         .section __ex_table, "a"
104                 .long 9b, 99b           // write fault
105         .previous
108  * long strncpy_from_user(char *dst, const char *src, long count)
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
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
132         l.lwz   r6,0(r1)
133         l.addi  r5,r5,1
134         l.sub   r11,r11,r5              // r11 holds the return value
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
143         .section .fixup, "ax"
145                 l.movhi r11,hi(-EFAULT)
146                 l.ori   r11,r11,lo(-EFAULT)
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
156         .section __ex_table, "a"
157                 .long 8b, 99b           // read fault
158         .previous
161  * extern int __strnlen_user(const char *str, long len, unsigned long top);
164  * RTRN: - length of a string including NUL termination character
165  *       - on page fault 0
166  */
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
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
187         l.lwz   r6,0(r1)
188         l.lwz   r3,4(r1)
189         l.jr    r9
190         l.addi  r1,r1,8
192         .section .fixup, "ax"
194                 l.addi  r11,r0,0
196                 l.lwz   r6,0(r1)
197                 l.lwz   r3,4(r1)
198                 l.jr    r9
199                 l.addi  r1,r1,8
200         .previous
202         .section __ex_table, "a"
203                 .long 8b, 99b           // read fault
204         .previous