xref: /openbmc/linux/arch/powerpc/lib/string.S (revision 64c70b1c)
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#ifdef CONFIG_PPC64
17	.align	3
18#define EXTBL	.llong
19#else
20	.align	2
21#define EXTBL	.long
22#endif
23	.text
24
25_GLOBAL(strcpy)
26	addi	r5,r3,-1
27	addi	r4,r4,-1
281:	lbzu	r0,1(r4)
29	cmpwi	0,r0,0
30	stbu	r0,1(r5)
31	bne	1b
32	blr
33
34/* This clears out any unused part of the destination buffer,
35   just as the libc version does.  -- paulus */
36_GLOBAL(strncpy)
37	cmpwi	0,r5,0
38	beqlr
39	mtctr	r5
40	addi	r6,r3,-1
41	addi	r4,r4,-1
421:	lbzu	r0,1(r4)
43	cmpwi	0,r0,0
44	stbu	r0,1(r6)
45	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
46	bnelr			/* if we didn't hit a null char, we're done */
47	mfctr	r5
48	cmpwi	0,r5,0		/* any space left in destination buffer? */
49	beqlr			/* we know r0 == 0 here */
502:	stbu	r0,1(r6)	/* clear it out if so */
51	bdnz	2b
52	blr
53
54_GLOBAL(strcat)
55	addi	r5,r3,-1
56	addi	r4,r4,-1
571:	lbzu	r0,1(r5)
58	cmpwi	0,r0,0
59	bne	1b
60	addi	r5,r5,-1
611:	lbzu	r0,1(r4)
62	cmpwi	0,r0,0
63	stbu	r0,1(r5)
64	bne	1b
65	blr
66
67_GLOBAL(strcmp)
68	addi	r5,r3,-1
69	addi	r4,r4,-1
701:	lbzu	r3,1(r5)
71	cmpwi	1,r3,0
72	lbzu	r0,1(r4)
73	subf.	r3,r0,r3
74	beqlr	1
75	beq	1b
76	blr
77
78_GLOBAL(strlen)
79	addi	r4,r3,-1
801:	lbzu	r0,1(r4)
81	cmpwi	0,r0,0
82	bne	1b
83	subf	r3,r3,r4
84	blr
85
86_GLOBAL(memcmp)
87	cmpwi	0,r5,0
88	ble-	2f
89	mtctr	r5
90	addi	r6,r3,-1
91	addi	r4,r4,-1
921:	lbzu	r3,1(r6)
93	lbzu	r0,1(r4)
94	subf.	r3,r0,r3
95	bdnzt	2,1b
96	blr
972:	li	r3,0
98	blr
99
100_GLOBAL(memchr)
101	cmpwi	0,r5,0
102	ble-	2f
103	mtctr	r5
104	addi	r3,r3,-1
1051:	lbzu	r0,1(r3)
106	cmpw	0,r0,r4
107	bdnzf	2,1b
108	beqlr
1092:	li	r3,0
110	blr
111
112_GLOBAL(__clear_user)
113	addi	r6,r3,-4
114	li	r3,0
115	li	r5,0
116	cmplwi	0,r4,4
117	blt	7f
118	/* clear a single word */
11911:	stwu	r5,4(r6)
120	beqlr
121	/* clear word sized chunks */
122	andi.	r0,r6,3
123	add	r4,r0,r4
124	subf	r6,r0,r6
125	srwi	r0,r4,2
126	andi.	r4,r4,3
127	mtctr	r0
128	bdz	7f
1291:	stwu	r5,4(r6)
130	bdnz	1b
131	/* clear byte sized chunks */
1327:	cmpwi	0,r4,0
133	beqlr
134	mtctr	r4
135	addi	r6,r6,3
1368:	stbu	r5,1(r6)
137	bdnz	8b
138	blr
13990:	mr	r3,r4
140	blr
14191:	mfctr	r3
142	slwi	r3,r3,2
143	add	r3,r3,r4
144	blr
14592:	mfctr	r3
146	blr
147
148	.section __ex_table,"a"
149	EXTBL	11b,90b
150	EXTBL	1b,91b
151	EXTBL	8b,92b
152	.text
153
154_GLOBAL(__strncpy_from_user)
155	addi	r6,r3,-1
156	addi	r4,r4,-1
157	cmpwi	0,r5,0
158	beq	2f
159	mtctr	r5
1601:	lbzu	r0,1(r4)
161	cmpwi	0,r0,0
162	stbu	r0,1(r6)
163	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
164	beq	3f
1652:	addi	r6,r6,1
1663:	subf	r3,r3,r6
167	blr
16899:	li	r3,-EFAULT
169	blr
170
171	.section __ex_table,"a"
172	EXTBL	1b,99b
173	.text
174
175/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
176_GLOBAL(__strnlen_user)
177	addi	r7,r3,-1
178	subf	r6,r7,r5	/* top+1 - str */
179	cmplw	0,r4,r6
180	bge	0f
181	mr	r6,r4
1820:	mtctr	r6		/* ctr = min(len, top - str) */
1831:	lbzu	r0,1(r7)	/* get next byte */
184	cmpwi	0,r0,0
185	bdnzf	2,1b		/* loop if --ctr != 0 && byte != 0 */
186	addi	r7,r7,1
187	subf	r3,r3,r7	/* number of bytes we have looked at */
188	beqlr			/* return if we found a 0 byte */
189	cmpw	0,r3,r4		/* did we look at all len bytes? */
190	blt	99f		/* if not, must have hit top */
191	addi	r3,r4,1		/* return len + 1 to indicate no null found */
192	blr
19399:	li	r3,0		/* bad address, return 0 */
194	blr
195
196	.section __ex_table,"a"
197	EXTBL	1b,99b
198