xref: /netbsd-src/sys/arch/m68k/m68k/w16copy.s (revision 4aa16837d6c5a854ea7598ac4deb33c3d4a4f074)
1/*	$NetBSD: w16copy.s,v 1.4 2023/09/26 12:46:30 tsutsui Exp $	*/
2
3/*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Fredette.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * NOTICE: This is not a standalone file.  To use it, #include it in
34 * your port's locore.s, like so:
35 *
36 *	#include <m68k/m68k/w16copy.s>
37 */
38
39/*
40 * Function to zero a region of memory using only
41 * properly aligned 8- and 16-bit accesses.
42 */
43ENTRY(w16zero)
44	movl	8(%sp), %d0		| get our count
45	beq	6f			| return if count is zero
46	movl	4(%sp), %a0		| get our address
47
48| align %a0 to a 16-bit boundary:
49	movl	%a0, %d1
50	btst	#0, %d1			| is %a0 even?
51	beq	1f			| if so, skip ahead
52	clrb	(%a0)+			| zero one byte
53	subql	#1, %d0			| decrement count
54
55| now zero 32 bits at a time:
561:	movl	%d0, %d1		| copy count into %d1
57	lsrl	#2, %d1			| turn %d1 into long count
58	subqw	#1, %d1			| set up for dbf
59	bcs	3f			| skip ahead if long count % 64k == 0
60#ifdef	__mc68010__
61| on a 68010, 32-bit accesses become 16-bit accesses externally:
622:	clrl	(%a0)+
63	dbf	%d1, 2b			| will use the 68010 loop mode
64#else	/* !__mc68010__ */
652:	clrw	(%a0)+
66	clrw	(%a0)+
67	dbf	%d1, 2b
68#endif	/* !__mc68010__ */
69| since DBcc only uses the low 16-bits of the count
70| register, we have to decrement the high 16-bits:
713:	subil	#0x10000, %d1
72	bcc	2b
73
74| zero the odd bytes:
754:	andil	#3, %d0			| odd byte count in %d0
76	subqw	#1, %d0			| set up for dbf
77	bcs	6f			| skip ahead if no odd bytes
785:	clrb	(%a0)+
79	dbf	%d0, 5b			| will use the 68010 loop mode
80
816:	rts
82
83/*
84 * Function to copy a region of memory to a nonoverlapping
85 * region of memory using only properly aligned 8- and
86 * 16-bit accesses.
87 */
88ENTRY(w16copy)
89	movl	12(%sp), %d0		| get our count
90	beq	8f			| return if count is zero
91	movl	4(%sp), %a0		| get our source address
92	movl	8(%sp), %a1		| get our destination address
93
94| align %a0 to a 16-bit boundary:
95	movl	%a0, %d1
96	btst	#0, %d1			| is %a0 even?
97	beq	1f			| if so, skip ahead
98	movb	(%a0)+, (%a1)+		| copy one byte
99	subql	#1, %d0			| decrement count
100
101| branch on whether or not %a1 is aligned to a 16-bit boundary:
1021:	movl	%a1, %d1
103	btst	#0, %d1			| is %a1 even?
104	bne	4f			| if not, skip ahead
105
106| %a1 is also aligned to a 16-bit boundary, so we can copy
107| the easy way, 32 bits at a time:
108	movl	%d0, %d1		| copy count into %d1
109	lsrl	#2, %d1			| turn %d1 into long count
110	subqw	#1, %d1			| set up for dbf
111	bcs	3f			| skip ahead if long count % 64k == 0
112#ifdef	__mc68010__
113| on a 68010, 32-bit accesses become 16-bit accesses externally:
1142:	movl	(%a0)+, (%a1)+
115	dbf	%d1, 2b			| will use the 68010 loop mode
116#else	/* !__mc68010__ */
1172:	movw	(%a0)+, (%a1)+
118	movw	(%a0)+, (%a1)+
119	dbf	%d1, 2b
120#endif	/* !__mc68010__ */
121| since DBcc only uses the low 16-bits of the count
122| register, we have to decrement the high 16-bits:
1233:	subil	#0x10000, %d1
124	bcc	2b
125	bra	6f			| jump ahead to copy the odd bytes
126
127| %a1 is misaligned, so we're forced to copy the hard way.
128| if there are fewer than four bytes, copy only odd bytes:
1294:	cmpil	#4, %d0			| is count less than 4?
130	bcs	6f			| if so, skip ahead
131| prime the FIFO:
132	movw	(%a0)+, %d1		| FIFO: xx01
133	rorl	#8, %d1			| FIFO: 1xx0
134	movb	%d1, (%a1)+		| FIFO: 1xxx
135	subql	#4, %d0			| subtract 4 from count
136| run the FIFO:
1375:	rorl	#8, %d1			| FIFO: x1xx
138	movw	(%a0)+, %d1		| FIFO: x123
139	rorl	#8, %d1			| FIFO: 3x12
140	movw	%d1, (%a1)+		| FIFO: 3xxx -> 1xxx
141	subql	#2, %d0			| two or more bytes remaining?
142	bcc	5b			| loop back, if so.
143| flush the FIFO:
144	roll	#8, %d1			| FIFO: xxx1
145	movb	%d1, (%a1)+		| FIFO: xxxx
146	addl	#2, %d0			| fix up count
147
148| copy the odd bytes:
1496:	andil	#3, %d0			| odd byte count in %d0
150	subqw	#1, %d0			| set up for dbf
151	bcs	8f			| skip ahead if no odd bytes
1527:	movb	(%a0)+, (%a1)+
153	dbf	%d0, 7b			| use loop mode
154
1558:	rts
156