blob: 55fcc9fb00edfae1dc2b0b0e746559cd128c09a8 [file] [log] [blame]
Alexey Brodkinb628c012014-02-04 12:56:15 +04001/*
2 * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7/*
8 * ARC700 has a relatively long pipeline and branch prediction, so we want
9 * to avoid branches that are hard to predict. On the other hand, the
10 * presence of the norm instruction makes it easier to operate on whole
11 * words branch-free.
12 */
13
14.global strchr
15.align 4
16strchr:
17 extb_s %r1, %r1
18 asl %r5, %r1, 8
19 bmsk %r2, %r0, 1
20 or %r5, %r5, %r1
21 mov_s %r3, 0x01010101
22 breq.d %r2, %r0, .Laligned
23 asl %r4, %r5, 16
24 sub_s %r0, %r0, %r2
25 asl %r7, %r2, 3
26 ld_s %r2, [%r0]
27#ifdef __LITTLE_ENDIAN__
28 asl %r7, %r3, %r7
29#else /* __BIG_ENDIAN__ */
30 lsr %r7, %r3, %r7
31#endif /* _ENDIAN__ */
32 or %r5, %r5, %r4
33 ror %r4, %r3
34 sub %r12, %r2, %r7
35 bic_s %r12, %r12, %r2
36 and %r12, %r12, %r4
37 brne.d %r12, 0, .Lfound0_ua
38 xor %r6, %r2, %r5
39 ld.a %r2, [%r0, 4]
40 sub %r12, %r6, %r7
41 bic %r12, %r12, %r6
42#ifdef __LITTLE_ENDIAN__
43 and %r7, %r12, %r4
44 /* For speed, we want this branch to be unaligned. */
45 breq %r7, 0, .Loop
46 /* Likewise this one */
47 b .Lfound_char
48#else /* __BIG_ENDIAN__ */
49 and %r12, %r12, %r4
50 /* For speed, we want this branch to be unaligned. */
51 breq %r12, 0, .Loop
52 lsr_s %r12, %r12, 7
53 bic %r2, %r7, %r6
54 b.d .Lfound_char_b
55 and_s %r2, %r2, %r12
56#endif /* _ENDIAN__ */
57 /* We require this code address to be unaligned for speed... */
58.Laligned:
59 ld_s %r2, [%r0]
60 or %r5, %r5, %r4
61 ror %r4, %r3
62 /* ... so that this code address is aligned, for itself and ... */
63.Loop:
64 sub %r12, %r2, %r3
65 bic_s %r12, %r12, %r2
66 and %r12, %r12, %r4
67 brne.d %r12, 0, .Lfound0
68 xor %r6, %r2, %r5
69 ld.a %r2, [%r0, 4]
70 sub %r12, %r6, %r3
71 bic %r12, %r12, %r6
72 and %r7, %r12, %r4
73 breq %r7, 0, .Loop
74 /*
75 *... so that this branch is unaligned.
76 * Found searched-for character.
77 * r0 has already advanced to next word.
78 */
79#ifdef __LITTLE_ENDIAN__
80 /*
81 * We only need the information about the first matching byte
82 * (i.e. the least significant matching byte) to be exact,
83 * hence there is no problem with carry effects.
84 */
85.Lfound_char:
86 sub %r3, %r7, 1
87 bic %r3, %r3, %r7
88 norm %r2, %r3
89 sub_s %r0, %r0, 1
90 asr_s %r2, %r2, 3
91 j.d [%blink]
92 sub_s %r0, %r0, %r2
93
94 .balign 4
95.Lfound0_ua:
96 mov %r3, %r7
97.Lfound0:
98 sub %r3, %r6, %r3
99 bic %r3, %r3, %r6
100 and %r2, %r3, %r4
101 or_s %r12, %r12, %r2
102 sub_s %r3, %r12, 1
103 bic_s %r3, %r3, %r12
104 norm %r3, %r3
105 add_s %r0, %r0, 3
106 asr_s %r12, %r3, 3
107 asl.f 0, %r2, %r3
108 sub_s %r0, %r0, %r12
109 j_s.d [%blink]
110 mov.pl %r0, 0
111#else /* __BIG_ENDIAN__ */
112.Lfound_char:
113 lsr %r7, %r7, 7
114
115 bic %r2, %r7, %r6
116.Lfound_char_b:
117 norm %r2, %r2
118 sub_s %r0, %r0, 4
119 asr_s %r2, %r2, 3
120 j.d [%blink]
121 add_s %r0, %r0, %r2
122
123.Lfound0_ua:
124 mov_s %r3, %r7
125.Lfound0:
126 asl_s %r2, %r2, 7
127 or %r7, %r6, %r4
128 bic_s %r12, %r12, %r2
129 sub %r2, %r7, %r3
130 or %r2, %r2, %r6
131 bic %r12, %r2, %r12
132 bic.f %r3, %r4, %r12
133 norm %r3, %r3
134
135 add.pl %r3, %r3, 1
136 asr_s %r12, %r3, 3
137 asl.f 0, %r2, %r3
138 add_s %r0, %r0, %r12
139 j_s.d [%blink]
140 mov.mi %r0, 0
141#endif /* _ENDIAN__ */