1*0a6a1f1dSLionel Sambuc/* $NetBSD: memcpy.S,v 1.6 2014/03/04 17:05:14 macallan Exp $ */ 2b6cbf720SGianluca Guida 3b6cbf720SGianluca Guida/* stropt/memcpy_440.S, pl_string_common, pl_linux 10/11/04 11:45:36 4b6cbf720SGianluca Guida * ========================================================================== 5b6cbf720SGianluca Guida * Optimized memcpy implementation for IBM PowerPC 440. 6b6cbf720SGianluca Guida * 7b6cbf720SGianluca Guida * Copyright (c) 2003, IBM Corporation 8b6cbf720SGianluca Guida * All rights reserved. 9b6cbf720SGianluca Guida * 10b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or 11b6cbf720SGianluca Guida * without modification, are permitted provided that the following 12b6cbf720SGianluca Guida * conditions are met: 13b6cbf720SGianluca Guida * 14b6cbf720SGianluca Guida * * Redistributions of source code must retain the above 15b6cbf720SGianluca Guida * copyright notice, this list of conditions and the following 16b6cbf720SGianluca Guida * disclaimer. 17b6cbf720SGianluca Guida * * Redistributions in binary form must reproduce the above 18b6cbf720SGianluca Guida * copyright notice, this list of conditions and the following 19b6cbf720SGianluca Guida * disclaimer in the documentation and/or other materials 20b6cbf720SGianluca Guida * provided with the distribution. 21b6cbf720SGianluca Guida * * Neither the name of IBM nor the names of its contributors 22b6cbf720SGianluca Guida * may be used to endorse or promote products derived from this 23b6cbf720SGianluca Guida * software without specific prior written permission. 24b6cbf720SGianluca Guida * 25b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 26b6cbf720SGianluca Guida * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 27b6cbf720SGianluca Guida * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28b6cbf720SGianluca Guida * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29b6cbf720SGianluca Guida * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 30b6cbf720SGianluca Guida * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31b6cbf720SGianluca Guida * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32b6cbf720SGianluca Guida * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33b6cbf720SGianluca Guida * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 34b6cbf720SGianluca Guida * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35b6cbf720SGianluca Guida * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 36b6cbf720SGianluca Guida * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37b6cbf720SGianluca Guida * 38b6cbf720SGianluca Guida * ========================================================================== 39b6cbf720SGianluca Guida * 40b6cbf720SGianluca Guida * Function: Copy n bytes of the source to the destination. Behavior is 41b6cbf720SGianluca Guida * undefined for objects that overlap. 42b6cbf720SGianluca Guida * 43b6cbf720SGianluca Guida * 44b6cbf720SGianluca Guida * void *memcpy(void * dest, const void * src, int n) 45b6cbf720SGianluca Guida * 46b6cbf720SGianluca Guida * Input: r3 - destination address 47b6cbf720SGianluca Guida * r4 - source address 48b6cbf720SGianluca Guida * r5 - byte count 49b6cbf720SGianluca Guida * Output: r3 - destination address 50b6cbf720SGianluca Guida * 51b6cbf720SGianluca Guida * ========================================================================== 52b6cbf720SGianluca Guida */ 53b6cbf720SGianluca Guida 54b6cbf720SGianluca Guida#include <machine/asm.h> 55*0a6a1f1dSLionel Sambuc#ifdef _KERNEL_OPT 56*0a6a1f1dSLionel Sambuc#include "opt_ppcarch.h" 57*0a6a1f1dSLionel Sambuc#endif 58b6cbf720SGianluca Guida 59b6cbf720SGianluca Guida .text 60b6cbf720SGianluca Guida .align 4 61b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memcpy(void *, const void *, size_t) */ 62b6cbf720SGianluca GuidaENTRY(memcpy) 63b6cbf720SGianluca Guida /* 64b6cbf720SGianluca Guida * Check count passed in R5. If zero, return; otherwise continue. 65b6cbf720SGianluca Guida */ 66b6cbf720SGianluca Guida cmpwi %r5,0 67b6cbf720SGianluca Guida beqlr- 68b6cbf720SGianluca Guida 69*0a6a1f1dSLionel Sambuc#if defined(_KERNEL) && defined(PPC_OEA601) 70*0a6a1f1dSLionel Sambuc /* 71*0a6a1f1dSLionel Sambuc * 601 will generate alignment exceptions if operand crosses 72*0a6a1f1dSLionel Sambuc * 4k page boundary, so do byte copy when exception handler 73*0a6a1f1dSLionel Sambuc * not available. Maybe want to have a different memcpy for 601 74*0a6a1f1dSLionel Sambuc * that checks for page boundaries/word alignment... 75*0a6a1f1dSLionel Sambuc */ 76*0a6a1f1dSLionel Sambuc mfspr %r6, 287 /* mfpvbr %r6 PVR = 287 */ 77*0a6a1f1dSLionel Sambuc srwi %r6, %r6, 0x10 /* get version field from PVR */ 78*0a6a1f1dSLionel Sambuc cmpwi %r6, 0x1 /* 601 CPU = 0x0001 */ 79*0a6a1f1dSLionel Sambuc bne bnorm /* skip byte-only unless 601 */ 80*0a6a1f1dSLionel Sambuc 81*0a6a1f1dSLionel Sambuc or %r6, %r3, %r4 /* see if both source and dest */ 82*0a6a1f1dSLionel Sambuc andi. %r6, %r6, 3 /* are 32bit aligned */ 83*0a6a1f1dSLionel Sambuc beq bnorm /* skip byte-only if they are */ 84*0a6a1f1dSLionel Sambucbcpy: 85*0a6a1f1dSLionel Sambuc mtctr %r5 /* byte copy everything */ 86*0a6a1f1dSLionel Sambuc li %r6, 0 87*0a6a1f1dSLionel Sambucbloop: 88*0a6a1f1dSLionel Sambuc lbzx %r7, %r4, %r6 89*0a6a1f1dSLionel Sambuc stbx %r7, %r3, %r6 90*0a6a1f1dSLionel Sambuc addi %r6, %r6, 1 91*0a6a1f1dSLionel Sambuc bdnz bloop 92*0a6a1f1dSLionel Sambuc blr 93*0a6a1f1dSLionel Sambuc 94*0a6a1f1dSLionel Sambucbnorm: 95*0a6a1f1dSLionel Sambuc 96*0a6a1f1dSLionel Sambuc#endif 97*0a6a1f1dSLionel Sambuc 98b6cbf720SGianluca Guida mr %r8, %r3 /* Copy dst (return value) */ 99b6cbf720SGianluca Guida 100b6cbf720SGianluca Guida addi %r4, %r4, -4 /* Prepare for main loop's auto */ 101b6cbf720SGianluca Guida addi %r8, %r8, -4 /* update */ 102b6cbf720SGianluca Guida 103b6cbf720SGianluca Guida srwi. %r9,%r5,2 /* Word count -> r9 */ 104b6cbf720SGianluca Guida beq- last1 /* Partial copy if <4 bytes */ 105b6cbf720SGianluca Guida 106b6cbf720SGianluca Guida mtctr %r9 /* Word cnt in CTR for loop */ 107b6cbf720SGianluca Guida lwzu %r7, 4(%r4) /* Preload for main loop */ 108b6cbf720SGianluca Guida 109b6cbf720SGianluca Guida b g1 110b6cbf720SGianluca Guida 111b6cbf720SGianluca Guidag0: /* Main loop */ 112b6cbf720SGianluca Guida 113b6cbf720SGianluca Guida lwzu %r7, 4(%r4) /* Load a new word */ 114b6cbf720SGianluca Guida stwu %r6, 4(%r8) /* Store previous word */ 115b6cbf720SGianluca Guida 116b6cbf720SGianluca Guidag1: 117b6cbf720SGianluca Guida 118b6cbf720SGianluca Guida bdz- last /* Dec ctr and exit loop if no */ 119b6cbf720SGianluca Guida /* more words */ 120b6cbf720SGianluca Guida lwzu %r6, 4(%r4) /* Load another word */ 121b6cbf720SGianluca Guida stwu %r7, 4(%r8) /* Store previous word */ 122b6cbf720SGianluca Guida bdnz+ g0 /* Dec ctr and continue loop if */ 123b6cbf720SGianluca Guida /* more words */ 124b6cbf720SGianluca Guida 125b6cbf720SGianluca Guida mr %r7, %r6 126b6cbf720SGianluca Guida 127b6cbf720SGianluca Guidalast: 128b6cbf720SGianluca Guida 129b6cbf720SGianluca Guida stwu %r7, 4(%r8) /* Store last word */ 130b6cbf720SGianluca Guida 131b6cbf720SGianluca Guidalast1: /* Byte-by-byte copy */ 132b6cbf720SGianluca Guida 133b6cbf720SGianluca Guida clrlwi. %r5,%r5,30 134b6cbf720SGianluca Guida beqlr 135b6cbf720SGianluca Guida 136b6cbf720SGianluca Guida mtctr %r5 137b6cbf720SGianluca Guida 138b6cbf720SGianluca Guida lbzu %r6, 4(%r4) /* 1st byte: update by word */ 139b6cbf720SGianluca Guida stbu %r6, 4(%r8) 140b6cbf720SGianluca Guida bdzlr- 141b6cbf720SGianluca Guida 142b6cbf720SGianluca Guidalast2: 143b6cbf720SGianluca Guida 144b6cbf720SGianluca Guida lbzu %r6, 1(%r4) /* Handle the rest */ 145b6cbf720SGianluca Guida stbu %r6, 1(%r8) 146b6cbf720SGianluca Guida bdnz+ last2 147b6cbf720SGianluca Guida 148b6cbf720SGianluca Guida blr 149b6cbf720SGianluca GuidaEND(memcpy) 150