xref: /openbmc/linux/arch/powerpc/lib/string.S (revision 87c2ce3b)
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 <linux/config.h>
12#include <asm/processor.h>
13#include <asm/errno.h>
14#include <asm/ppc_asm.h>
15
16	.section __ex_table,"a"
17#ifdef CONFIG_PPC64
18	.align	3
19#define EXTBL	.llong
20#else
21	.align	2
22#define EXTBL	.long
23#endif
24	.text
25
26_GLOBAL(strcpy)
27	addi	r5,r3,-1
28	addi	r4,r4,-1
291:	lbzu	r0,1(r4)
30	cmpwi	0,r0,0
31	stbu	r0,1(r5)
32	bne	1b
33	blr
34
35/* This clears out any unused part of the destination buffer,
36   just as the libc version does.  -- paulus */
37_GLOBAL(strncpy)
38	cmpwi	0,r5,0
39	beqlr
40	mtctr	r5
41	addi	r6,r3,-1
42	addi	r4,r4,-1
431:	lbzu	r0,1(r4)
44	cmpwi	0,r0,0
45	stbu	r0,1(r6)
46	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
47	bnelr			/* if we didn't hit a null char, we're done */
48	mfctr	r5
49	cmpwi	0,r5,0		/* any space left in destination buffer? */
50	beqlr			/* we know r0 == 0 here */
512:	stbu	r0,1(r6)	/* clear it out if so */
52	bdnz	2b
53	blr
54
55_GLOBAL(strcat)
56	addi	r5,r3,-1
57	addi	r4,r4,-1
581:	lbzu	r0,1(r5)
59	cmpwi	0,r0,0
60	bne	1b
61	addi	r5,r5,-1
621:	lbzu	r0,1(r4)
63	cmpwi	0,r0,0
64	stbu	r0,1(r5)
65	bne	1b
66	blr
67
68_GLOBAL(strcmp)
69	addi	r5,r3,-1
70	addi	r4,r4,-1
711:	lbzu	r3,1(r5)
72	cmpwi	1,r3,0
73	lbzu	r0,1(r4)
74	subf.	r3,r0,r3
75	beqlr	1
76	beq	1b
77	blr
78
79_GLOBAL(strlen)
80	addi	r4,r3,-1
811:	lbzu	r0,1(r4)
82	cmpwi	0,r0,0
83	bne	1b
84	subf	r3,r3,r4
85	blr
86
87_GLOBAL(memcmp)
88	cmpwi	0,r5,0
89	ble-	2f
90	mtctr	r5
91	addi	r6,r3,-1
92	addi	r4,r4,-1
931:	lbzu	r3,1(r6)
94	lbzu	r0,1(r4)
95	subf.	r3,r0,r3
96	bdnzt	2,1b
97	blr
982:	li	r3,0
99	blr
100
101_GLOBAL(memchr)
102	cmpwi	0,r5,0
103	ble-	2f
104	mtctr	r5
105	addi	r3,r3,-1
1061:	lbzu	r0,1(r3)
107	cmpw	0,r0,r4
108	bdnzf	2,1b
109	beqlr
1102:	li	r3,0
111	blr
112
113_GLOBAL(__clear_user)
114	addi	r6,r3,-4
115	li	r3,0
116	li	r5,0
117	cmplwi	0,r4,4
118	blt	7f
119	/* clear a single word */
12011:	stwu	r5,4(r6)
121	beqlr
122	/* clear word sized chunks */
123	andi.	r0,r6,3
124	add	r4,r0,r4
125	subf	r6,r0,r6
126	srwi	r0,r4,2
127	andi.	r4,r4,3
128	mtctr	r0
129	bdz	7f
1301:	stwu	r5,4(r6)
131	bdnz	1b
132	/* clear byte sized chunks */
1337:	cmpwi	0,r4,0
134	beqlr
135	mtctr	r4
136	addi	r6,r6,3
1378:	stbu	r5,1(r6)
138	bdnz	8b
139	blr
14090:	mr	r3,r4
141	blr
14291:	mfctr	r3
143	slwi	r3,r3,2
144	add	r3,r3,r4
145	blr
14692:	mfctr	r3
147	blr
148
149	.section __ex_table,"a"
150	EXTBL	11b,90b
151	EXTBL	1b,91b
152	EXTBL	8b,92b
153	.text
154
155_GLOBAL(__strncpy_from_user)
156	addi	r6,r3,-1
157	addi	r4,r4,-1
158	cmpwi	0,r5,0
159	beq	2f
160	mtctr	r5
1611:	lbzu	r0,1(r4)
162	cmpwi	0,r0,0
163	stbu	r0,1(r6)
164	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
165	beq	3f
1662:	addi	r6,r6,1
1673:	subf	r3,r3,r6
168	blr
16999:	li	r3,-EFAULT
170	blr
171
172	.section __ex_table,"a"
173	EXTBL	1b,99b
174	.text
175
176/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
177_GLOBAL(__strnlen_user)
178	addi	r7,r3,-1
179	subf	r6,r7,r5	/* top+1 - str */
180	cmplw	0,r4,r6
181	bge	0f
182	mr	r6,r4
1830:	mtctr	r6		/* ctr = min(len, top - str) */
1841:	lbzu	r0,1(r7)	/* get next byte */
185	cmpwi	0,r0,0
186	bdnzf	2,1b		/* loop if --ctr != 0 && byte != 0 */
187	addi	r7,r7,1
188	subf	r3,r3,r7	/* number of bytes we have looked at */
189	beqlr			/* return if we found a 0 byte */
190	cmpw	0,r3,r4		/* did we look at all len bytes? */
191	blt	99f		/* if not, must have hit top */
192	addi	r3,r4,1		/* return len + 1 to indicate no null found */
193	blr
19499:	li	r3,0		/* bad address, return 0 */
195	blr
196
197	.section __ex_table,"a"
198	EXTBL	1b,99b
199