1*1890dda8Smacallan/* $NetBSD: memcpy.S,v 1.6 2014/03/04 17:05:14 macallan Exp $ */ 22ba84f0fSgarbled 32ba84f0fSgarbled/* stropt/memcpy_440.S, pl_string_common, pl_linux 10/11/04 11:45:36 42ba84f0fSgarbled * ========================================================================== 52ba84f0fSgarbled * Optimized memcpy implementation for IBM PowerPC 440. 62ba84f0fSgarbled * 72ba84f0fSgarbled * Copyright (c) 2003, IBM Corporation 82ba84f0fSgarbled * All rights reserved. 92ba84f0fSgarbled * 102ba84f0fSgarbled * Redistribution and use in source and binary forms, with or 112ba84f0fSgarbled * without modification, are permitted provided that the following 122ba84f0fSgarbled * conditions are met: 132ba84f0fSgarbled * 142ba84f0fSgarbled * * Redistributions of source code must retain the above 152ba84f0fSgarbled * copyright notice, this list of conditions and the following 162ba84f0fSgarbled * disclaimer. 172ba84f0fSgarbled * * Redistributions in binary form must reproduce the above 182ba84f0fSgarbled * copyright notice, this list of conditions and the following 192ba84f0fSgarbled * disclaimer in the documentation and/or other materials 202ba84f0fSgarbled * provided with the distribution. 212ba84f0fSgarbled * * Neither the name of IBM nor the names of its contributors 222ba84f0fSgarbled * may be used to endorse or promote products derived from this 232ba84f0fSgarbled * software without specific prior written permission. 242ba84f0fSgarbled * 252ba84f0fSgarbled * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 262ba84f0fSgarbled * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 272ba84f0fSgarbled * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 282ba84f0fSgarbled * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 292ba84f0fSgarbled * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 302ba84f0fSgarbled * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 312ba84f0fSgarbled * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 322ba84f0fSgarbled * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 332ba84f0fSgarbled * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 342ba84f0fSgarbled * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 352ba84f0fSgarbled * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 362ba84f0fSgarbled * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 372ba84f0fSgarbled * 382ba84f0fSgarbled * ========================================================================== 392ba84f0fSgarbled * 402ba84f0fSgarbled * Function: Copy n bytes of the source to the destination. Behavior is 412ba84f0fSgarbled * undefined for objects that overlap. 422ba84f0fSgarbled * 432ba84f0fSgarbled * 442ba84f0fSgarbled * void *memcpy(void * dest, const void * src, int n) 452ba84f0fSgarbled * 462ba84f0fSgarbled * Input: r3 - destination address 472ba84f0fSgarbled * r4 - source address 482ba84f0fSgarbled * r5 - byte count 492ba84f0fSgarbled * Output: r3 - destination address 502ba84f0fSgarbled * 512ba84f0fSgarbled * ========================================================================== 522ba84f0fSgarbled */ 532ba84f0fSgarbled 542ba84f0fSgarbled#include <machine/asm.h> 55f3eefe6cSmatt#ifdef _KERNEL_OPT 56a00f9ab0Smacallan#include "opt_ppcarch.h" 57a00f9ab0Smacallan#endif 582ba84f0fSgarbled 592ba84f0fSgarbled .text 602ba84f0fSgarbled .align 4 612ba84f0fSgarbled/* LINTSTUB: Func: void *memcpy(void *, const void *, size_t) */ 622ba84f0fSgarbledENTRY(memcpy) 632ba84f0fSgarbled /* 642ba84f0fSgarbled * Check count passed in R5. If zero, return; otherwise continue. 652ba84f0fSgarbled */ 662ba84f0fSgarbled cmpwi %r5,0 672ba84f0fSgarbled beqlr- 682ba84f0fSgarbled 69a00f9ab0Smacallan#if defined(_KERNEL) && defined(PPC_OEA601) 70a00f9ab0Smacallan /* 71a00f9ab0Smacallan * 601 will generate alignment exceptions if operand crosses 72a00f9ab0Smacallan * 4k page boundary, so do byte copy when exception handler 73a00f9ab0Smacallan * not available. Maybe want to have a different memcpy for 601 74a00f9ab0Smacallan * that checks for page boundaries/word alignment... 75a00f9ab0Smacallan */ 76a00f9ab0Smacallan mfspr %r6, 287 /* mfpvbr %r6 PVR = 287 */ 77a00f9ab0Smacallan srwi %r6, %r6, 0x10 /* get version field from PVR */ 78a00f9ab0Smacallan cmpwi %r6, 0x1 /* 601 CPU = 0x0001 */ 79a00f9ab0Smacallan bne bnorm /* skip byte-only unless 601 */ 80a00f9ab0Smacallan 81*1890dda8Smacallan or %r6, %r3, %r4 /* see if both source and dest */ 82*1890dda8Smacallan andi. %r6, %r6, 3 /* are 32bit aligned */ 83*1890dda8Smacallan beq bnorm /* skip byte-only if they are */ 84a00f9ab0Smacallanbcpy: 85a00f9ab0Smacallan mtctr %r5 /* byte copy everything */ 86a00f9ab0Smacallan li %r6, 0 87a00f9ab0Smacallanbloop: 88a00f9ab0Smacallan lbzx %r7, %r4, %r6 89a00f9ab0Smacallan stbx %r7, %r3, %r6 90a00f9ab0Smacallan addi %r6, %r6, 1 91a00f9ab0Smacallan bdnz bloop 92a00f9ab0Smacallan blr 93a00f9ab0Smacallan 94a00f9ab0Smacallanbnorm: 95a00f9ab0Smacallan 96a00f9ab0Smacallan#endif 97a00f9ab0Smacallan 982ba84f0fSgarbled mr %r8, %r3 /* Copy dst (return value) */ 992ba84f0fSgarbled 1002ba84f0fSgarbled addi %r4, %r4, -4 /* Prepare for main loop's auto */ 1012ba84f0fSgarbled addi %r8, %r8, -4 /* update */ 1022ba84f0fSgarbled 1032ba84f0fSgarbled srwi. %r9,%r5,2 /* Word count -> r9 */ 1042ba84f0fSgarbled beq- last1 /* Partial copy if <4 bytes */ 1052ba84f0fSgarbled 1062ba84f0fSgarbled mtctr %r9 /* Word cnt in CTR for loop */ 1072ba84f0fSgarbled lwzu %r7, 4(%r4) /* Preload for main loop */ 1082ba84f0fSgarbled 1092ba84f0fSgarbled b g1 1102ba84f0fSgarbled 1112ba84f0fSgarbledg0: /* Main loop */ 1122ba84f0fSgarbled 1132ba84f0fSgarbled lwzu %r7, 4(%r4) /* Load a new word */ 1142ba84f0fSgarbled stwu %r6, 4(%r8) /* Store previous word */ 1152ba84f0fSgarbled 1162ba84f0fSgarbledg1: 1172ba84f0fSgarbled 1182ba84f0fSgarbled bdz- last /* Dec ctr and exit loop if no */ 1192ba84f0fSgarbled /* more words */ 1202ba84f0fSgarbled lwzu %r6, 4(%r4) /* Load another word */ 1212ba84f0fSgarbled stwu %r7, 4(%r8) /* Store previous word */ 1222ba84f0fSgarbled bdnz+ g0 /* Dec ctr and continue loop if */ 1232ba84f0fSgarbled /* more words */ 1242ba84f0fSgarbled 1252ba84f0fSgarbled mr %r7, %r6 1262ba84f0fSgarbled 1272ba84f0fSgarbledlast: 1282ba84f0fSgarbled 1292ba84f0fSgarbled stwu %r7, 4(%r8) /* Store last word */ 1302ba84f0fSgarbled 1312ba84f0fSgarbledlast1: /* Byte-by-byte copy */ 1322ba84f0fSgarbled 1332ba84f0fSgarbled clrlwi. %r5,%r5,30 1342ba84f0fSgarbled beqlr 1352ba84f0fSgarbled 1362ba84f0fSgarbled mtctr %r5 1372ba84f0fSgarbled 1382ba84f0fSgarbled lbzu %r6, 4(%r4) /* 1st byte: update by word */ 1392ba84f0fSgarbled stbu %r6, 4(%r8) 1402ba84f0fSgarbled bdzlr- 1412ba84f0fSgarbled 1422ba84f0fSgarbledlast2: 1432ba84f0fSgarbled 1442ba84f0fSgarbled lbzu %r6, 1(%r4) /* Handle the rest */ 1452ba84f0fSgarbled stbu %r6, 1(%r8) 1462ba84f0fSgarbled bdnz+ last2 1472ba84f0fSgarbled 1482ba84f0fSgarbled blr 149cf88c389SmattEND(memcpy) 150