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