11.1Sisaki/*	$NetBSD: memcpy.S,v 1.1 2020/08/16 06:43:43 isaki Exp $	*/
21.1Sisaki
31.1Sisaki/*
41.1Sisaki * Copyright (C) 2020 Tetsuya Isaki. All rights reserved.
51.1Sisaki * Copyright (C) 2020 Y.Sugahara (moveccr). All rights reserved.
61.1Sisaki *
71.1Sisaki * Redistribution and use in source and binary forms, with or without
81.1Sisaki * modification, are permitted provided that the following conditions
91.1Sisaki * are met:
101.1Sisaki * 1. Redistributions of source code must retain the above copyright
111.1Sisaki *    notice, this list of conditions and the following disclaimer.
121.1Sisaki * 2. Redistributions in binary form must reproduce the above copyright
131.1Sisaki *    notice, this list of conditions and the following disclaimer in the
141.1Sisaki *    documentation and/or other materials provided with the distribution.
151.1Sisaki *
161.1Sisaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
171.1Sisaki * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
181.1Sisaki * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
191.1Sisaki * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
201.1Sisaki * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
211.1Sisaki * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
221.1Sisaki * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
231.1Sisaki * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
241.1Sisaki * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251.1Sisaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261.1Sisaki * SUCH DAMAGE.
271.1Sisaki */
281.1Sisaki
291.1Sisaki/*
301.1Sisaki * Size optimized (but slow) version for primary bootloader.
311.1Sisaki */
321.1Sisaki
331.1Sisaki#include <machine/asm.h>
341.1Sisaki
351.1Sisaki|
361.1Sisaki| void bcopy(const void *src, void *dst, size_t len);
371.1Sisaki|
381.1SisakiASENTRY_NOPROFILE(bcopy)
391.1Sisaki		moveml	%sp@,%d0-%d1/%a0-%a1	| %d0: (return address)
401.1Sisaki						| %d1: src
411.1Sisaki						| %a0: dst
421.1Sisaki						| %a1: count
431.1Sisaki		jbra	memmove_common
441.1Sisaki|
451.1Sisaki| void *memcpy(void *dst, const void *src, size_t count);
461.1Sisaki| void *memmove(void *dst, const void *src, size_t count);
471.1Sisaki|
481.1SisakiASENTRY_NOPROFILE(memcpy)
491.1SisakiASENTRY_NOPROFILE(memmove)
501.1Sisaki		moveml	%sp@,%d0-%d1/%a0-%a1	| %d0: (return address)
511.1Sisaki						| %d1: dst
521.1Sisaki						| %a0: src
531.1Sisaki						| %a1: count
541.1Sisaki
551.1Sisaki		exg	%d1,%a0			| %d1: src
561.1Sisaki						| %a0: dst
571.1Sisaki						| %a1: count
581.1Sisakimemmove_common:
591.1Sisaki		exg	%d1,%a1			| %d1: count
601.1Sisaki						| %a0: dst
611.1Sisaki						| %a1: src
621.1Sisaki		moveql	#0,%d0
631.1Sisaki						| %d0: offset in forward mode.
641.1Sisaki						| %d1: offset in backward mode
651.1Sisaki						|  and also loop counter.
661.1Sisaki		jbra	2f
671.1Sisakiloop:
681.1Sisaki		| if src(=%a1) > dst(=%a0), then this is forward copy,
691.1Sisaki		|  %d0 is already forward offset.
701.1Sisaki		| Otherwise backward copy.  Copy %d1(backward offset) to %d0.
711.1Sisaki		cmpl	%a1,%a0
721.1Sisaki		jcs	1f
731.1Sisaki		movel	%d1,%d0
741.1Sisaki1:
751.1Sisaki		moveb	%a1@(%d0.l),%a0@(%d0.l) | %d0: offset
761.1Sisaki		addql	#1,%d0			| increment forward counter,
771.1Sisaki						|  though it's pointless in
781.1Sisaki						|  backward mode
791.1Sisaki2:
801.1Sisaki		subql	#1,%d1			| if (--count < 0)
811.1Sisaki		jcc	loop			|  goto exit
821.1Sisakiexit:
831.1Sisaki		rts				| %a0 holds return value (=dst)
841.1Sisaki
851.1Sisaki
861.1Sisaki#if defined(SELFTEST)
871.1Sisaki#include "iocscall.h"
881.1Sisaki		.macro	PRINT	msg
891.1Sisaki		leal	\msg,%a1
901.1Sisaki		IOCS(__B_PRINT)
911.1Sisaki		.endm
921.1Sisaki
931.1Sisaki		.macro	TEST	name
941.1Sisaki		leal	\name,%a2
951.1Sisaki		jbsr	test
961.1Sisaki		.endm
971.1Sisaki
981.1SisakiASENTRY_NOPROFILE(selftest_memmove)
991.1Sisaki		moveml	%d2-%d7/%a2-%a6,%sp@-
1001.1Sisaki		PRINT	%pc@(msg_testname)
1011.1Sisaki
1021.1Sisaki		TEST	test1
1031.1Sisaki		TEST	test2
1041.1Sisaki		TEST	test3
1051.1Sisaki		TEST	test4
1061.1Sisaki
1071.1Sisaki		PRINT	%pc@(msg_crlf)
1081.1Sisaki		moveml	%sp@+,%d2-%d7/%a2-%a6
1091.1Sisaki		rts
1101.1Sisaki
1111.1Sisakitest:
1121.1Sisaki		movel	%a2@+,buf:W		| initial contents of buffer
1131.1Sisaki		movew	%a2@+,(buf+4):W		|  (6 bytes total)
1141.1Sisaki		movel	%a2@+,%sp@-		| push len
1151.1Sisaki		movel	%a2@+,%sp@-		| push src
1161.1Sisaki		movel	%a2@+,%a3		| keep dst and
1171.1Sisaki		movel	%a3,%sp@-		| push dst
1181.1Sisaki		jbsr	memmove
1191.1Sisaki		leal	%sp@(12),%sp
1201.1Sisaki
1211.1Sisaki		cmpal	%a3,%a0			| compare return value
1221.1Sisaki		jne	fail
1231.1Sisaki		movel	%a2@+,%d0		| compare buf[0..3]
1241.1Sisaki		cmpl	buf:W,%d0
1251.1Sisaki		jne	fail
1261.1Sisaki		movew	%a2@+,%d0		| compare buf[4..5]
1271.1Sisaki		cmpw	(buf+4):W,%d0		| compare buf[4..5]
1281.1Sisaki		jne	fail
1291.1Sisaki		PRINT	%pc@(msg_ok)
1301.1Sisaki		rts
1311.1Sisakifail:
1321.1Sisaki		PRINT	%pc@(msg_fail)
1331.1Sisaki		rts
1341.1Sisaki
1351.1Sisakitest1:
1361.1Sisaki		| src=buf+1: 1 2 3 4 5 6
1371.1Sisaki		|               \ \
1381.1Sisaki		| dst=buf+2: 1 2 2 3 5 6
1391.1Sisaki		.byte	1, 2, 3, 4, 5, 6	| initial buf
1401.1Sisaki		.long	2			| len
1411.1Sisaki		.long	buf+1			| src
1421.1Sisaki		.long	buf+2			| dst
1431.1Sisaki		.byte	1, 2, 2, 3, 5, 6	| expected buf
1441.1Sisaki
1451.1Sisakitest2:
1461.1Sisaki		| src=buf+2: 1 2 3 4 5 6
1471.1Sisaki		|               / /
1481.1Sisaki		| dst=buf+1: 1 3 4 4 5 6
1491.1Sisaki		.byte	1, 2, 3, 4, 5, 6	| initial buf
1501.1Sisaki		.long	2			| len
1511.1Sisaki		.long	buf+2			| src
1521.1Sisaki		.long	buf+1			| dst
1531.1Sisaki		.byte	1, 3, 4, 4, 5, 6	| expected buf
1541.1Sisaki
1551.1Sisakitest3:
1561.1Sisaki		| src == dst
1571.1Sisaki		.byte	1, 2, 3, 4, 5, 6	| initial buf
1581.1Sisaki		.long	2			| len
1591.1Sisaki		.long	buf+1			| src
1601.1Sisaki		.long	buf+1			| dst
1611.1Sisaki		.byte	1, 2, 3, 4, 5, 6	| expected buf
1621.1Sisaki
1631.1Sisakitest4:
1641.1Sisaki		| len == 0
1651.1Sisaki		.byte	1, 2, 3, 4, 5, 6	| initial buf
1661.1Sisaki		.long	0			| len
1671.1Sisaki		.long	buf+1			| src
1681.1Sisaki		.long	buf+1			| dst
1691.1Sisaki		.byte	1, 2, 3, 4, 5, 6	| expected buf
1701.1Sisaki
1711.1Sisakimsg_testname:
1721.1Sisaki		.asciz	"memmove"
1731.1Sisakimsg_ok:
1741.1Sisaki		.asciz	" ok"
1751.1Sisakimsg_fail:
1761.1Sisaki		.asciz	" fail"
1771.1Sisakimsg_crlf:
1781.1Sisaki		.asciz	"\r\n"
1791.1Sisaki
1801.1Sisaki		BSS(buf, 8)
1811.1Sisaki#endif
182