Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / arc / lib / memcmp.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
4  */
5
6 #include <linux/linkage.h>
7
8 #ifdef __LITTLE_ENDIAN__
9 #define WORD2 r2
10 #define SHIFT r3
11 #else /* BIG ENDIAN */
12 #define WORD2 r3
13 #define SHIFT r2
14 #endif
15
16 ENTRY_CFI(memcmp)
17         or      r12,r0,r1
18         asl_s   r12,r12,30
19         sub     r3,r2,1
20         brls    r2,r12,.Lbytewise
21         ld      r4,[r0,0]
22         ld      r5,[r1,0]
23         lsr.f   lp_count,r3,3
24 #ifdef CONFIG_ISA_ARCV2
25         /* In ARCv2 a branch can't be the last instruction in a zero overhead
26          * loop.
27          * So we move the branch to the start of the loop, duplicate it
28          * after the end, and set up r12 so that the branch isn't taken
29          *  initially.
30          */
31         mov_s   r12,WORD2
32         lpne    .Loop_end
33         brne    WORD2,r12,.Lodd
34         ld      WORD2,[r0,4]
35 #else
36         lpne    .Loop_end
37         ld_s    WORD2,[r0,4]
38 #endif
39         ld_s    r12,[r1,4]
40         brne    r4,r5,.Leven
41         ld.a    r4,[r0,8]
42         ld.a    r5,[r1,8]
43 #ifdef CONFIG_ISA_ARCV2
44 .Loop_end:
45         brne    WORD2,r12,.Lodd
46 #else
47         brne    WORD2,r12,.Lodd
48 .Loop_end:
49 #endif
50         asl_s   SHIFT,SHIFT,3
51         bhs_s   .Last_cmp
52         brne    r4,r5,.Leven
53         ld      r4,[r0,4]
54         ld      r5,[r1,4]
55 #ifdef __LITTLE_ENDIAN__
56         nop_s
57         ; one more load latency cycle
58 .Last_cmp:
59         xor     r0,r4,r5
60         bset    r0,r0,SHIFT
61         sub_s   r1,r0,1
62         bic_s   r1,r1,r0
63         norm    r1,r1
64         b.d     .Leven_cmp
65         and     r1,r1,24
66 .Leven:
67         xor     r0,r4,r5
68         sub_s   r1,r0,1
69         bic_s   r1,r1,r0
70         norm    r1,r1
71         ; slow track insn
72         and     r1,r1,24
73 .Leven_cmp:
74         asl     r2,r4,r1
75         asl     r12,r5,r1
76         lsr_s   r2,r2,1
77         lsr_s   r12,r12,1
78         j_s.d   [blink]
79         sub     r0,r2,r12
80         .balign 4
81 .Lodd:
82         xor     r0,WORD2,r12
83         sub_s   r1,r0,1
84         bic_s   r1,r1,r0
85         norm    r1,r1
86         ; slow track insn
87         and     r1,r1,24
88         asl_s   r2,r2,r1
89         asl_s   r12,r12,r1
90         lsr_s   r2,r2,1
91         lsr_s   r12,r12,1
92         j_s.d   [blink]
93         sub     r0,r2,r12
94 #else /* BIG ENDIAN */
95 .Last_cmp:
96         neg_s   SHIFT,SHIFT
97         lsr     r4,r4,SHIFT
98         lsr     r5,r5,SHIFT
99         ; slow track insn
100 .Leven:
101         sub.f   r0,r4,r5
102         mov.ne  r0,1
103         j_s.d   [blink]
104         bset.cs r0,r0,31
105 .Lodd:
106         cmp_s   WORD2,r12
107         mov_s   r0,1
108         j_s.d   [blink]
109         bset.cs r0,r0,31
110 #endif /* ENDIAN */
111         .balign 4
112 .Lbytewise:
113         breq    r2,0,.Lnil
114         ldb     r4,[r0,0]
115         ldb     r5,[r1,0]
116         lsr.f   lp_count,r3
117 #ifdef CONFIG_ISA_ARCV2
118         mov     r12,r3
119         lpne    .Lbyte_end
120         brne    r3,r12,.Lbyte_odd
121 #else
122         lpne    .Lbyte_end
123 #endif
124         ldb_s   r3,[r0,1]
125         ldb     r12,[r1,1]
126         brne    r4,r5,.Lbyte_even
127         ldb.a   r4,[r0,2]
128         ldb.a   r5,[r1,2]
129 #ifdef CONFIG_ISA_ARCV2
130 .Lbyte_end:
131         brne    r3,r12,.Lbyte_odd
132 #else
133         brne    r3,r12,.Lbyte_odd
134 .Lbyte_end:
135 #endif
136         bcc     .Lbyte_even
137         brne    r4,r5,.Lbyte_even
138         ldb_s   r3,[r0,1]
139         ldb_s   r12,[r1,1]
140 .Lbyte_odd:
141         j_s.d   [blink]
142         sub     r0,r3,r12
143 .Lbyte_even:
144         j_s.d   [blink]
145         sub     r0,r4,r5
146 .Lnil:
147         j_s.d   [blink]
148         mov     r0,0
149 END_CFI(memcmp)