1/*-
2 * Copyright (c) 2018 Instituto de Pesquisas Eldorado
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of its contributors may
14 *    be used to endorse or promote products derived from this software
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29
30#include <machine/asm.h>
31#if 0
32	RCSID("$NetBSD: strcpy.S,v 1.0 2018/05/08 13:00:49 lbianc Exp $")
33#endif
34
35ENTRY(__strcpy_arch_2_05)
36	mr	%r8, %r3
37
38/*
39 * Aligning the reading address, even if it is already aligned to avoid
40 * performance degradation with strings with 8 bytes or less.
41 */
42.Lalignment:
43	lbz	%r0,0(%r4)
44	cmpdi	cr7,%r0,0
45	stb	%r0,0(%r8)
46	beq	cr7,.Lexit
47	addi	%r4,%r4,1
48	addi	%r8,%r8,1
49	andi.	%r0,%r4,0x7
50	bne	.Lalignment
51
52/* Copy by double word with aligned address. */
53.Lcopy_dw:
54	ld	%r0,0(%r4)
55	xor	%r6,%r6,%r6
56	cmpb	%r5,%r0,%r6
57	cmpdi	cr7,%r5,0
58	bne	cr7,.Lcheck_zero
59	/* Backward r8 to use stdu instruction in Lcopy_dw_loop */
60	addi	%r8,%r8,-8
61.Lcopy_dw_loop:
62	stdu	%r0,8(%r8)
63	ldu	%r0,8(%r4)
64	cmpb	%r5,%r0,%r6
65	cmpdi	cr7,%r5,0
66	beq	cr7,.Lcopy_dw_loop
67
68	addi	%r8,%r8,8   /* Forward r8 to use std instruction. */
69#if defined(__BIG_ENDIAN__)
70/* Find where the zero is located. */
71.Lcheck_zero:
72	rldicr.	%r5,%r0,0,7
73	beq	.Lfound_on_byte_0
74	rldicr.	%r7,%r0,8,7
75	beq	.Lfound_on_byte_1
76	rldicr.	%r7,%r0,16,7
77	beq	.Lfound_on_byte_2
78	rldicr.	%r7,%r0,24,7
79	beq	.Lfound_on_byte_3
80	andis.	%r7,%r0,0xff00
81	beq	.Lfound_on_byte_4
82	andis.	%r7,%r0,0xff
83	beq	.Lfound_on_byte_5
84	andi.	%r7,%r0,0xff00
85	beq	.Lfound_on_byte_6
86
87/* Copy the last string bytes according to the string end position. */
88.Lfound_on_byte_7:
89	std	%r0,0(%r8)
90	b	.Lexit
91
92.Lfound_on_byte_6:
93	srdi	%r6,%r0,32
94	stw	%r6,0(%r8)
95	srdi	%r6,%r0,16
96	sth	%r6,4(%r8)
97	srdi	%r6,%r0,8
98	stb	%r6,6(%r8)
99	b	.Lexit
100
101.Lfound_on_byte_5:
102	srdi	%r6,%r0,32
103	stw	%r6,0(%r8)
104	srdi	%r6,%r0,16
105	sth	%r6,4(%r8)
106	b	.Lexit
107
108.Lfound_on_byte_4:
109	srdi	%r6,%r0,32
110	stw	%r6,0(%r8)
111	srdi	%r6,%r0,24
112	stb	%r6,4(%r8)
113	b	.Lexit
114
115.Lfound_on_byte_3:
116	srdi	%r6,%r0,32
117	stw	%r6,0(%r8)
118	b	.Lexit
119
120.Lfound_on_byte_2:
121	srdi	%r6,%r0,48
122	sth	%r6,0(%r8)
123	srdi	%r6,%r0,40
124	stb	%r6,2(%r8)
125	b	.Lexit
126
127.Lfound_on_byte_1:
128	srdi	%r6,%r0,48
129	sth	%r6,0(%r8)
130	b	.Lexit
131
132.Lfound_on_byte_0:
133	srdi	%r6,%r0,56
134	stb	%r6,0(%r8)
135#elif defined(__LITTLE_ENDIAN__)
136/* Find where the zero is located. */
137.Lcheck_zero:
138	andi.	%r7,%r0,0xff
139	beq	.Lfound_on_byte_0
140	andi.	%r7,%r0,0xff00
141	beq	.Lfound_on_byte_1
142	andis.	%r7,%r0,0xff
143	beq	.Lfound_on_byte_2
144	andis.	%r7,%r0,0xff00
145	beq	.Lfound_on_byte_3
146	rldicr.	%r7,%r0,24,7
147	beq	.Lfound_on_byte_4
148	rldicr.	%r7,%r0,16,7
149	beq	.Lfound_on_byte_5
150	rldicr.	%r7,%r0,8,7
151	beq	.Lfound_on_byte_6
152
153/* Copy the last string bytes according to the string end position. */
154.Lfound_on_byte_7:
155	std	%r0,0(%r8)
156	b	.Lexit
157
158.Lfound_on_byte_6:
159	stw	%r0,0(%r8)
160	srdi	%r6,%r0,32
161	sth	%r6,4(%r8)
162	srdi	%r6,%r0,48
163	stb	%r6,6(%r8)
164	b	.Lexit
165
166.Lfound_on_byte_5:
167	stw	%r0,0(%r8)
168	srdi	%r6,%r0,32
169	sth	%r6,4(%r8)
170	b	.Lexit
171
172.Lfound_on_byte_4:
173	stw	%r0,0(%r8)
174	srdi	%r6,%r0,32
175	stb	%r6,4(%r8)
176	b	.Lexit
177
178.Lfound_on_byte_3:
179	stw	%r0,0(%r8)
180	b	.Lexit
181
182.Lfound_on_byte_2:
183	sth	%r0,0(%r8)
184	srdi	%r6,%r0,16
185	stb	%r6,2(%r8)
186	b	.Lexit
187
188.Lfound_on_byte_1:
189	sth	%r0,0(%r8)
190	b	.Lexit
191
192.Lfound_on_byte_0:
193	stb	%r0,0(%r8)
194#else
195#error "Unable to determine Endianness"
196#endif
197.Lexit:
198	blr
199
200END(__strcpy_arch_2_05)
201
202	.section .note.GNU-stack,"",%progbits
203