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__FBSDID("$FreeBSD$");
32
33#if 0
34	RCSID("$NetBSD: strcpy.S,v 1.0 2018/05/08 13:00:49 lbianc Exp $")
35#endif
36
37ENTRY(__strcpy_arch_2_05)
38	mr	%r8, %r3
39
40/*
41 * Aligning the reading address, even if it is already aligned to avoid
42 * performance degradation with strings with 8 bytes or less.
43 */
44.Lalignment:
45	lbz	%r0,0(%r4)
46	cmpdi	cr7,%r0,0
47	stb	%r0,0(%r8)
48	beq	cr7,.Lexit
49	addi	%r4,%r4,1
50	addi	%r8,%r8,1
51	andi.	%r0,%r4,0x7
52	bne	.Lalignment
53
54/* Copy by double word with aligned address. */
55.Lcopy_dw:
56	ld	%r0,0(%r4)
57	xor	%r6,%r6,%r6
58	cmpb	%r5,%r0,%r6
59	cmpdi	cr7,%r5,0
60	bne	cr7,.Lcheck_zero
61	/* Backward r8 to use stdu instruction in Lcopy_dw_loop */
62	addi	%r8,%r8,-8
63.Lcopy_dw_loop:
64	stdu	%r0,8(%r8)
65	ldu	%r0,8(%r4)
66	cmpb	%r5,%r0,%r6
67	cmpdi	cr7,%r5,0
68	beq	cr7,.Lcopy_dw_loop
69
70	addi	%r8,%r8,8   /* Forward r8 to use std instruction. */
71#if defined(__BIG_ENDIAN__)
72/* Find where the zero is located. */
73.Lcheck_zero:
74	rldicr.	%r5,%r0,0,7
75	beq	.Lfound_on_byte_0
76	rldicr.	%r7,%r0,8,7
77	beq	.Lfound_on_byte_1
78	rldicr.	%r7,%r0,16,7
79	beq	.Lfound_on_byte_2
80	rldicr.	%r7,%r0,24,7
81	beq	.Lfound_on_byte_3
82	andis.	%r7,%r0,0xff00
83	beq	.Lfound_on_byte_4
84	andis.	%r7,%r0,0xff
85	beq	.Lfound_on_byte_5
86	andi.	%r7,%r0,0xff00
87	beq	.Lfound_on_byte_6
88
89/* Copy the last string bytes according to the string end position. */
90.Lfound_on_byte_7:
91	std	%r0,0(%r8)
92	b	.Lexit
93
94.Lfound_on_byte_6:
95	srdi	%r6,%r0,32
96	stw	%r6,0(%r8)
97	srdi	%r6,%r0,16
98	sth	%r6,4(%r8)
99	srdi	%r6,%r0,8
100	stb	%r6,6(%r8)
101	b	.Lexit
102
103.Lfound_on_byte_5:
104	srdi	%r6,%r0,32
105	stw	%r6,0(%r8)
106	srdi	%r6,%r0,16
107	sth	%r6,4(%r8)
108	b	.Lexit
109
110.Lfound_on_byte_4:
111	srdi	%r6,%r0,32
112	stw	%r6,0(%r8)
113	srdi	%r6,%r0,24
114	stb	%r6,4(%r8)
115	b	.Lexit
116
117.Lfound_on_byte_3:
118	srdi	%r6,%r0,32
119	stw	%r6,0(%r8)
120	b	.Lexit
121
122.Lfound_on_byte_2:
123	srdi	%r6,%r0,48
124	sth	%r6,0(%r8)
125	srdi	%r6,%r0,40
126	stb	%r6,2(%r8)
127	b	.Lexit
128
129.Lfound_on_byte_1:
130	srdi	%r6,%r0,48
131	sth	%r6,0(%r8)
132	b	.Lexit
133
134.Lfound_on_byte_0:
135	srdi	%r6,%r0,56
136	stb	%r6,0(%r8)
137#elif defined(__LITTLE_ENDIAN__)
138/* Find where the zero is located. */
139.Lcheck_zero:
140	andi.	%r7,%r0,0xff
141	beq	.Lfound_on_byte_0
142	andi.	%r7,%r0,0xff00
143	beq	.Lfound_on_byte_1
144	andis.	%r7,%r0,0xff
145	beq	.Lfound_on_byte_2
146	andis.	%r7,%r0,0xff00
147	beq	.Lfound_on_byte_3
148	rldicr.	%r7,%r0,24,7
149	beq	.Lfound_on_byte_4
150	rldicr.	%r7,%r0,16,7
151	beq	.Lfound_on_byte_5
152	rldicr.	%r7,%r0,8,7
153	beq	.Lfound_on_byte_6
154
155/* Copy the last string bytes according to the string end position. */
156.Lfound_on_byte_7:
157	std	%r0,0(%r8)
158	b	.Lexit
159
160.Lfound_on_byte_6:
161	stw	%r0,0(%r8)
162	srdi	%r6,%r0,32
163	sth	%r6,4(%r8)
164	srdi	%r6,%r0,48
165	stb	%r6,6(%r8)
166	b	.Lexit
167
168.Lfound_on_byte_5:
169	stw	%r0,0(%r8)
170	srdi	%r6,%r0,32
171	sth	%r6,4(%r8)
172	b	.Lexit
173
174.Lfound_on_byte_4:
175	stw	%r0,0(%r8)
176	srdi	%r6,%r0,32
177	stb	%r6,4(%r8)
178	b	.Lexit
179
180.Lfound_on_byte_3:
181	stw	%r0,0(%r8)
182	b	.Lexit
183
184.Lfound_on_byte_2:
185	sth	%r0,0(%r8)
186	srdi	%r6,%r0,16
187	stb	%r6,2(%r8)
188	b	.Lexit
189
190.Lfound_on_byte_1:
191	sth	%r0,0(%r8)
192	b	.Lexit
193
194.Lfound_on_byte_0:
195	stb	%r0,0(%r8)
196#else
197#error "Unable to determine Endianness"
198#endif
199.Lexit:
200	blr
201
202END(__strcpy_arch_2_05)
203
204	.section .note.GNU-stack,"",%progbits
205