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