Home | History | Annotate | Line # | Download | only in m68k
      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  */
     43 ENTRY(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:
     56 1:	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:
     62 2:	clrl	(%a0)+
     63 	dbf	%d1, 2b			| will use the 68010 loop mode
     64 #else	/* !__mc68010__ */
     65 2:	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:
     71 3:	subil	#0x10000, %d1
     72 	bcc	2b
     73 
     74 | zero the odd bytes:
     75 4:	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
     78 5:	clrb	(%a0)+
     79 	dbf	%d0, 5b			| will use the 68010 loop mode
     80 
     81 6:	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  */
     88 ENTRY(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:
    102 1:	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:
    114 2:	movl	(%a0)+, (%a1)+
    115 	dbf	%d1, 2b			| will use the 68010 loop mode
    116 #else	/* !__mc68010__ */
    117 2:	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:
    123 3:	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:
    129 4:	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:
    137 5:	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:
    149 6:	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
    152 7:	movb	(%a0)+, (%a1)+
    153 	dbf	%d0, 7b			| use loop mode
    154 
    155 8:	rts
    156