xref: /openbmc/linux/arch/powerpc/lib/string.S (revision fd589a8f)
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/processor.h>
12#include <asm/errno.h>
13#include <asm/ppc_asm.h>
14
15	.section __ex_table,"a"
16	PPC_LONG_ALIGN
17	.text
18
19_GLOBAL(strcpy)
20	addi	r5,r3,-1
21	addi	r4,r4,-1
221:	lbzu	r0,1(r4)
23	cmpwi	0,r0,0
24	stbu	r0,1(r5)
25	bne	1b
26	blr
27
28/* This clears out any unused part of the destination buffer,
29   just as the libc version does.  -- paulus */
30_GLOBAL(strncpy)
31	cmpwi	0,r5,0
32	beqlr
33	mtctr	r5
34	addi	r6,r3,-1
35	addi	r4,r4,-1
361:	lbzu	r0,1(r4)
37	cmpwi	0,r0,0
38	stbu	r0,1(r6)
39	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
40	bnelr			/* if we didn't hit a null char, we're done */
41	mfctr	r5
42	cmpwi	0,r5,0		/* any space left in destination buffer? */
43	beqlr			/* we know r0 == 0 here */
442:	stbu	r0,1(r6)	/* clear it out if so */
45	bdnz	2b
46	blr
47
48_GLOBAL(strcat)
49	addi	r5,r3,-1
50	addi	r4,r4,-1
511:	lbzu	r0,1(r5)
52	cmpwi	0,r0,0
53	bne	1b
54	addi	r5,r5,-1
551:	lbzu	r0,1(r4)
56	cmpwi	0,r0,0
57	stbu	r0,1(r5)
58	bne	1b
59	blr
60
61_GLOBAL(strcmp)
62	addi	r5,r3,-1
63	addi	r4,r4,-1
641:	lbzu	r3,1(r5)
65	cmpwi	1,r3,0
66	lbzu	r0,1(r4)
67	subf.	r3,r0,r3
68	beqlr	1
69	beq	1b
70	blr
71
72_GLOBAL(strncmp)
73	PPC_LCMPI r5,0
74	beqlr
75	mtctr	r5
76	addi	r5,r3,-1
77	addi	r4,r4,-1
781:	lbzu	r3,1(r5)
79	cmpwi	1,r3,0
80	lbzu	r0,1(r4)
81	subf.	r3,r0,r3
82	beqlr	1
83	bdnzt	eq,1b
84	blr
85
86_GLOBAL(strlen)
87	addi	r4,r3,-1
881:	lbzu	r0,1(r4)
89	cmpwi	0,r0,0
90	bne	1b
91	subf	r3,r3,r4
92	blr
93
94_GLOBAL(memcmp)
95	cmpwi	0,r5,0
96	ble-	2f
97	mtctr	r5
98	addi	r6,r3,-1
99	addi	r4,r4,-1
1001:	lbzu	r3,1(r6)
101	lbzu	r0,1(r4)
102	subf.	r3,r0,r3
103	bdnzt	2,1b
104	blr
1052:	li	r3,0
106	blr
107
108_GLOBAL(memchr)
109	cmpwi	0,r5,0
110	ble-	2f
111	mtctr	r5
112	addi	r3,r3,-1
1131:	lbzu	r0,1(r3)
114	cmpw	0,r0,r4
115	bdnzf	2,1b
116	beqlr
1172:	li	r3,0
118	blr
119
120_GLOBAL(__clear_user)
121	addi	r6,r3,-4
122	li	r3,0
123	li	r5,0
124	cmplwi	0,r4,4
125	blt	7f
126	/* clear a single word */
12711:	stwu	r5,4(r6)
128	beqlr
129	/* clear word sized chunks */
130	andi.	r0,r6,3
131	add	r4,r0,r4
132	subf	r6,r0,r6
133	srwi	r0,r4,2
134	andi.	r4,r4,3
135	mtctr	r0
136	bdz	7f
1371:	stwu	r5,4(r6)
138	bdnz	1b
139	/* clear byte sized chunks */
1407:	cmpwi	0,r4,0
141	beqlr
142	mtctr	r4
143	addi	r6,r6,3
1448:	stbu	r5,1(r6)
145	bdnz	8b
146	blr
14790:	mr	r3,r4
148	blr
14991:	mfctr	r3
150	slwi	r3,r3,2
151	add	r3,r3,r4
152	blr
15392:	mfctr	r3
154	blr
155
156	.section __ex_table,"a"
157	PPC_LONG	11b,90b
158	PPC_LONG	1b,91b
159	PPC_LONG	8b,92b
160	.text
161
162_GLOBAL(__strncpy_from_user)
163	addi	r6,r3,-1
164	addi	r4,r4,-1
165	cmpwi	0,r5,0
166	beq	2f
167	mtctr	r5
1681:	lbzu	r0,1(r4)
169	cmpwi	0,r0,0
170	stbu	r0,1(r6)
171	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
172	beq	3f
1732:	addi	r6,r6,1
1743:	subf	r3,r3,r6
175	blr
17699:	li	r3,-EFAULT
177	blr
178
179	.section __ex_table,"a"
180	PPC_LONG	1b,99b
181	.text
182
183/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
184_GLOBAL(__strnlen_user)
185	addi	r7,r3,-1
186	subf	r6,r7,r5	/* top+1 - str */
187	cmplw	0,r4,r6
188	bge	0f
189	mr	r6,r4
1900:	mtctr	r6		/* ctr = min(len, top - str) */
1911:	lbzu	r0,1(r7)	/* get next byte */
192	cmpwi	0,r0,0
193	bdnzf	2,1b		/* loop if --ctr != 0 && byte != 0 */
194	addi	r7,r7,1
195	subf	r3,r3,r7	/* number of bytes we have looked at */
196	beqlr			/* return if we found a 0 byte */
197	cmpw	0,r3,r4		/* did we look at all len bytes? */
198	blt	99f		/* if not, must have hit top */
199	addi	r3,r4,1		/* return len + 1 to indicate no null found */
200	blr
20199:	li	r3,0		/* bad address, return 0 */
202	blr
203
204	.section __ex_table,"a"
205	PPC_LONG	1b,99b
206