blackfin architecture
[linux-2.6.git] / arch / blackfin / lib / memcmp.S
1 /*
2  * File:         arch/blackfin/lib/memcmp.S
3  * Based on:
4  * Author:
5  *
6  * Created:
7  * Description:
8  *
9  * Modified:
10  *               Copyright 2004-2006 Analog Devices Inc.
11  *
12  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, see the file COPYING, or write
26  * to the Free Software Foundation, Inc.,
27  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29
30 #include <linux/linkage.h>
31
32 /* int memcmp(const void *s1, const void *s2, size_t n);
33  * R0 = First Address (s1)
34  * R1 = Second Address (s2)
35  * R2 = count (n)
36  *
37  * Favours word aligned data.
38  */
39
40 .text
41
42 .align 2
43
44 ENTRY(_memcmp)
45         I1 = P3;
46         P0 = R0;                        /* P0 = s1 address */
47         P3 = R1;                        /* P3 = s2 Address  */
48         P2 = R2 ;                       /* P2 = count */
49         CC = R2 <= 7(IU);
50         IF CC JUMP .Ltoo_small;
51         I0 = R1;                        /* s2 */
52         R1 = R1 | R0;           /* OR addresses together */
53         R1 <<= 30;              /* check bottom two bits */
54         CC =  AZ;                       /* AZ set if zero. */
55         IF !CC JUMP .Lbytes ;   /* Jump if addrs not aligned. */
56
57         P1 = P2 >> 2;           /* count = n/4 */
58         R3 =  3;
59         R2 = R2 & R3;           /* remainder */
60         P2 = R2;                        /* set remainder */
61
62         LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1;
63 .Lquad_loop_s:
64         MNOP || R0 = [P0++] || R1 = [I0++];
65         CC = R0 == R1;
66         IF !CC JUMP .Lquad_different;
67 .Lquad_loop_e:
68         NOP;
69
70         P3 = I0;                        /* s2 */
71 .Ltoo_small:
72         CC = P2 == 0;           /* Check zero count*/
73         IF CC JUMP .Lfinished;  /* very unlikely*/
74
75 .Lbytes:
76         LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2;
77 .Lbyte_loop_s:
78         R1 = B[P3++](Z);        /* *s2 */
79         R0 = B[P0++](Z);        /* *s1 */
80         CC = R0 == R1;
81         IF !CC JUMP .Ldifferent;
82 .Lbyte_loop_e:
83         NOP;
84
85 .Ldifferent:
86         R0 = R0 - R1;
87         P3 = I1;
88         RTS;
89
90 .Lquad_different:
91         /* We've read two quads which don't match.
92          * Can't just compare them, because we're
93          * a little-endian machine, so the MSBs of
94          * the regs occur at later addresses in the
95          * string.
96          * Arrange to re-read those two quads again,
97          * byte-by-byte.
98          */
99         P0 += -4;               /* back up to the start of the */
100         P3 = I0;                /* quads, and increase the*/
101         P2 += 4;                /* remainder count*/
102         P3 += -4;
103         JUMP .Lbytes;
104
105 .Lfinished:
106         R0 = 0;
107         P3 = I1;
108         RTS;
109
110 .size _memcmp,.-_memcmp