Merge with git://www.denx.de/git/u-boot.git#testing-USB
[platform/kernel/u-boot.git] / lib_blackfin / memmove.S
1 /*
2  * File:         arch/blackfin/lib/memmove.S
3  * Based on:
4  * Author:
5  *
6  * Created:
7  * Description:
8  *
9  * Rev:          $Id: memmove.S 2205 2006-09-23 07:53:49Z vapier $
10  *
11  * Modified:
12  *               Copyright 2004-2006 Analog Devices Inc.
13  *
14  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see the file COPYING, or write
28  * to the Free Software Foundation, Inc.,
29  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 .align 2
33
34 /*
35  * C Library function MEMMOVE
36  * R0 = To Address (leave unchanged to form result)
37  * R1 = From Address
38  * R2 = count
39  * Data may overlap
40  */
41
42 .globl _memmove;
43 _memmove:
44         I1 = P3;
45         P0 = R0;                  /* P0 = To address */
46         P3 = R1;                  /* P3 = From Address */
47         P2 = R2 ;                 /* P2 = count */
48         CC = P2 == 0;             /* Check zero count*/
49         IF CC JUMP .Lfinished;    /* very unlikely */
50
51         CC = R1 < R0 (IU);        /* From < To */
52         IF !CC JUMP .Lno_overlap;
53         R3 = R1 + R2;
54         CC = R0 <= R3 (IU);       /* (From+len) >= To */
55         IF CC JUMP .Loverlap;
56 .Lno_overlap:
57         R3 = 11;
58         CC = R2 <= R3;
59         IF CC JUMP  .Lbytes;
60         R3 = R1 | R0;             /* OR addresses together */
61         R3 <<= 30;                /* check bottom two bits */
62         CC =  AZ;                 /* AZ set if zero.*/
63         IF !CC JUMP  .Lbytes ;    /* Jump if addrs not aligned.*/
64
65         I0 = P3;
66         P1 = P2 >> 2;             /* count = n/4 */
67         P1 += -1;
68         R3 =  3;
69         R2 = R2 & R3;             /* remainder */
70         P2 = R2;                  /* set remainder */
71         R1 = [I0++];
72
73         LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1;
74 .Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++];
75         [P0++] = R1;
76
77         CC = P2 == 0;             /* any remaining bytes? */
78         P3 = I0;                  /* Ammend P3 to updated ptr. */
79         IF !CC JUMP .Lbytes;
80         P3 = I1;
81         RTS;
82
83 .Lbytes:     LSETUP (.Lbyte2_s , .Lbyte2_e) LC0=P2;
84 .Lbyte2_s:   R1 = B[P3++](Z);
85 .Lbyte2_e:   B[P0++] = R1;
86
87 .Lfinished:  P3 = I1;
88         RTS;
89
90 .Loverlap:
91         P2 += -1;
92         P0 = P0 + P2;
93         P3 = P3 + P2;
94         R1 = B[P3--] (Z);
95         CC = P2 == 0;
96         IF CC JUMP .Lno_loop;
97         LSETUP (.Lol_s, .Lol_e) LC0 = P2;
98 .Lol_s:    B[P0--] = R1;
99 .Lol_e:    R1 = B[P3--] (Z);
100 .Lno_loop: B[P0] = R1;
101         P3 = I1;
102         RTS;