1/*	$NetBSD: memcpy.S,v 1.1 2020/08/16 06:43:43 isaki Exp $	*/
2
3/*
4 * Copyright (C) 2020 Tetsuya Isaki. All rights reserved.
5 * Copyright (C) 2020 Y.Sugahara (moveccr). All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * 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 * Size optimized (but slow) version for primary bootloader.
31 */
32
33#include <machine/asm.h>
34
35|
36| void bcopy(const void *src, void *dst, size_t len);
37|
38ASENTRY_NOPROFILE(bcopy)
39		moveml	%sp@,%d0-%d1/%a0-%a1	| %d0: (return address)
40						| %d1: src
41						| %a0: dst
42						| %a1: count
43		jbra	memmove_common
44|
45| void *memcpy(void *dst, const void *src, size_t count);
46| void *memmove(void *dst, const void *src, size_t count);
47|
48ASENTRY_NOPROFILE(memcpy)
49ASENTRY_NOPROFILE(memmove)
50		moveml	%sp@,%d0-%d1/%a0-%a1	| %d0: (return address)
51						| %d1: dst
52						| %a0: src
53						| %a1: count
54
55		exg	%d1,%a0			| %d1: src
56						| %a0: dst
57						| %a1: count
58memmove_common:
59		exg	%d1,%a1			| %d1: count
60						| %a0: dst
61						| %a1: src
62		moveql	#0,%d0
63						| %d0: offset in forward mode.
64						| %d1: offset in backward mode
65						|  and also loop counter.
66		jbra	2f
67loop:
68		| if src(=%a1) > dst(=%a0), then this is forward copy,
69		|  %d0 is already forward offset.
70		| Otherwise backward copy.  Copy %d1(backward offset) to %d0.
71		cmpl	%a1,%a0
72		jcs	1f
73		movel	%d1,%d0
741:
75		moveb	%a1@(%d0.l),%a0@(%d0.l) | %d0: offset
76		addql	#1,%d0			| increment forward counter,
77						|  though it's pointless in
78						|  backward mode
792:
80		subql	#1,%d1			| if (--count < 0)
81		jcc	loop			|  goto exit
82exit:
83		rts				| %a0 holds return value (=dst)
84
85
86#if defined(SELFTEST)
87#include "iocscall.h"
88		.macro	PRINT	msg
89		leal	\msg,%a1
90		IOCS(__B_PRINT)
91		.endm
92
93		.macro	TEST	name
94		leal	\name,%a2
95		jbsr	test
96		.endm
97
98ASENTRY_NOPROFILE(selftest_memmove)
99		moveml	%d2-%d7/%a2-%a6,%sp@-
100		PRINT	%pc@(msg_testname)
101
102		TEST	test1
103		TEST	test2
104		TEST	test3
105		TEST	test4
106
107		PRINT	%pc@(msg_crlf)
108		moveml	%sp@+,%d2-%d7/%a2-%a6
109		rts
110
111test:
112		movel	%a2@+,buf:W		| initial contents of buffer
113		movew	%a2@+,(buf+4):W		|  (6 bytes total)
114		movel	%a2@+,%sp@-		| push len
115		movel	%a2@+,%sp@-		| push src
116		movel	%a2@+,%a3		| keep dst and
117		movel	%a3,%sp@-		| push dst
118		jbsr	memmove
119		leal	%sp@(12),%sp
120
121		cmpal	%a3,%a0			| compare return value
122		jne	fail
123		movel	%a2@+,%d0		| compare buf[0..3]
124		cmpl	buf:W,%d0
125		jne	fail
126		movew	%a2@+,%d0		| compare buf[4..5]
127		cmpw	(buf+4):W,%d0		| compare buf[4..5]
128		jne	fail
129		PRINT	%pc@(msg_ok)
130		rts
131fail:
132		PRINT	%pc@(msg_fail)
133		rts
134
135test1:
136		| src=buf+1: 1 2 3 4 5 6
137		|               \ \
138		| dst=buf+2: 1 2 2 3 5 6
139		.byte	1, 2, 3, 4, 5, 6	| initial buf
140		.long	2			| len
141		.long	buf+1			| src
142		.long	buf+2			| dst
143		.byte	1, 2, 2, 3, 5, 6	| expected buf
144
145test2:
146		| src=buf+2: 1 2 3 4 5 6
147		|               / /
148		| dst=buf+1: 1 3 4 4 5 6
149		.byte	1, 2, 3, 4, 5, 6	| initial buf
150		.long	2			| len
151		.long	buf+2			| src
152		.long	buf+1			| dst
153		.byte	1, 3, 4, 4, 5, 6	| expected buf
154
155test3:
156		| src == dst
157		.byte	1, 2, 3, 4, 5, 6	| initial buf
158		.long	2			| len
159		.long	buf+1			| src
160		.long	buf+1			| dst
161		.byte	1, 2, 3, 4, 5, 6	| expected buf
162
163test4:
164		| len == 0
165		.byte	1, 2, 3, 4, 5, 6	| initial buf
166		.long	0			| len
167		.long	buf+1			| src
168		.long	buf+1			| dst
169		.byte	1, 2, 3, 4, 5, 6	| expected buf
170
171msg_testname:
172		.asciz	"memmove"
173msg_ok:
174		.asciz	" ok"
175msg_fail:
176		.asciz	" fail"
177msg_crlf:
178		.asciz	"\r\n"
179
180		BSS(buf, 8)
181#endif
182