/* $NetBSD: w16copy.s,v 1.3 2013/08/01 13:42:52 matt Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Matt Fredette. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * NOTICE: This is not a standalone file. To use it, #include it in * your port's locore.s, like so: * * #include */ /* * Function to zero a region of memory using only * properly aligned 8- and 16-bit accesses. */ ENTRY(w16zero) movl 8(%sp), %d0 | get our count beq 6f | return if count is zero movl 4(%sp), %a0 | get our address | align %a0 to a 16-bit boundary: movl %a0, %d1 btst #0, %d1 | is %a0 even? beq 1f | if so, skip ahead clrb (%a0)+ | zero one byte subql #1, %d0 | decrement count | now zero 32 bits at a time: 1: movl %d0, %d1 | copy count into %d1 lsrl #2, %d1 | turn %d1 into long count subqw #1, %d1 | set up for dbf bcs 3f | skip ahead if long count % 64k == 0 #ifdef __mc68010__ | on a 68010, 32-bit accesses become 16-bit accesses externally: 2: clrl (%a0)+ dbf %d1, 2b | will use the 68010 loop mode #else /* !__mc68010__ */ 2: clrw (%a0)+ clrw (%a0)+ dbf %d1, 2b #endif /* !__mc68010__ */ | since DBcc only uses the low 16-bits of the count | register, we have to decrement the high 16-bits: 3: subil #0x10000, %d1 bcc 2b | zero the odd bytes: 4: andil #3, %d0 | odd byte count in %d0 subqw #1, %d0 | set up for dbf bcs 6f | skip ahead if no odd bytes 5: clrb (%a0)+ dbf %d0, 5b | will use the 68010 loop mode 6: rts /* * Function to copy a region of memory to a nonoverlapping * region of memory using only properly aligned 8- and * 16-bit accesses. */ ENTRY(w16copy) movl 12(%sp), %d0 | get our count beq 8f | return if count is zero movl 4(%sp), %a0 | get our source address movl 8(%sp), %a1 | get our destination address | align %a0 to a 16-bit boundary: movl %a0, %d1 btst #0, %d1 | is %a0 even? beq 1f | if so, skip ahead movb (%a0)+, (%a1)+ | copy one byte subql #1, %d0 | decrement count | branch on whether or not %a1 is aligned to a 16-bit boundary: 1: movl %a1, %d1 btst #0, %d1 | is %a1 even? bne 4f | if not, skip ahead | %a1 is also aligned to a 16-bit boundary, so we can copy | the easy way, 32 bits at a time: movl %d0, %d1 | copy count into %d1 lsrl #2, %d1 | turn %d1 into long count subqw #1, %d1 | set up for dbf bcs 3f | skip ahead if long count % 64k == 0 #ifdef __mc68010__ | on a 68010, 32-bit accesses become 16-bit accesses externally: 2: movl (%a0)+, (%a1)+ dbf %d1, 2b | will use the 68010 loop mode #else /* !__mc68010__ */ 2: movw (%a0)+, (%a1)+ movw (%a0)+, (%a1)+ dbf %d1, 2b #endif /* !__mc68010__ */ | since DBcc only uses the low 16-bits of the count | register, we have to decrement the high 16-bits: 3: subil #0x10000, %d1 bcc 2b bra 6f | jump ahead to copy the odd bytes | %a1 is misaligned, so we're forced to copy the hard way. | if there are fewer than four bytes, copy only odd bytes: 4: cmpil #4, %d0 | is count less than 4? bcs 6f | if so, skip ahead | prime the FIFO: movw (%a0)+, %d1 | FIFO: xx01 rorl #8, %d1 | FIFO: 1xx0 movb %d1, (%a1)+ | FIFO: 1xxx subql #4, %d0 | subtract 4 from count | run the FIFO: 5: rorl #8, %d1 | FIFO: x1xx movw (%a0)+, %d1 | FIFO: x123 rorl #8, %d1 | FIFO: 3x12 movw %d1, (%a1)+ | FIFO: 3xxx -> 1xxx subql #2, %d0 | two or more bytes remaining? bcc 5b | loop back, if so. | flush the FIFO: roll #8, %d1 | FIFO: xxx1 movb %d1, (%a1)+ | FIFO: xxxx addl #2, %d0 | fix up count | copy the odd bytes: 6: andil #3, %d0 | odd byte count in %d0 subqw #1, %d0 | set up for dbf bcs 8f | skip ahead if no odd bytes 7: movb (%a0)+, (%a1)+ dbf %d0, 7b | use loop mode 8: rts