Cygwin: Add new APIs tc[gs]etwinsize()
[newlib-cygwin.git] / newlib / libc / machine / arc / strchr-bs.S
blob125d1f7718627f109af7ff5699c651af1208fcd9
1 /*
2    Copyright (c) 2015-2024, Synopsys, Inc. All rights reserved.
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions are met:
7    1) Redistributions of source code must retain the above copyright notice,
8    this list of conditions and the following disclaimer.
10    2) Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
14    3) Neither the name of the Synopsys, Inc., nor the names of its contributors
15    may be used to endorse or promote products derived from this software
16    without specific prior written permission.
18    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28    POSSIBILITY OF SUCH DAMAGE.
31 /* This implementation is optimized for performance.  For code size a generic
32    implementation of this function from newlib/libc/string/strchr.c will be
33    used.  */
34 #if !defined (__OPTIMIZE_SIZE__) && !defined (PREFER_SIZE_OVER_SPEED) \
35     && !defined (__ARC_RF16__)
37 #include "asm.h"
39 /* In order to search for a zero in a W, we calculate
40    X := (W - 0x01010101) & ~W & 0x80808080;
41    In the little endian case:
42      If no byte in W is zero, X will be zero; otherwise, the least significant
43      byte of X which is nonzero indicates the least significant byte of W that
44      is zero.
45    In the big endian case:
46      X will be zero iff no byte in W is zero.
47      If X is nonzero, to find out which is the most significant zero byte
48      in W, we calculate:
49      Y := ~(((W | 0x80808080) - 0x01010101) | W) & 0x80808080;
50      Each byte in Y is 0x80 if the the corresponding byte in
51      W is zero, otherwise that byte of Y is 0.  */
53 #if defined (__ARC_BARREL_SHIFTER__) && \
54    (defined (__ARC600__) || (!defined (__ARC_NORM__) && !defined (__ARC601__)))
56 ENTRY (strchr)
57         bmsk.f  r2,r0,1
58         mov_s   r3,0x01010101
59         extb_s  r1,r1
60         asl     r5,r1,8
61         or      r5,r5,r1
62         beq.d   .Laligned
63         asl     r4,r5,16
64         sub_s   r0,r0,r2
65         asl_s   r2,r2,3
66 #ifdef  __LITTLE_ENDIAN__
67         asl     r7,r3,r2
68 #else
69         lsr     r7,r3,r2
70 #endif
71         ld_s    r2,[r0]
72         or      r5,r5,r4
73         ror     r4,r3
74         sub     r12,r2,r7
75         bic_s   r12,r12,r2
76         and     r12,r12,r4
78         brne.d  r12,0,.Lfound0_ua
79         xor     r6,r2,r5
80         ld.a    r2,[r0,4]
81         sub     r12,r6,r7
82         bic     r12,r12,r6
83 #ifdef __LITTLE_ENDIAN__
84         and.f   r7,r12,r4
85         sub     r12,r2,r3
86         bic_s   r12,r12,r2
87         beq.d   .Loop
88         and     r12,r12,r4
89         b.d     .Lfound_char_ua
90         btst    r7,7
91 #else
92         and.f   r8,r12,r4
93         sub     r12,r2,r3
94         bic_s   r12,r12,r2
95         beq.d   .Loop
96         and     r12,r12,r4
97         bic     r12,r7,r6
98         asl_s   r12,r12,7
99         and.f   r2,r8,r12
100         b.d     .Lfound_char_ua
101         sub_s   r0,r0,4
102 #endif
104         .balign 4
105 .Laligned:
106         ld_s    r2,[r0]
107         or      r5,r5,r4
108         ror     r4,r3
109         sub     r12,r2,r3
110         bic_s   r12,r12,r2
111         and     r12,r12,r4
112 .Loop:
114         brne.d  r12,0,.Lfound0
115         xor     r6,r2,r5
116         ld.a    r2,[r0,4]
117         sub     r12,r6,r3
118         bic     r12,r12,r6
119         and.f   r7,r12,r4
120         sub     r12,r2,r3
121         bic_s   r12,r12,r2
122         beq.d   .Loop
123         and     r12,r12,r4
124 ; Found searched-for character.  r0 has already advanced to next word.
125 #ifdef __LITTLE_ENDIAN__
126 /* We only need the information about the first matching byte
127    (i.e. the least significant matching byte) to be exact,
128    hence there is no problem with carry effects.  */
129 .Lfound_char:
130         btst    r7,7
131 .Lfound_char_ua:
132         sub_s   r0,r0,4
133         add.eq  r0,r0,1
134         btst.eq r7,15
135         add.eq  r0,r0,1
136         btst.eq r7,23
137         j_s.d   [blink]
138         add.eq  r0,r0,1
140         .balign 4
141 .Lfound0_ua:
142         mov_l   r3,r7
143 .Lfound0:
144         sub     r2,r6,r3
145         bic     r2,r2,r6
146         and     r2,r2,r4
147         or      r3,r12,r2
148         sub_s   r12,r3,1
149         xor_s   r3,r3,r12
150         tst_s   r2,r3
151         lsr     r2,r3,31
152         lsr     r12,r3,16
153         jeq.d   [blink]
154         mov.eq  r0,0
155         lsr     r3,r3,8
156         sub_s   r2,r2,r12
157         sub_s   r2,r2,r3
158         bmsk_s  r2,r2,1
159         j_s.d   [blink]
160         add_s   r0,r0,r2
161 #else /* BIG ENDIAN */
162 .Lfound_char:
163         asl     r6,r6,7
164         sub_s   r0,r0,4
165         bic.f   r2,r7,r6
166 .Lfound_char_ua:
167         add.pl  r0,r0,1
168         jmi.d   [blink]
169         btst_s  r2,23
170         add.eq  r0,r0,1
171         btst.eq r2,15
172         j_s.d   [blink]
173         add.eq  r0,r0,1
175 ; N.B. if we searched for a char zero and found it in the MSB,
176 ; and ignored matches are identical, we will take the early exit
177 ; like for an ordinary found zero - except for the extra stalls at jhi -
178 ; but still compute the right result.
179 .Lfound0_ua:
180         mov_s   r3,r7
181 .Lfound0:
182         asl_s   r2,r2,7
183         or      r7,r6,r4
184         bic_s   r12,r12,r2
185         sub     r2,r7,r3
186         or      r2,r2,r6
187         bic     r2,r4,r2
188         cmp     r12,r2
189         mov.hi  r0,0
190         btst.ls r2,31
191         jhi.d   [blink]
192         add.eq  r0,r0,1
193         btst.eq r2,23
194         add.eq  r0,r0,1
195         btst.eq r2,15
196         j_s.d   [blink]
197         add.eq  r0,r0,1
198 #endif /* ENDIAN */
199 ENDFUNC (strchr)
200 #endif /* __ARC_BARREL_SHIFTER__ &&
201     (__ARC600__ || (!__ARC_NORM__ && !__ARC601__)) */
203 #endif /* !__OPTIMIZE_SIZE__ && !PREFER_SIZE_OVER_SPEED */