xref: /openbmc/linux/arch/openrisc/lib/string.S (revision 1ab142d4)
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
432:  	l.sfeq  r11,r0
44	l.bf    1f
45	l.addi  r11,r11,-1
468:    	l.lbz   r6,0(r4)
479:    	l.sb    0(r3),r6
48	l.addi  r3,r3,1
49	l.j     2b
50	l.addi  r4,r4,1
511:
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"
6199:
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
822:	l.sfeq	r4,r0
83	l.bf	1f
84	l.addi	r4,r4,-1
859:	l.sb	0(r3),r0
86	l.j	2b
87	l.addi  r3,r3,1
88
891:
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"
9899:
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
1212:  	l.sfeq  r5,r0
122	l.bf    1f
123	l.addi  r5,r5,-1
1248:    	l.lbz   r6,0(r4)
125	l.sfeq  r6,r0
126	l.bf    1f
1279:    	l.sb    0(r3),r6
128	l.addi  r3,r3,1
129	l.j     2b
130	l.addi  r4,r4,1
1311:
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"
14499:
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
1752:  	l.sfeq  r11,r4
176	l.bf    1f
177	l.addi  r11,r11,1
1788:    	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
1861:
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"
19399:
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
205