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