]>
Commit | Line | Data |
---|---|---|
3f0606ad | 1 | /* |
155fd766 | 2 | * File: memcpy.S |
3f0606ad | 3 | * |
155fd766 AL |
4 | * Copyright 2004-2007 Analog Devices Inc. |
5 | * Enter bugs at http://blackfin.uclinux.org/ | |
3f0606ad | 6 | * |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
3f0606ad | 8 | */ |
155fd766 | 9 | |
3f0606ad AL |
10 | .align 2 |
11 | ||
12 | .globl _memcpy_ASM; | |
5b22163f | 13 | .type _memcpy_ASM, STT_FUNC; |
3f0606ad AL |
14 | _memcpy_ASM: |
15 | CC = R2 <= 0; /* length not positive?*/ | |
16 | IF CC JUMP .L_P1L2147483647; /* Nothing to do */ | |
17 | ||
18 | P0 = R0 ; /* dst*/ | |
19 | P1 = R1 ; /* src*/ | |
20 | P2 = R2 ; /* length */ | |
21 | ||
22 | /* check for overlapping data */ | |
23 | CC = R1 < R0; /* src < dst */ | |
24 | IF !CC JUMP .Lno_overlap; | |
25 | R3 = R1 + R2; | |
26 | CC = R0 < R3; /* and dst < src+len */ | |
27 | IF CC JUMP .Lhas_overlap; | |
28 | ||
29 | .Lno_overlap: | |
30 | /* Check for aligned data.*/ | |
31 | ||
32 | R3 = R1 | R0; | |
33 | R0 = 0x3; | |
34 | R3 = R3 & R0; | |
35 | CC = R3; /* low bits set on either address? */ | |
36 | IF CC JUMP .Lnot_aligned; | |
37 | ||
38 | /* Both addresses are word-aligned, so we can copy | |
39 | at least part of the data using word copies.*/ | |
40 | P2 = P2 >> 2; | |
41 | CC = P2 <= 2; | |
42 | IF !CC JUMP .Lmore_than_seven; | |
43 | /* less than eight bytes... */ | |
44 | P2 = R2; | |
45 | LSETUP(.Lthree_start, .Lthree_end) LC0=P2; | |
46 | R0 = R1; /* setup src address for return */ | |
47 | .Lthree_start: | |
48 | R3 = B[P1++] (X); | |
49 | .Lthree_end: | |
50 | B[P0++] = R3; | |
51 | ||
52 | RTS; | |
53 | ||
54 | .Lmore_than_seven: | |
55 | /* There's at least eight bytes to copy. */ | |
56 | P2 += -1; /* because we unroll one iteration */ | |
57 | LSETUP(.Lword_loop, .Lword_loop) LC0=P2; | |
58 | R0 = R1; | |
59 | I1 = P1; | |
60 | R3 = [I1++]; | |
61 | .Lword_loop: | |
62 | MNOP || [P0++] = R3 || R3 = [I1++]; | |
63 | ||
64 | [P0++] = R3; | |
65 | /* Any remaining bytes to copy? */ | |
66 | R3 = 0x3; | |
67 | R3 = R2 & R3; | |
68 | CC = R3 == 0; | |
69 | P1 = I1; /* in case there's something left, */ | |
70 | IF !CC JUMP .Lbytes_left; | |
71 | RTS; | |
72 | .Lbytes_left: P2 = R3; | |
73 | .Lnot_aligned: | |
74 | /* From here, we're copying byte-by-byte. */ | |
75 | LSETUP (.Lbyte_start , .Lbyte_end) LC0=P2; | |
76 | R0 = R1; /* Save src address for return */ | |
77 | .Lbyte_start: | |
78 | R1 = B[P1++] (X); | |
79 | .Lbyte_end: | |
80 | B[P0++] = R1; | |
81 | ||
82 | .L_P1L2147483647: | |
83 | RTS; | |
84 | ||
85 | .Lhas_overlap: | |
86 | /* Need to reverse the copying, because the | |
87 | * dst would clobber the src. | |
88 | * Don't bother to work out alignment for | |
89 | * the reverse case. | |
90 | */ | |
91 | R0 = R1; /* save src for later. */ | |
92 | P0 = P0 + P2; | |
93 | P0 += -1; | |
94 | P1 = P1 + P2; | |
95 | P1 += -1; | |
96 | LSETUP(.Lover_start, .Lover_end) LC0=P2; | |
97 | .Lover_start: | |
98 | R1 = B[P1--] (X); | |
99 | .Lover_end: | |
100 | B[P0--] = R1; | |
101 | ||
102 | RTS; | |
5b22163f MF |
103 | |
104 | .size _memcpy_ASM, .-_memcpy_ASM |