1*b6cbf720SGianluca Guida/* $NetBSD: memcpy.S,v 1.2 2006/04/22 23:53:47 uwe Exp $ */ 2*b6cbf720SGianluca Guida 3*b6cbf720SGianluca Guida/* 4*b6cbf720SGianluca Guida * Copyright (c) 2000 SHIMIZU Ryo <ryo@misakimix.org> 5*b6cbf720SGianluca Guida * All rights reserved. 6*b6cbf720SGianluca Guida * 7*b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or without 8*b6cbf720SGianluca Guida * modification, are permitted provided that the following conditions 9*b6cbf720SGianluca Guida * are met: 10*b6cbf720SGianluca Guida * 1. Redistributions of source code must retain the above copyright 11*b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer. 12*b6cbf720SGianluca Guida * 2. Redistributions in binary form must reproduce the above copyright 13*b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer in the 14*b6cbf720SGianluca Guida * documentation and/or other materials provided with the distribution. 15*b6cbf720SGianluca Guida * 3. The name of the author may not be used to endorse or promote products 16*b6cbf720SGianluca Guida * derived from this software without specific prior written permission. 17*b6cbf720SGianluca Guida * 18*b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19*b6cbf720SGianluca Guida * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20*b6cbf720SGianluca Guida * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21*b6cbf720SGianluca Guida * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22*b6cbf720SGianluca Guida * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23*b6cbf720SGianluca Guida * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*b6cbf720SGianluca Guida * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*b6cbf720SGianluca Guida * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*b6cbf720SGianluca Guida * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*b6cbf720SGianluca Guida * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*b6cbf720SGianluca Guida */ 29*b6cbf720SGianluca Guida 30*b6cbf720SGianluca Guida#include <machine/asm.h> 31*b6cbf720SGianluca Guida 32*b6cbf720SGianluca Guida#if defined(LIBC_SCCS) && !defined(lint) 33*b6cbf720SGianluca Guida RCSID("$NetBSD: memcpy.S,v 1.2 2006/04/22 23:53:47 uwe Exp $") 34*b6cbf720SGianluca Guida#endif 35*b6cbf720SGianluca Guida 36*b6cbf720SGianluca Guida#if !defined(MEMCOPY) && !defined(MEMMOVE) && !defined(BCOPY) 37*b6cbf720SGianluca Guida#define MEMCOPY 38*b6cbf720SGianluca Guida#endif 39*b6cbf720SGianluca Guida 40*b6cbf720SGianluca Guida#if defined(MEMCOPY) || defined(MEMMOVE) 41*b6cbf720SGianluca Guida#define REG_DST0 r3 42*b6cbf720SGianluca Guida#define REG_SRC r5 43*b6cbf720SGianluca Guida#define REG_DST r4 44*b6cbf720SGianluca Guida#else 45*b6cbf720SGianluca Guida#define REG_SRC r4 46*b6cbf720SGianluca Guida#define REG_DST r5 47*b6cbf720SGianluca Guida#endif 48*b6cbf720SGianluca Guida 49*b6cbf720SGianluca Guida#define REG_LEN r6 50*b6cbf720SGianluca Guida 51*b6cbf720SGianluca Guida#if defined(MEMCOPY) 52*b6cbf720SGianluca GuidaENTRY(memcpy) 53*b6cbf720SGianluca Guida#elif defined(MEMMOVE) 54*b6cbf720SGianluca GuidaENTRY(memmove) 55*b6cbf720SGianluca Guida#elif defined(BCOPY) 56*b6cbf720SGianluca GuidaENTRY(bcopy) 57*b6cbf720SGianluca Guida#endif 58*b6cbf720SGianluca Guida#ifdef REG_DST0 59*b6cbf720SGianluca Guida mov REG_DST,REG_DST0 60*b6cbf720SGianluca Guida#endif 61*b6cbf720SGianluca Guida cmp/eq REG_DST,REG_SRC /* if ( src == dst ) return; */ 62*b6cbf720SGianluca Guida bt/s bcopy_return 63*b6cbf720SGianluca Guida cmp/hi REG_DST,REG_SRC 64*b6cbf720SGianluca Guida bf/s bcopy_overlap 65*b6cbf720SGianluca Guida 66*b6cbf720SGianluca Guida mov REG_SRC,r0 67*b6cbf720SGianluca Guida xor REG_DST,r0 68*b6cbf720SGianluca Guida and #3,r0 69*b6cbf720SGianluca Guida mov r0,r1 70*b6cbf720SGianluca Guida tst r0,r0 /* (src ^ dst) & 3 */ 71*b6cbf720SGianluca Guida bf/s word_align 72*b6cbf720SGianluca Guida 73*b6cbf720SGianluca Guidalongword_align: 74*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN /* if ( len==0 ) return; */ 75*b6cbf720SGianluca Guida bt/s bcopy_return 76*b6cbf720SGianluca Guida 77*b6cbf720SGianluca Guida 78*b6cbf720SGianluca Guida mov REG_SRC,r0 79*b6cbf720SGianluca Guida tst #1,r0 /* if ( src & 1 ) */ 80*b6cbf720SGianluca Guida bt 1f 81*b6cbf720SGianluca Guida mov.b @REG_SRC+,r0 /* *dst++ = *src++; */ 82*b6cbf720SGianluca Guida add #-1,REG_LEN 83*b6cbf720SGianluca Guida mov.b r0,@REG_DST 84*b6cbf720SGianluca Guida add #1,REG_DST 85*b6cbf720SGianluca Guida1: 86*b6cbf720SGianluca Guida 87*b6cbf720SGianluca Guida 88*b6cbf720SGianluca Guida mov #1,r0 89*b6cbf720SGianluca Guida cmp/hi r0,REG_LEN /* if ( (len > 1) && */ 90*b6cbf720SGianluca Guida bf/s 1f 91*b6cbf720SGianluca Guida mov REG_SRC,r0 92*b6cbf720SGianluca Guida tst #2,r0 /* (src & 2) { */ 93*b6cbf720SGianluca Guida bt 1f 94*b6cbf720SGianluca Guida mov.w @REG_SRC+,r0 /* *((unsigned short*)dst)++ = *((unsigned short*)src)++; */ 95*b6cbf720SGianluca Guida add #-2,REG_LEN /* len -= 2; */ 96*b6cbf720SGianluca Guida mov.w r0,@REG_DST 97*b6cbf720SGianluca Guida add #2,REG_DST /* } */ 98*b6cbf720SGianluca Guida1: 99*b6cbf720SGianluca Guida 100*b6cbf720SGianluca Guida 101*b6cbf720SGianluca Guida mov #3,r1 102*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN /* while ( len > 3 ) { */ 103*b6cbf720SGianluca Guida bf/s no_align_delay 104*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 105*b6cbf720SGianluca Guida2: 106*b6cbf720SGianluca Guida mov.l @REG_SRC+,r0 /* *((unsigned long*)dst)++ = *((unsigned long*)src)++; */ 107*b6cbf720SGianluca Guida add #-4,REG_LEN /* len -= 4; */ 108*b6cbf720SGianluca Guida mov.l r0,@REG_DST 109*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN 110*b6cbf720SGianluca Guida bt/s 2b 111*b6cbf720SGianluca Guida add #4,REG_DST /* } */ 112*b6cbf720SGianluca Guida 113*b6cbf720SGianluca Guida bra no_align_delay 114*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 115*b6cbf720SGianluca Guida 116*b6cbf720SGianluca Guida 117*b6cbf720SGianluca Guidaword_align: 118*b6cbf720SGianluca Guida mov r1,r0 119*b6cbf720SGianluca Guida tst #1,r0 120*b6cbf720SGianluca Guida bf/s no_align_delay 121*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN /* if ( len == 0 ) return; */ 122*b6cbf720SGianluca Guida bt bcopy_return 123*b6cbf720SGianluca Guida 124*b6cbf720SGianluca Guida 125*b6cbf720SGianluca Guida mov REG_SRC,r0 /* if ( src & 1 ) */ 126*b6cbf720SGianluca Guida tst #1,r0 127*b6cbf720SGianluca Guida bt 1f 128*b6cbf720SGianluca Guida mov.b @REG_SRC+,r0 /* *dst++ = *src++; */ 129*b6cbf720SGianluca Guida add #-1,REG_LEN 130*b6cbf720SGianluca Guida mov.b r0,@REG_DST 131*b6cbf720SGianluca Guida add #1,REG_DST 132*b6cbf720SGianluca Guida1: 133*b6cbf720SGianluca Guida 134*b6cbf720SGianluca Guida 135*b6cbf720SGianluca Guida mov #1,r1 136*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN /* while ( len > 1 ) { */ 137*b6cbf720SGianluca Guida bf/s no_align_delay 138*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 139*b6cbf720SGianluca Guida2: 140*b6cbf720SGianluca Guida mov.w @REG_SRC+,r0 /* *((unsigned short*)dst)++ = *((unsigned short*)src)++; */ 141*b6cbf720SGianluca Guida add #-2,REG_LEN /* len -= 2; */ 142*b6cbf720SGianluca Guida mov.w r0,@REG_DST 143*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN 144*b6cbf720SGianluca Guida bt/s 2b 145*b6cbf720SGianluca Guida add #2,REG_DST /* } */ 146*b6cbf720SGianluca Guida 147*b6cbf720SGianluca Guida 148*b6cbf720SGianluca Guidano_align: 149*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN /* while ( len!= ) { */ 150*b6cbf720SGianluca Guidano_align_delay: 151*b6cbf720SGianluca Guida bt bcopy_return 152*b6cbf720SGianluca Guida1: 153*b6cbf720SGianluca Guida mov.b @REG_SRC+,r0 /* *dst++ = *src++; */ 154*b6cbf720SGianluca Guida add #-1,REG_LEN /* len--; */ 155*b6cbf720SGianluca Guida mov.b r0,@REG_DST 156*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 157*b6cbf720SGianluca Guida bf/s 1b 158*b6cbf720SGianluca Guida add #1,REG_DST /* } */ 159*b6cbf720SGianluca Guidabcopy_return: 160*b6cbf720SGianluca Guida rts 161*b6cbf720SGianluca Guida#ifdef REG_DST0 162*b6cbf720SGianluca Guida mov REG_DST0,r0 163*b6cbf720SGianluca Guida#else 164*b6cbf720SGianluca Guida nop 165*b6cbf720SGianluca Guida#endif 166*b6cbf720SGianluca Guida 167*b6cbf720SGianluca Guida 168*b6cbf720SGianluca Guidabcopy_overlap: 169*b6cbf720SGianluca Guida add REG_LEN,REG_SRC 170*b6cbf720SGianluca Guida add REG_LEN,REG_DST 171*b6cbf720SGianluca Guida 172*b6cbf720SGianluca Guida mov REG_SRC,r0 173*b6cbf720SGianluca Guida xor REG_DST,r0 174*b6cbf720SGianluca Guida and #3,r0 175*b6cbf720SGianluca Guida mov r0,r1 176*b6cbf720SGianluca Guida tst r0,r0 /* (src ^ dst) & 3 */ 177*b6cbf720SGianluca Guida bf/s ov_word_align 178*b6cbf720SGianluca Guida 179*b6cbf720SGianluca Guidaov_longword_align: 180*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN /* if ( len==0 ) return; */ 181*b6cbf720SGianluca Guida bt/s bcopy_return 182*b6cbf720SGianluca Guida 183*b6cbf720SGianluca Guida 184*b6cbf720SGianluca Guida mov REG_SRC,r0 185*b6cbf720SGianluca Guida tst #1,r0 /* if ( src & 1 ) */ 186*b6cbf720SGianluca Guida bt 1f 187*b6cbf720SGianluca Guida add #-1,REG_SRC /* *--dst = *--src; */ 188*b6cbf720SGianluca Guida mov.b @REG_SRC,r0 189*b6cbf720SGianluca Guida mov.b r0,@-REG_DST 190*b6cbf720SGianluca Guida add #-1,REG_LEN 191*b6cbf720SGianluca Guida1: 192*b6cbf720SGianluca Guida 193*b6cbf720SGianluca Guida 194*b6cbf720SGianluca Guida mov #1,r0 195*b6cbf720SGianluca Guida cmp/hi r0,REG_LEN /* if ( (len > 1) && */ 196*b6cbf720SGianluca Guida bf/s 1f 197*b6cbf720SGianluca Guida mov REG_SRC,r0 198*b6cbf720SGianluca Guida tst #2,r0 /* (src & 2) { */ 199*b6cbf720SGianluca Guida bt 1f 200*b6cbf720SGianluca Guida add #-2,REG_SRC /* *--((unsigned short*)dst) = *--((unsigned short*)src); */ 201*b6cbf720SGianluca Guida mov.w @REG_SRC,r0 202*b6cbf720SGianluca Guida add #-2,REG_LEN /* len -= 2; */ 203*b6cbf720SGianluca Guida mov.w r0,@-REG_DST /* } */ 204*b6cbf720SGianluca Guida1: 205*b6cbf720SGianluca Guida 206*b6cbf720SGianluca Guida 207*b6cbf720SGianluca Guida mov #3,r1 208*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN /* while ( len > 3 ) { */ 209*b6cbf720SGianluca Guida bf/s ov_no_align_delay 210*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 211*b6cbf720SGianluca Guida2: 212*b6cbf720SGianluca Guida add #-4,REG_SRC 213*b6cbf720SGianluca Guida mov.l @REG_SRC,r0 /* *((unsigned long*)dst)++ = *((unsigned long*)src)++; */ 214*b6cbf720SGianluca Guida add #-4,REG_LEN /* len -= 4; */ 215*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN 216*b6cbf720SGianluca Guida bt/s 2b 217*b6cbf720SGianluca Guida mov.l r0,@-REG_DST /* } */ 218*b6cbf720SGianluca Guida 219*b6cbf720SGianluca Guida bra ov_no_align_delay 220*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 221*b6cbf720SGianluca Guida 222*b6cbf720SGianluca Guida 223*b6cbf720SGianluca Guidaov_word_align: 224*b6cbf720SGianluca Guida mov r1,r0 225*b6cbf720SGianluca Guida tst #1,r0 226*b6cbf720SGianluca Guida bf/s ov_no_align_delay 227*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN /* if ( len == 0 ) return; */ 228*b6cbf720SGianluca Guida bt bcopy_return 229*b6cbf720SGianluca Guida 230*b6cbf720SGianluca Guida 231*b6cbf720SGianluca Guida mov REG_SRC,r0 /* if ( src & 1 ) */ 232*b6cbf720SGianluca Guida tst #1,r0 233*b6cbf720SGianluca Guida bt 1f 234*b6cbf720SGianluca Guida add #-1,REG_SRC 235*b6cbf720SGianluca Guida mov.b @REG_SRC,r0 /* *--dst = *--src; */ 236*b6cbf720SGianluca Guida add #-1,REG_LEN 237*b6cbf720SGianluca Guida mov.b r0,@-REG_DST 238*b6cbf720SGianluca Guida1: 239*b6cbf720SGianluca Guida 240*b6cbf720SGianluca Guida 241*b6cbf720SGianluca Guida mov #1,r1 242*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN /* while ( len > 1 ) { */ 243*b6cbf720SGianluca Guida bf/s ov_no_align_delay 244*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 245*b6cbf720SGianluca Guida2: 246*b6cbf720SGianluca Guida add #-2,REG_SRC 247*b6cbf720SGianluca Guida mov.w @REG_SRC,r0 /* *--((unsigned short*)dst) = *--((unsigned short*)src); */ 248*b6cbf720SGianluca Guida add #-2,REG_LEN /* len -= 2; */ 249*b6cbf720SGianluca Guida cmp/hi r1,REG_LEN 250*b6cbf720SGianluca Guida bt/s 2b 251*b6cbf720SGianluca Guida mov.w r0,@-REG_DST /* } */ 252*b6cbf720SGianluca Guida 253*b6cbf720SGianluca Guida 254*b6cbf720SGianluca Guidaov_no_align: 255*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN /* while ( len!= ) { */ 256*b6cbf720SGianluca Guidaov_no_align_delay: 257*b6cbf720SGianluca Guida bt 9f 258*b6cbf720SGianluca Guida1: 259*b6cbf720SGianluca Guida add #-1,REG_SRC 260*b6cbf720SGianluca Guida mov.b @REG_SRC,r0 /* *--dst = *--src; */ 261*b6cbf720SGianluca Guida add #-1,REG_LEN /* len--; */ 262*b6cbf720SGianluca Guida tst REG_LEN,REG_LEN 263*b6cbf720SGianluca Guida bf/s 1b 264*b6cbf720SGianluca Guida mov.b r0,@-REG_DST /* } */ 265*b6cbf720SGianluca Guida9: 266*b6cbf720SGianluca Guida rts 267*b6cbf720SGianluca Guida#ifdef REG_DST0 268*b6cbf720SGianluca Guida mov REG_DST0,r0 269*b6cbf720SGianluca Guida#else 270*b6cbf720SGianluca Guida nop 271*b6cbf720SGianluca Guida#endif 272