xref: /minix3/common/lib/libc/arch/aarch64/string/memcpy.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/* $NetBSD: memcpy.S,v 1.1 2014/08/10 05:47:35 matt Exp $ */
2*0a6a1f1dSLionel Sambuc
3*0a6a1f1dSLionel Sambuc/*-
4*0a6a1f1dSLionel Sambuc * Copyright (c) 2014 The NetBSD Foundation, Inc.
5*0a6a1f1dSLionel Sambuc * All rights reserved.
6*0a6a1f1dSLionel Sambuc *
7*0a6a1f1dSLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
8*0a6a1f1dSLionel Sambuc * by Matt Thomas of 3am Software Foundry.
9*0a6a1f1dSLionel Sambuc *
10*0a6a1f1dSLionel Sambuc * Redistribution and use in source and binary forms, with or without
11*0a6a1f1dSLionel Sambuc * modification, are permitted provided that the following conditions
12*0a6a1f1dSLionel Sambuc * are met:
13*0a6a1f1dSLionel Sambuc * 1. Redistributions of source code must retain the above copyright
14*0a6a1f1dSLionel Sambuc *    notice, this list of conditions and the following disclaimer.
15*0a6a1f1dSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16*0a6a1f1dSLionel Sambuc *    notice, this list of conditions and the following disclaimer in the
17*0a6a1f1dSLionel Sambuc *    documentation and/or other materials provided with the distribution.
18*0a6a1f1dSLionel Sambuc *
19*0a6a1f1dSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*0a6a1f1dSLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*0a6a1f1dSLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*0a6a1f1dSLionel Sambuc * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*0a6a1f1dSLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*0a6a1f1dSLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*0a6a1f1dSLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*0a6a1f1dSLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*0a6a1f1dSLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*0a6a1f1dSLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*0a6a1f1dSLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
30*0a6a1f1dSLionel Sambuc */
31*0a6a1f1dSLionel Sambuc
32*0a6a1f1dSLionel Sambuc#include <machine/asm.h>
33*0a6a1f1dSLionel Sambuc
34*0a6a1f1dSLionel SambucRCSID("$NetBSD: memcpy.S,v 1.1 2014/08/10 05:47:35 matt Exp $")
35*0a6a1f1dSLionel Sambuc
36*0a6a1f1dSLionel Sambuc/* LINTSTUB: void *memcpy(void * restrict, const void * restrict, size_t); */
37*0a6a1f1dSLionel Sambuc
38*0a6a1f1dSLionel SambucENTRY(memcpy)
39*0a6a1f1dSLionel Sambuc	mov	x10, x0
40*0a6a1f1dSLionel Sambuc	mov	x11, x1
41*0a6a1f1dSLionel Sambuc	cbz	x2, .Lmemcpy_ret
42*0a6a1f1dSLionel Sambuc
43*0a6a1f1dSLionel Sambuc	cmp	x2, #7
44*0a6a1f1dSLionel Sambuc	b.ls	.Lmemcpy_last_dword
45*0a6a1f1dSLionel Sambuc
46*0a6a1f1dSLionel Sambuc	ands	x3, x10, #7
47*0a6a1f1dSLionel Sambuc	b.eq	.Lmemcpy_dword_aligned
48*0a6a1f1dSLionel Sambuc
49*0a6a1f1dSLionel Sambuc/*
50*0a6a1f1dSLionel Sambuc * The dst address doesn't have dword alignment.  The src address may or may
51*0a6a1f1dSLionel Sambuc * not have the same alignment.  Make dst dword aligned.  Hope src will be
52*0a6a1f1dSLionel Sambuc * dword aligned but if it isn't, take advantage of unaligned access.
53*0a6a1f1dSLionel Sambuc */
54*0a6a1f1dSLionel Sambuc	add	x2, x2, x3		/* add unalignment to length */
55*0a6a1f1dSLionel Sambuc	sub	x2, x2, #8		/* now subtract a dword */
56*0a6a1f1dSLionel Sambuc
57*0a6a1f1dSLionel Sambuc	tbz	x10, #0, .Lmemcpy_hword_aligned
58*0a6a1f1dSLionel Sambuc	ldrb	w4, [x11], #1
59*0a6a1f1dSLionel Sambuc	strb	w4, [x10], #1
60*0a6a1f1dSLionel Sambuc.Lmemcpy_hword_aligned:
61*0a6a1f1dSLionel Sambuc	tbz	x10, #1, .Lmemcpy_word_aligned
62*0a6a1f1dSLionel Sambuc	ldrh	w4, [x11], #2
63*0a6a1f1dSLionel Sambuc	strh	w4, [x10], #2
64*0a6a1f1dSLionel Sambuc.Lmemcpy_word_aligned:
65*0a6a1f1dSLionel Sambuc	tbz	x10, #2, .Lmemcpy_dword_aligned
66*0a6a1f1dSLionel Sambuc	ldr	w4, [x11], #4
67*0a6a1f1dSLionel Sambuc	str	w4, [x10], #4
68*0a6a1f1dSLionel Sambuc.Lmemcpy_dword_aligned:
69*0a6a1f1dSLionel Sambuc	/*
70*0a6a1f1dSLionel Sambuc	 * destination is now dword aligned.
71*0a6a1f1dSLionel Sambuc	 */
72*0a6a1f1dSLionel Sambuc	subs	x2, x2, #32
73*0a6a1f1dSLionel Sambuc	b.mi	.Lmemcpy_last_oword
74*0a6a1f1dSLionel Sambuc
75*0a6a1f1dSLionel Sambuc.Lmemcpy_oword_loop:
76*0a6a1f1dSLionel Sambuc	ldp	x4, x5, [x11], #16
77*0a6a1f1dSLionel Sambuc	ldp	x6, x7, [x11], #16
78*0a6a1f1dSLionel Sambuc	stp	x4, x5, [x10], #16
79*0a6a1f1dSLionel Sambuc	stp	x6, x7, [x10], #16
80*0a6a1f1dSLionel Sambuc	cbz	x2, .Lmemcpy_ret
81*0a6a1f1dSLionel Sambuc	subs	x2, x2, #32
82*0a6a1f1dSLionel Sambuc	b.pl	.Lmemcpy_oword_loop
83*0a6a1f1dSLionel Sambuc
84*0a6a1f1dSLionel Sambuc.Lmemcpy_last_oword:
85*0a6a1f1dSLionel Sambuc	/*
86*0a6a1f1dSLionel Sambuc	 * We have 31 bytes or less to copy.  First see if we can write a qword
87*0a6a1f1dSLionel Sambuc	 */
88*0a6a1f1dSLionel Sambuc	tbz	x2, #4, .Lmemcpy_last_qword
89*0a6a1f1dSLionel Sambuc	ldp	x4, x5, [x11], #16		/* read word */
90*0a6a1f1dSLionel Sambuc	stp	x4, x5, [x10], #16		/* write word */
91*0a6a1f1dSLionel Sambuc
92*0a6a1f1dSLionel Sambuc.Lmemcpy_last_qword:
93*0a6a1f1dSLionel Sambuc	/*
94*0a6a1f1dSLionel Sambuc	 * We have 15 bytes or less to copy.  First see if we can write a dword
95*0a6a1f1dSLionel Sambuc	 */
96*0a6a1f1dSLionel Sambuc	tbz	x2, #3, .Lmemcpy_last_dword
97*0a6a1f1dSLionel Sambuc	ldr	x4, [x11], #8		/* read word */
98*0a6a1f1dSLionel Sambuc	str	x4, [x10], #8		/* write word */
99*0a6a1f1dSLionel Sambuc
100*0a6a1f1dSLionel Sambuc.Lmemcpy_last_dword:
101*0a6a1f1dSLionel Sambuc	/*
102*0a6a1f1dSLionel Sambuc	 * We have 7 bytes or less to copy.  First see if we can write a word
103*0a6a1f1dSLionel Sambuc	 */
104*0a6a1f1dSLionel Sambuc	tbz	x2, #2, .Lmemcpy_last_word
105*0a6a1f1dSLionel Sambuc	ldr	w4, [x11], #4		/* read word */
106*0a6a1f1dSLionel Sambuc	str	w4, [x10], #4		/* write word */
107*0a6a1f1dSLionel Sambuc
108*0a6a1f1dSLionel Sambuc.Lmemcpy_last_word:
109*0a6a1f1dSLionel Sambuc	/*
110*0a6a1f1dSLionel Sambuc	 * We have 3 bytes or less to copy.  First see if we can write a hword
111*0a6a1f1dSLionel Sambuc	 */
112*0a6a1f1dSLionel Sambuc	tbz	x2, #1, .Lmemcpy_last_hword
113*0a6a1f1dSLionel Sambuc	ldrh	w4, [x11], #2
114*0a6a1f1dSLionel Sambuc	strh	w4, [x10], #2
115*0a6a1f1dSLionel Sambuc
116*0a6a1f1dSLionel Sambuc.Lmemcpy_last_hword:
117*0a6a1f1dSLionel Sambuc	/*
118*0a6a1f1dSLionel Sambuc	 * We have 1 or none bytes to copy.
119*0a6a1f1dSLionel Sambuc	 */
120*0a6a1f1dSLionel Sambuc	tbz	x2, #0, .Lmemcpy_ret
121*0a6a1f1dSLionel Sambuc	ldrb	w4, [x11]
122*0a6a1f1dSLionel Sambuc	strb	w4, [x10]
123*0a6a1f1dSLionel Sambuc
124*0a6a1f1dSLionel Sambuc.Lmemcpy_ret:
125*0a6a1f1dSLionel Sambuc	ret
126*0a6a1f1dSLionel SambucEND(memcpy)
127