xref: /freebsd/lib/libc/powerpc64/string/memcpy.S (revision 2f513db72b034fd5ef7f080b11be5c711c15186a)
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#ifndef FN_NAME
34#define FN_NAME				__memcpy
35WEAK_REFERENCE(__memcpy, memcpy);
36#define BLOCK_BITS			4
37#endif
38
39#define BLOCK_BYTES			(1 << BLOCK_BITS)
40#define BLOCK_MASK			(BLOCK_BYTES - 1)
41
42/*
43 * r3: dst
44 * r4: src
45 * r5: len
46 */
47ENTRY(FN_NAME)
48	cmpdi	%r5, 0			/* len == 0? nothing to do */
49	beqlr-
50
51	mr	%r8, %r3		/* save dst */
52
53	/* align src */
54.Lalignment_loop:
55	lbz	%r6, 0(%r4)
56	stb	%r6, 0(%r3)
57	addi	%r3, %r3, 1
58	addi	%r4, %r4, 1
59	addi	%r5, %r5, -1
60	cmpdi	%r5, 0
61	beq	.Lexit
62	andi.	%r0, %r4, BLOCK_MASK
63	bne	.Lalignment_loop
64
65	/* r7 = remaining, non-block, bytes */
66	andi.	%r7, %r5, BLOCK_MASK
67
68	/* Check if there are blocks of BLOCK_BYTES to be copied */
69	xor.	%r5, %r5, %r7
70	beq	.Lcopy_remaining_fix_index_byte
71
72#ifdef FN_COPY_LOOP
73FN_COPY_LOOP
74#else
75	/* Setup to copy word with ldu and stdu */
76	ld	%r6, 0(%r4)
77	ld	%r9, 8(%r4)
78	std	%r6, 0(%r3)
79	std	%r9, 8(%r3)
80	addi	%r5, %r5, -BLOCK_BYTES
81	cmpd	%r5, 0
82	beq	.Lcopy_remaining_fix_index_word
83
84	srdi	%r5, %r5, BLOCK_BITS
85	mtctr	%r5
86.Lcopy_word:
87	ldu	%r6, 16(%r4)
88	ld	%r9,  8(%r4)
89	stdu	%r6, 16(%r3)
90	std	%r9,  8(%r3)
91	bdnz	.Lcopy_word
92
93.Lcopy_remaining_fix_index_word:
94	/* Check if there are remaining bytes */
95	cmpd	%r7, 0
96	beq	.Lexit
97	addi	%r3, %r3, BLOCK_MASK
98	addi	%r4, %r4, BLOCK_MASK
99	b	.Lcopy_remaining
100#endif
101
102.Lcopy_remaining_fix_index_byte:
103	addi	%r4, %r4, -1
104	addi	%r3, %r3, -1
105
106	/* Copy remaining bytes */
107.Lcopy_remaining:
108	mtctr	%r7
109.Lcopy_remaining_loop:
110	lbzu	%r6, 1(%r4)
111	stbu	%r6, 1(%r3)
112	bdnz	.Lcopy_remaining_loop
113
114.Lexit:
115	/* Restore dst */
116	mr	%r3, %r8
117	blr
118
119END(FN_NAME)
120
121	.section .note.GNU-stack,"",%progbits
122
123