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