Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
5210d1e6 VG |
2 | /* |
3 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | |
5210d1e6 VG |
4 | */ |
5 | ||
ec7ac6af | 6 | #include <linux/linkage.h> |
5210d1e6 VG |
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 | ||
86effd0d | 16 | ENTRY_CFI(memcmp) |
5210d1e6 VG |
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 | |
8922bc30 VG |
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 | |
5210d1e6 VG |
36 | lpne .Loop_end |
37 | ld_s WORD2,[r0,4] | |
8922bc30 | 38 | #endif |
5210d1e6 VG |
39 | ld_s r12,[r1,4] |
40 | brne r4,r5,.Leven | |
41 | ld.a r4,[r0,8] | |
42 | ld.a r5,[r1,8] | |
8922bc30 VG |
43 | #ifdef CONFIG_ISA_ARCV2 |
44 | .Loop_end: | |
45 | brne WORD2,r12,.Lodd | |
46 | #else | |
5210d1e6 VG |
47 | brne WORD2,r12,.Lodd |
48 | .Loop_end: | |
8922bc30 | 49 | #endif |
5210d1e6 VG |
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 | |
5210d1e6 VG |
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 | |
8922bc30 VG |
117 | #ifdef CONFIG_ISA_ARCV2 |
118 | mov r12,r3 | |
5210d1e6 | 119 | lpne .Lbyte_end |
8922bc30 VG |
120 | brne r3,r12,.Lbyte_odd |
121 | #else | |
122 | lpne .Lbyte_end | |
123 | #endif | |
5210d1e6 VG |
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] | |
8922bc30 VG |
129 | #ifdef CONFIG_ISA_ARCV2 |
130 | .Lbyte_end: | |
131 | brne r3,r12,.Lbyte_odd | |
132 | #else | |
5210d1e6 VG |
133 | brne r3,r12,.Lbyte_odd |
134 | .Lbyte_end: | |
8922bc30 | 135 | #endif |
5210d1e6 VG |
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 | |
86effd0d | 149 | END_CFI(memcmp) |