1*b6cbf720SGianluca Guida/* $NetBSD: memmove.S,v 1.3 2011/01/15 07:31:12 matt Exp $ */ 2*b6cbf720SGianluca Guida 3*b6cbf720SGianluca Guida/* stropt/memmove.S, pl_string_common, pl_linux 10/11/04 11:45:37 4*b6cbf720SGianluca Guida * ========================================================================== 5*b6cbf720SGianluca Guida * Optimized memmove implementation for IBM PowerPC 405/440. 6*b6cbf720SGianluca Guida * 7*b6cbf720SGianluca Guida * Copyright (c) 2003, IBM Corporation 8*b6cbf720SGianluca Guida * All rights reserved. 9*b6cbf720SGianluca Guida * 10*b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or 11*b6cbf720SGianluca Guida * without modification, are permitted provided that the following 12*b6cbf720SGianluca Guida * conditions are met: 13*b6cbf720SGianluca Guida * 14*b6cbf720SGianluca Guida * * Redistributions of source code must retain the above 15*b6cbf720SGianluca Guida * copyright notice, this list of conditions and the following 16*b6cbf720SGianluca Guida * disclaimer. 17*b6cbf720SGianluca Guida * * Redistributions in binary form must reproduce the above 18*b6cbf720SGianluca Guida * copyright notice, this list of conditions and the following 19*b6cbf720SGianluca Guida * disclaimer in the documentation and/or other materials 20*b6cbf720SGianluca Guida * provided with the distribution. 21*b6cbf720SGianluca Guida * * Neither the name of IBM nor the names of its contributors 22*b6cbf720SGianluca Guida * may be used to endorse or promote products derived from this 23*b6cbf720SGianluca Guida * software without specific prior written permission. 24*b6cbf720SGianluca Guida * 25*b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 26*b6cbf720SGianluca Guida * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 27*b6cbf720SGianluca Guida * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28*b6cbf720SGianluca Guida * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29*b6cbf720SGianluca Guida * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 30*b6cbf720SGianluca Guida * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31*b6cbf720SGianluca Guida * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32*b6cbf720SGianluca Guida * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33*b6cbf720SGianluca Guida * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 34*b6cbf720SGianluca Guida * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35*b6cbf720SGianluca Guida * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 36*b6cbf720SGianluca Guida * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37*b6cbf720SGianluca Guida * 38*b6cbf720SGianluca Guida * ========================================================================== 39*b6cbf720SGianluca Guida * 40*b6cbf720SGianluca Guida * Function: Move memory area (handles overlapping regions) 41*b6cbf720SGianluca Guida * 42*b6cbf720SGianluca Guida * void *memmove(void * dest, const void * src, int n) 43*b6cbf720SGianluca Guida * 44*b6cbf720SGianluca Guida * Input: r3 - destination address 45*b6cbf720SGianluca Guida * r4 - source address 46*b6cbf720SGianluca Guida * r5 - byte count 47*b6cbf720SGianluca Guida * Output: r3 - destination address 48*b6cbf720SGianluca Guida * 49*b6cbf720SGianluca Guida * ========================================================================== 50*b6cbf720SGianluca Guida */ 51*b6cbf720SGianluca Guida 52*b6cbf720SGianluca Guida#include <machine/asm.h> 53*b6cbf720SGianluca Guida 54*b6cbf720SGianluca Guida .text 55*b6cbf720SGianluca Guida .align 4 56*b6cbf720SGianluca Guida#ifdef _BCOPY 57*b6cbf720SGianluca Guida/* bcopy = memcpy/memmove with arguments reversed. */ 58*b6cbf720SGianluca Guida/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */ 59*b6cbf720SGianluca GuidaENTRY(bcopy) 60*b6cbf720SGianluca Guida mr %r6, %r3 /* swap src/dst */ 61*b6cbf720SGianluca Guida mr %r3, %r4 62*b6cbf720SGianluca Guida mr %r4, %r6 63*b6cbf720SGianluca Guida#else 64*b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */ 65*b6cbf720SGianluca GuidaENTRY(memmove) 66*b6cbf720SGianluca Guida#endif 67*b6cbf720SGianluca Guida 68*b6cbf720SGianluca Guida mr %r8, %r3 /* Save dst (return value) */ 69*b6cbf720SGianluca Guida 70*b6cbf720SGianluca Guida cmpw %r4, %r8 /* Branch to reverse if */ 71*b6cbf720SGianluca Guida blt reverse /* src < dest. Don't want to */ 72*b6cbf720SGianluca Guida /* overwrite end of src with */ 73*b6cbf720SGianluca Guida /* start of dest */ 74*b6cbf720SGianluca Guida 75*b6cbf720SGianluca Guida addi %r4, %r4, -4 /* Back up src and dst pointers */ 76*b6cbf720SGianluca Guida addi %r8, %r8, -4 /* due to auto-update of 'load' */ 77*b6cbf720SGianluca Guida 78*b6cbf720SGianluca Guida srwi. %r9,%r5,2 /* How many words in total cnt */ 79*b6cbf720SGianluca Guida beq- last1 /* Handle byte by byte if < 4 */ 80*b6cbf720SGianluca Guida /* bytes total */ 81*b6cbf720SGianluca Guida mtctr %r9 /* Count of words for loop */ 82*b6cbf720SGianluca Guida lwzu %r7, 4(%r4) /* Preload first word */ 83*b6cbf720SGianluca Guida 84*b6cbf720SGianluca Guida b g1 85*b6cbf720SGianluca Guida 86*b6cbf720SGianluca Guidag0: /* Main loop */ 87*b6cbf720SGianluca Guida 88*b6cbf720SGianluca Guida lwzu %r7, 4(%r4) /* Load a new word */ 89*b6cbf720SGianluca Guida stwu %r6, 4(%r8) /* Store previous word */ 90*b6cbf720SGianluca Guida 91*b6cbf720SGianluca Guidag1: 92*b6cbf720SGianluca Guida 93*b6cbf720SGianluca Guida bdz- last /* Dec cnt, and branch if just */ 94*b6cbf720SGianluca Guida /* one word to store */ 95*b6cbf720SGianluca Guida lwzu %r6, 4(%r4) /* Load another word */ 96*b6cbf720SGianluca Guida stwu %r7, 4(%r8) /* Store previous word */ 97*b6cbf720SGianluca Guida bdnz+ g0 /* Dec cnt, and loop again if */ 98*b6cbf720SGianluca Guida /* more words */ 99*b6cbf720SGianluca Guida mr %r7, %r6 /* If word count -> 0, then... */ 100*b6cbf720SGianluca Guida 101*b6cbf720SGianluca Guidalast: 102*b6cbf720SGianluca Guida 103*b6cbf720SGianluca Guida stwu %r7, 4(%r8) /* ... store last word */ 104*b6cbf720SGianluca Guida 105*b6cbf720SGianluca Guidalast1: /* Byte-by-byte copy */ 106*b6cbf720SGianluca Guida 107*b6cbf720SGianluca Guida clrlwi. %r5,%r5,30 /* If count -> 0, then ... */ 108*b6cbf720SGianluca Guida beqlr /* we're done */ 109*b6cbf720SGianluca Guida 110*b6cbf720SGianluca Guida mtctr %r5 /* else load count for loop */ 111*b6cbf720SGianluca Guida 112*b6cbf720SGianluca Guida lbzu %r6, 4(%r4) /* 1st byte: update addr by 4 */ 113*b6cbf720SGianluca Guida stbu %r6, 4(%r8) /* since we pre-adjusted by 4 */ 114*b6cbf720SGianluca Guida bdzlr- /* in anticipation of main loop */ 115*b6cbf720SGianluca Guida 116*b6cbf720SGianluca Guidalast2: 117*b6cbf720SGianluca Guida 118*b6cbf720SGianluca Guida lbzu %r6, 1(%r4) /* But handle the rest by */ 119*b6cbf720SGianluca Guida stbu %r6, 1(%r8) /* updating addr by 1 */ 120*b6cbf720SGianluca Guida bdnz+ last2 121*b6cbf720SGianluca Guida 122*b6cbf720SGianluca Guida blr 123*b6cbf720SGianluca Guida 124*b6cbf720SGianluca Guida /* We're here since src < dest. Don't want to overwrite end of */ 125*b6cbf720SGianluca Guida /* src with start of dest */ 126*b6cbf720SGianluca Guida 127*b6cbf720SGianluca Guidareverse: 128*b6cbf720SGianluca Guida 129*b6cbf720SGianluca Guida add %r4, %r4, %r5 /* Work from end to beginning */ 130*b6cbf720SGianluca Guida add %r8, %r8, %r5 /* so add count to string ptrs */ 131*b6cbf720SGianluca Guida srwi. %r9,%r5,2 /* Words in total count */ 132*b6cbf720SGianluca Guida beq- rlast1 /* Handle byte by byte if < 4 */ 133*b6cbf720SGianluca Guida /* bytes total */ 134*b6cbf720SGianluca Guida 135*b6cbf720SGianluca Guida mtctr %r9 /* Count of words for loop */ 136*b6cbf720SGianluca Guida 137*b6cbf720SGianluca Guida lwzu %r7, -4(%r4) /* Preload first word */ 138*b6cbf720SGianluca Guida b rg1 139*b6cbf720SGianluca Guida 140*b6cbf720SGianluca Guidarg0: /* Main loop */ 141*b6cbf720SGianluca Guida 142*b6cbf720SGianluca Guida lwzu %r7, -4(%r4) /* Load a new word */ 143*b6cbf720SGianluca Guida stwu %r6, -4(%r8) /* Store previous word */ 144*b6cbf720SGianluca Guida 145*b6cbf720SGianluca Guidarg1: 146*b6cbf720SGianluca Guida 147*b6cbf720SGianluca Guida bdz- rlast /* Dec cnt, and branch if just */ 148*b6cbf720SGianluca Guida /* one word to store */ 149*b6cbf720SGianluca Guida 150*b6cbf720SGianluca Guida lwzu %r6, -4(%r4) /* Load another word */ 151*b6cbf720SGianluca Guida stwu %r7, -4(%r8) /* Store previous word */ 152*b6cbf720SGianluca Guida 153*b6cbf720SGianluca Guida bdnz+ rg0 /* Dec cnt, and loop again if */ 154*b6cbf720SGianluca Guida /* more words */ 155*b6cbf720SGianluca Guida 156*b6cbf720SGianluca Guida mr %r7, %r6 /* If word count -> 0, then... */ 157*b6cbf720SGianluca Guida 158*b6cbf720SGianluca Guidarlast: 159*b6cbf720SGianluca Guida 160*b6cbf720SGianluca Guida stwu %r7, -4(%r8) /* ... store last word */ 161*b6cbf720SGianluca Guida 162*b6cbf720SGianluca Guidarlast1: /* Byte-by-byte copy */ 163*b6cbf720SGianluca Guida 164*b6cbf720SGianluca Guida clrlwi. %r5,%r5,30 /* If count -> 0, then... */ 165*b6cbf720SGianluca Guida beqlr /* ... we're done */ 166*b6cbf720SGianluca Guida 167*b6cbf720SGianluca Guida mtctr %r5 /* else load count for loop */ 168*b6cbf720SGianluca Guida 169*b6cbf720SGianluca Guidarlast2: 170*b6cbf720SGianluca Guida 171*b6cbf720SGianluca Guida lbzu %r6, -1(%r4) /* Handle the rest, byte by */ 172*b6cbf720SGianluca Guida stbu %r6, -1(%r8) /* byte */ 173*b6cbf720SGianluca Guida 174*b6cbf720SGianluca Guida bdnz+ rlast2 /* Dec ctr, and branch if more */ 175*b6cbf720SGianluca Guida /* bytes left */ 176*b6cbf720SGianluca Guida blr 177*b6cbf720SGianluca Guida 178*b6cbf720SGianluca Guida#ifdef _BCOPY 179*b6cbf720SGianluca GuidaEND(bcopy) 180*b6cbf720SGianluca Guida#else 181*b6cbf720SGianluca GuidaEND(memmove) 182*b6cbf720SGianluca Guida#endif 183