xref: /openbsd/sys/lib/libkern/arch/mips64/memmove.S (revision 4bdff4be)
1/*	$OpenBSD: memmove.S,v 1.6 2022/01/29 05:47:36 visa Exp $	*/
2/*-
3 * Copyright (c) 1991, 1993
4 *      The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Ralph Campbell.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "DEFS.h"
35
36
37/*
38 * memcpy(to, from, len)
39	always copy forward
40 *
41 * memmove(to, from, len), bcopy(from, to, len)
42 *	both handle overlap
43 */
44LEAF(memcpy, 0)
45	.set	noreorder
46	move	v0, a0			# swap from and to
47	move	a0, a1
48	move	a1, v0
49	PTR_ADDU t0, a0, a2		# t0 = end of s1 region
50	sltu	t1, a1, t0
51	sltu	t2, a0, a1
52	j	.Lforward		# do forward copy
53	slt	t2, a2, 12		# check for small copy
54
55ALEAF(memmove)
56	.set	noreorder
57	move	v0, a0			# swap from and to
58	move	a0, a1
59	move	a1, v0
60ALEAF(bcopy)
61	.set	noreorder
62	PTR_ADDU t0, a0, a2		# t0 = end of s1 region
63	sltu	t1, a1, t0
64	sltu	t2, a0, a1
65	and	t1, t1, t2		# t1 = true if from < to < (from+len)
66	beq	t1, zero, .Lforward	# non overlapping, do forward copy
67	slt	t2, a2, 12		# check for small copy
68
69	ble	a2, zero, 2f
70	PTR_ADDU t1, a1, a2		# t1 = end of to region
711:
72	lb	v1, -1(t0)		# copy bytes backwards,
73	PTR_SUBU t0, t0, 1		#   doesnt happen often so do slow way
74	PTR_SUBU t1, t1, 1
75	bne	t0, a0, 1b
76	sb	v1, 0(t1)
772:
78	j	ra
79	nop
80.Lforward:
81#ifdef _STANDALONE
82	bne	t2, zero, .Lsmallcpy	# do a small bcopy
83	xor	v1, a0, a1		# compare low two bits of addresses
84	and	v1, v1, 3
85	PTR_SUBU a3, zero, a1		# compute # bytes to word align address
86	beq	v1, zero, .Laligned	# addresses can be word aligned
87	and	a3, a3, 3
88
89	beq	a3, zero, 1f
90	PTR_SUBU a2, a2, a3		# subtract from remaining count
91	LWHI	v1, 0(a0)		# get next 4 bytes (unaligned)
92	LWLO	v1, 3(a0)
93	PTR_ADDU a0, a0, a3
94	SWHI	v1, 0(a1)		# store 1, 2, or 3 bytes to align a1
95	PTR_ADDU a1, a1, a3
961:
97	and	v1, a2, 3		# compute number of words left
98	PTR_SUBU a3, a2, v1
99	move	a2, v1
100	PTR_ADDU a3, a3, a0		# compute ending address
1012:
102	LWHI	v1, 0(a0)		# copy words a0 unaligned, a1 aligned
103	LWLO	v1, 3(a0)
104	PTR_ADDU a0, a0, 4
105	sw	v1, 0(a1)
106	PTR_ADDU a1, a1, 4
107	bne	a0, a3, 2b
108	nop				# We have to do this mmu-bug.
109	b	.Lsmallcpy
110	nop
111.Laligned:
112	beq	a3, zero, 1f
113	PTR_SUBU a2, a2, a3		# subtract from remaining count
114	LWHI	v1, 0(a0)		# copy 1, 2, or 3 bytes to align
115	PTR_ADDU a0, a0, a3
116	SWHI	v1, 0(a1)
117	PTR_ADDU a1, a1, a3
1181:
119	and	v1, a2, 3		# compute number of whole words left
120	PTR_SUBU a3, a2, v1
121	move	a2, v1
122	PTR_ADDU a3, a3, a0		# compute ending address
1232:
124	lw	v1, 0(a0)		# copy words
125	PTR_ADDU a0, a0, 4
126	sw	v1, 0(a1)
127	bne	a0, a3, 2b
128	PTR_ADDU a1, a1, 4
129#else
130	bne	t2, zero, .Lsmallcpy	# do a small bcopy
131	xor	v1, a0, a1		# compare low three bits of addresses
132	and	v1, v1, 7
133	PTR_SUBU a3, zero, a1		# compute # bytes to dword align address
134	beq	v1, zero, .Laligned	# addresses can be dword aligned
135	and	a3, a3, 7
136
137	beq	a3, zero, 1f
138	PTR_SUBU a2, a2, a3		# subtract from remaining count
139	LDHI	v1, 0(a0)		# get next 8 bytes (unaligned)
140	LDLO	v1, 7(a0)
141	PTR_ADDU a0, a0, a3
142	SDHI	v1, 0(a1)		# store 1-7 bytes to align a1
143	PTR_ADDU a1, a1, a3
1441:
145	and	v1, a2, 7		# compute number of dwords left
146	PTR_SUBU a3, a2, v1
147	beq	a3, zero, .Lsmallcpy
148	move	a2, v1
149	PTR_ADDU a3, a3, a0		# compute ending address
1502:
151	LDHI	v1, 0(a0)		# copy dwords a0 unaligned, a1 aligned
152	LDLO	v1, 7(a0)
153	PTR_ADDU a0, a0, 8
154	sd	v1, 0(a1)
155	PTR_ADDU a1, a1, 8
156	bne	a0, a3, 2b
157	nop				# We have to do this mmu-bug.
158	b	.Lsmallcpy
159	nop
160.Laligned:
161	beq	a3, zero, 1f
162	PTR_SUBU a2, a2, a3		# subtract from remaining count
163	LDHI	v1, 0(a0)		# copy 1-7 bytes to align
164	PTR_ADDU a0, a0, a3
165	SDHI	v1, 0(a1)
166	PTR_ADDU a1, a1, a3
1671:
168	and	v1, a2, 7		# compute number of whole dwords left
169	PTR_SUBU a3, a2, v1
170	beq	a3, zero, .Lsmallcpy
171	move	a2, v1
172	PTR_ADDU a3, a3, a0		# compute ending address
1732:
174	ld	v1, 0(a0)		# copy dwords
175	PTR_ADDU a0, a0, 8
176	sd	v1, 0(a1)
177	bne	a0, a3, 2b
178	PTR_ADDU a1, a1, 8
179#endif
180.Lsmallcpy:
181	ble	a2, zero, 2f
182	PTR_ADDU a3, a2, a0		# compute ending address
1831:
184	lbu	v1, 0(a0)		# copy bytes
185	PTR_ADDU a0, a0, 1
186	sb	v1, 0(a1)
187	bne	a0, a3, 1b
188	PTR_ADDU a1, a1, 1	# MMU BUG ? can not do -1(a1) at 0x80000000!!
1892:
190	j	ra
191	nop
192END(memcpy)
193