1/*
2 * String handling functions for PowerPC.
3 *
4 * Copyright (C) 1996 Paul Mackerras.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <asm/ppc_asm.tmpl>
12#include <asm/processor.h>
13#include <asm/errno.h>
14
15_GLOBAL(strcpy)
16	addi	r5,r3,-1
17	addi	r4,r4,-1
181:	lbzu	r0,1(r4)
19	cmpwi	0,r0,0
20	stbu	r0,1(r5)
21	bne	1b
22	blr
23
24_GLOBAL(strncpy)
25	cmpwi	0,r5,0
26	beqlr
27	mtctr	r5
28	addi	r6,r3,-1
29	addi	r4,r4,-1
301:	lbzu	r0,1(r4)
31	cmpwi	0,r0,0
32	stbu	r0,1(r6)
33	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
34	blr
35
36_GLOBAL(strcat)
37	addi	r5,r3,-1
38	addi	r4,r4,-1
391:	lbzu	r0,1(r5)
40	cmpwi	0,r0,0
41	bne	1b
42	addi	r5,r5,-1
431:	lbzu	r0,1(r4)
44	cmpwi	0,r0,0
45	stbu	r0,1(r5)
46	bne	1b
47	blr
48
49_GLOBAL(strcmp)
50	addi	r5,r3,-1
51	addi	r4,r4,-1
521:	lbzu	r3,1(r5)
53	cmpwi	1,r3,0
54	lbzu	r0,1(r4)
55	subf.	r3,r0,r3
56	beqlr	1
57	beq	1b
58	blr
59
60_GLOBAL(strlen)
61	addi	r4,r3,-1
621:	lbzu	r0,1(r4)
63	cmpwi	0,r0,0
64	bne	1b
65	subf	r3,r3,r4
66	blr
67
68_GLOBAL(memset)
69	rlwimi	r4,r4,8,16,23
70	rlwimi	r4,r4,16,0,15
71	addi	r6,r3,-4
72	cmplwi	0,r5,4
73	blt	7f
74	stwu	r4,4(r6)
75	beqlr
76	andi.	r0,r6,3
77	add	r5,r0,r5
78	subf	r6,r0,r6
79	srwi	r0,r5,2
80	mtctr	r0
81	bdz	6f
821:	stwu	r4,4(r6)
83	bdnz	1b
846:	andi.	r5,r5,3
857:	cmpwi	0,r5,0
86	beqlr
87	mtctr	r5
88	addi	r6,r6,3
898:	stbu	r4,1(r6)
90	bdnz	8b
91	blr
92
93_GLOBAL(memmove)
94	cmplw	0,r3,r4
95	bgt	.backwards_memcpy
96	b	.memcpy
97
98_GLOBAL(backwards_memcpy)
99	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
100	add	r6,r3,r5
101	add	r4,r4,r5
102	beq	2f
103	andi.	r0,r6,3
104	mtctr	r7
105	bne	5f
1061:	lwz	r7,-4(r4)
107	lwzu	r8,-8(r4)
108	stw	r7,-4(r6)
109	stwu	r8,-8(r6)
110	bdnz	1b
111	andi.	r5,r5,7
1122:	cmplwi	0,r5,4
113	blt	3f
114	lwzu	r0,-4(r4)
115	subi	r5,r5,4
116	stwu	r0,-4(r6)
1173:	cmpwi	0,r5,0
118	beqlr
119	mtctr	r5
1204:	lbzu	r0,-1(r4)
121	stbu	r0,-1(r6)
122	bdnz	4b
123	blr
1245:	mtctr	r0
1256:	lbzu	r7,-1(r4)
126	stbu	r7,-1(r6)
127	bdnz	6b
128	subf	r5,r0,r5
129	rlwinm.	r7,r5,32-3,3,31
130	beq	2b
131	mtctr	r7
132	b	1b
133
134_GLOBAL(memcmp)
135	cmpwi	0,r5,0
136	ble-	2f
137	mtctr	r5
138	addi	r6,r3,-1
139	addi	r4,r4,-1
1401:	lbzu	r3,1(r6)
141	lbzu	r0,1(r4)
142	subf.	r3,r0,r3
143	bdnzt	2,1b
144	blr
1452:	li	r3,0
146	blr
147
148_GLOBAL(memchr)
149	cmpwi	0,r5,0
150	ble-	2f
151	mtctr	r5
152	addi	r3,r3,-1
1531:	lbzu	r0,1(r3)
154	cmpw	0,r0,r4
155	bdnzf	2,1b
156	beqlr
1572:	li	r3,0
158	blr
159
160_GLOBAL(__clear_user)
161	addi	r6,r3,-4
162	li	r3,0
163	li	r5,0
164	cmplwi	0,r4,4
165	blt	7f
166	/* clear a single word */
16711:	stwu	r5,4(r6)
168	beqlr
169	/* clear word sized chunks */
170	andi.	r0,r6,3
171	add	r4,r0,r4
172	subf	r6,r0,r6
173	srwi	r0,r4,2
174	andi.	r4,r4,3
175	mtctr	r0
176	bdz	7f
1771:	stwu	r5,4(r6)
178	bdnz	1b
179	/* clear byte sized chunks */
1807:	cmpwi	0,r4,0
181	beqlr
182	mtctr	r4
183	addi	r6,r6,3
1848:	stbu	r5,1(r6)
185	bdnz	8b
186	blr
18790:	mr	r3,r4
188	blr
18991:	mfctr	r3
190	slwi	r3,r3,2
191	add	r3,r3,r4
192	blr
19392:	mfctr	r3
194	blr
195
196	.section __ex_table,"a"
197	.align	3
198	.llong	11b,90b
199	.llong	1b,91b
200	.llong	8b,92b
201	.text
202
203_GLOBAL(__strncpy_from_user)
204	addi	r6,r3,-1
205	addi	r4,r4,-1
206	cmpwi	0,r5,0
207	beq	2f
208	mtctr	r5
2091:	lbzu	r0,1(r4)
210	cmpwi	0,r0,0
211	stbu	r0,1(r6)
212	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
213	beq	3f
2142:	addi	r6,r6,1
2153:	subf	r3,r3,r6
216	blr
21799:	li	r3,-EFAULT
218	blr
219
220	.section __ex_table,"a"
221	.align	3
222	.llong	1b,99b
223	.text
224
225/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
226_GLOBAL(__strnlen_user)
227	addi	r7,r3,-1
228	subf	r6,r7,r5	/* top+1 - str */
229	cmplw	0,r4,r6
230	bge	0f
231	mr	r6,r4
2320:	mtctr	r6		/* ctr = min(len, top - str) */
2331:	lbzu	r0,1(r7)	/* get next byte */
234	cmpwi	0,r0,0
235	bdnzf	2,1b		/* loop if --ctr != 0 && byte != 0 */
236	addi	r7,r7,1
237	subf	r3,r3,r7	/* number of bytes we have looked at */
238	beqlr			/* return if we found a 0 byte */
239	cmpw	0,r3,r4		/* did we look at all len bytes? */
240	blt	99f		/* if not, must have hit top */
241	addi	r3,r4,1		/* return len + 1 to indicate no null found */
242	blr
24399:	li	r3,0		/* bad address, return 0 */
244	blr
245
246	.section __ex_table,"a"
247	.align	3
248	.llong	1b,99b
249