1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * internal version of memcpy(), issued by the compiler to copy blocks of 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * data around. This is really memmove() - it has to be able to deal with 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * possible overlaps, because that ambiguity is when the compiler gives up 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * and calls a function. We have our own, internal version so that we get 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * something we trust, even if the user has redefined the normal symbol. 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Copyright 2004-2009 Analog Devices Inc. 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Licensed under the Clear BSD license or the GPL-2 (or later) 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <linux/linkage.h> 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* void *memcpy(void *dest, const void *src, size_t n); 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * R0 = To Address (dest) (leave unchanged to form result) 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * R1 = From Address (src) 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * R2 = count 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Note: Favours word alignment 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#ifdef CONFIG_MEMCPY_L1 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.section .l1.text 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#else 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.text 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#endif 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.align 2 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen ChengENTRY(_memcpy) 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng CC = R2 <= 0; /* length not positive? */ 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng IF CC JUMP .L_P1L2147483647; /* Nothing to do */ 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P0 = R0 ; /* dst*/ 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P1 = R1 ; /* src*/ 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P2 = R2 ; /* length */ 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* check for overlapping data */ 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng CC = R1 < R0; /* src < dst */ 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng IF !CC JUMP .Lno_overlap; 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = R1 + R2; 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng CC = R0 < R3; /* and dst < src+len */ 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng IF CC JUMP .Lhas_overlap; 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lno_overlap: 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Check for aligned data.*/ 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = R1 | R0; 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R1 = 0x3; 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = R3 & R1; 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng CC = R3; /* low bits set on either address? */ 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng IF CC JUMP .Lnot_aligned; 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Both addresses are word-aligned, so we can copy 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng at least part of the data using word copies.*/ 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P2 = P2 >> 2; 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng CC = P2 <= 2; 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng IF !CC JUMP .Lmore_than_seven; 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* less than eight bytes... */ 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P2 = R2; 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng LSETUP(.Lthree_start, .Lthree_end) LC0=P2; 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lthree_start: 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = B[P1++] (X); 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lthree_end: 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng B[P0++] = R3; 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng RTS; 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lmore_than_seven: 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* There's at least eight bytes to copy. */ 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P2 += -1; /* because we unroll one iteration */ 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng LSETUP(.Lword_loops, .Lword_loope) LC0=P2; 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng I1 = P1; 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = [I1++]; 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#if ANOMALY_05000202 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lword_loops: 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng [P0++] = R3; 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lword_loope: 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = [I1++]; 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#else 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lword_loops: 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lword_loope: 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng MNOP || [P0++] = R3 || R3 = [I1++]; 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#endif 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng [P0++] = R3; 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Any remaining bytes to copy? */ 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = 0x3; 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R3 = R2 & R3; 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng CC = R3 == 0; 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P1 = I1; /* in case there's something left, */ 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng IF !CC JUMP .Lbytes_left; 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng RTS; 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lbytes_left: P2 = R3; 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lnot_aligned: 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* From here, we're copying byte-by-byte. */ 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng LSETUP (.Lbyte_start, .Lbyte_end) LC0=P2; 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lbyte_start: 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R1 = B[P1++] (X); 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lbyte_end: 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng B[P0++] = R1; 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.L_P1L2147483647: 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng RTS; 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lhas_overlap: 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Need to reverse the copying, because the 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * dst would clobber the src. 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Don't bother to work out alignment for 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * the reverse case. 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P0 = P0 + P2; 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P0 += -1; 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P1 = P1 + P2; 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng P1 += -1; 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng LSETUP(.Lover_start, .Lover_end) LC0=P2; 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lover_start: 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng R1 = B[P1--] (X); 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng.Lover_end: 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng B[P0--] = R1; 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng RTS; 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen ChengENDPROC(_memcpy) 125