Remove unused localedata/th_TH.in
[glibc.git] / sysdeps / m68k / strchr.S
blobe908e789aa2d3077d96449aee849a45fb0c0e709
1 /* strchr (str, ch) -- Return pointer to first occurrence of CH in STR.
2    For Motorola 68000.
3    Copyright (C) 1999-2023 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library.  If not, see
18    <https://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
21 #include "asm-syntax.h"
23         TEXT
24 ENTRY(strchr)
25         /* Save the callee-saved registers we use.  */
26         movel   R(d2),MEM_PREDEC(sp)
27         cfi_adjust_cfa_offset (4)
28         movel   R(d3),MEM_PREDEC(sp)
29         cfi_adjust_cfa_offset (4)
30         cfi_rel_offset (R(d2),4)
31         cfi_rel_offset (R(d3),0)
33         /* Get string pointer and character.  */
34         movel   MEM_DISP(sp,12),R(a0)
35         moveb   MEM_DISP(sp,19),R(d0)
37         /* Distribute the character to all bytes of a longword.  */
38         movel   R(d0),R(d1)
39         lsll    #8,R(d1)
40         moveb   R(d0),R(d1)
41         movel   R(d1),R(d0)
42         swap    R(d0)
43         movew   R(d1),R(d0)
45         /* First search for the character one byte at a time until the
46            pointer is aligned to a longword boundary.  */
47         movel   R(a0),R(d1)
48 #ifdef __mcoldfire__
49         andl    #3,R(d1)
50 #else
51         andw    #3,R(d1)
52 #endif
53         beq     L(L1)
54         moveb   MEM(a0),R(d2)
55         cmpb    R(d0),R(d2)
56         beq     L(L9)
57         tstb    R(d2)
58         beq     L(L3)
59         addql   #1,R(a0)
61 #ifdef __mcoldfire__
62         subql   #3,R(d1)
63 #else
64         subqw   #3,R(d1)
65 #endif
66         beq     L(L1)
67         moveb   MEM(a0),R(d2)
68         cmpb    R(d0),R(d2)
69         beq     L(L9)
70         tstb    R(d2)
71         beq     L(L3)
72         addql   #1,R(a0)
74 #ifdef __mcoldfire__
75         addql   #1,R(d1)
76 #else
77         addqw   #1,R(d1)
78 #endif
79         beq     L(L1)
80         moveb   MEM(a0),R(d2)
81         cmpb    R(d0),R(d2)
82         beq     L(L9)
83         tstb    R(d2)
84         beq     L(L3)
85         addql   #1,R(a0)
87 L(L1:)
88         /* Load the magic bits.  Unlike the generic implementation we can
89            use the carry bit as the fourth hole.  */
90         movel   #0xfefefeff,R(d3)
92       /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
93          change any of the hole bits of LONGWORD.
95          1) Is this safe?  Will it catch all the zero bytes?
96          Suppose there is a byte with all zeros.  Any carry bits
97          propagating from its left will fall into the hole at its
98          least significant bit and stop.  Since there will be no
99          carry from its most significant bit, the LSB of the
100          byte to the left will be unchanged, and the zero will be
101          detected.
103          2) Is this worthwhile?  Will it ignore everything except
104          zero bytes?  Suppose every byte of LONGWORD has a bit set
105          somewhere.  There will be a carry into bit 8.  If bit 8
106          is set, this will carry into bit 16.  If bit 8 is clear,
107          one of bits 9-15 must be set, so there will be a carry
108          into bit 16.  Similarly, there will be a carry into bit
109          24.  If one of bits 24-31 is set, there will be a carry
110          into bit 32 (=carry flag), so all of the hole bits will
111          be changed.
113          3) But wait!  Aren't we looking for C, not zero?
114          Good point.  So what we do is XOR LONGWORD with a longword,
115          each of whose bytes is C.  This turns each byte that is C
116          into a zero.  */
118 L(L2:)
119         /* Get the longword in question.  */
120         movel   MEM_POSTINC(a0),R(d1)
121         /* XOR with the byte we search for.  */
122         eorl    R(d0),R(d1)
124         /* Add the magic value.  We get carry bits reported for each byte
125            which is not C.  */
126         movel   R(d3),R(d2)
127         addl    R(d1),R(d2)
129         /* Check the fourth carry bit before it is clobbered by the next
130            XOR.  If it is not set we have a hit.  */
131         bcc     L(L8)
133         /* We are only interested in carry bits that change due to the
134            previous add, so remove original bits.  */
135         eorl    R(d1),R(d2)
137         /* Now test for the other three overflow bits.
138            Set all non-carry bits.  */
139         orl     R(d3),R(d2)
140         /* Add 1 to get zero if all carry bits were set.  */
141         addql   #1,R(d2)
143         /* If we don't get zero then at least one byte of the word equals
144            C.  */
145         bne     L(L8)
147         /* Next look for a NUL byte.
148            Restore original longword without reload.  */
149         eorl    R(d0),R(d1)
150         /* Add the magic value.  We get carry bits reported for each byte
151            which is not NUL.  */
152         movel   R(d3),R(d2)
153         addl    R(d1),R(d2)
155         /* Check the fourth carry bit before it is clobbered by the next
156            XOR.  If it is not set we have a hit, and return NULL.  */
157         bcc     L(L3)
159         /* We are only interested in carry bits that change due to the
160            previous add, so remove original bits.  */
161         eorl    R(d1),R(d2)
163         /* Now test for the other three overflow bits.
164            Set all non-carry bits.  */
165         orl     R(d3),R(d2)
166         /* Add 1 to get zero if all carry bits were set.  */
167         addql   #1,R(d2)
169         /* If we don't get zero then at least one byte of the word was NUL
170            and we return NULL.  Otherwise continue with the next longword.  */
171         bne     L(L3)
173         /* Get the longword in question.  */
174         movel   MEM_POSTINC(a0),R(d1)
175         /* XOR with the byte we search for.  */
176         eorl    R(d0),R(d1)
178         /* Add the magic value.  We get carry bits reported for each byte
179            which is not C.  */
180         movel   R(d3),R(d2)
181         addl    R(d1),R(d2)
183         /* Check the fourth carry bit before it is clobbered by the next
184            XOR.  If it is not set we have a hit.  */
185         bcc     L(L8)
187         /* We are only interested in carry bits that change due to the
188            previous add, so remove original bits */
189         eorl    R(d1),R(d2)
191         /* Now test for the other three overflow bits.
192            Set all non-carry bits.  */
193         orl     R(d3),R(d2)
194         /* Add 1 to get zero if all carry bits were set.  */
195         addql   #1,R(d2)
197         /* If we don't get zero then at least one byte of the word equals
198            C.  */
199         bne     L(L8)
201         /* Next look for a NUL byte.
202            Restore original longword without reload.  */
203         eorl    R(d0),R(d1)
204         /* Add the magic value.  We get carry bits reported for each byte
205            which is not NUL.  */
206         movel   R(d3),R(d2)
207         addl    R(d1),R(d2)
209         /* Check the fourth carry bit before it is clobbered by the next
210            XOR.  If it is not set we have a hit, and return NULL.  */
211         bcc     L(L3)
213         /* We are only interested in carry bits that change due to the
214            previous add, so remove original bits */
215         eorl    R(d1),R(d2)
217         /* Now test for the other three overflow bits.
218            Set all non-carry bits.  */
219         orl     R(d3),R(d2)
220         /* Add 1 to get zero if all carry bits were set.  */
221         addql   #1,R(d2)
223         /* If we don't get zero then at least one byte of the word was NUL
224            and we return NULL.  Otherwise continue with the next longword.  */
225         beq     L(L2)
227 L(L3:)
228         /* Return NULL.  */
229         clrl    R(d0)
230         movel   R(d0),R(a0)
231         movel   MEM_POSTINC(sp),R(d3)
232         cfi_remember_state
233         cfi_adjust_cfa_offset (-4)
234         cfi_restore (R(d3))
235         movel   MEM_POSTINC(sp),R(d2)
236         cfi_adjust_cfa_offset (-4)
237         cfi_restore (R(d2))
238         rts
240         cfi_restore_state
241 L(L8:)
242         /* We have a hit.  Check to see which byte it was.  First
243            compensate for the autoincrement in the loop.  */
244         subql   #4,R(a0)
246         moveb   MEM(a0),R(d1)
247         cmpb    R(d0),R(d1)
248         beq     L(L9)
249         tstb    R(d1)
250         beq     L(L3)
251         addql   #1,R(a0)
253         moveb   MEM(a0),R(d1)
254         cmpb    R(d0),R(d1)
255         beq     L(L9)
256         tstb    R(d1)
257         beq     L(L3)
258         addql   #1,R(a0)
260         moveb   MEM(a0),R(d1)
261         cmpb    R(d0),R(d1)
262         beq     L(L9)
263         tstb    R(d1)
264         beq     L(L3)
265         addql   #1,R(a0)
267         /* Otherwise the fourth byte must equal C.  */
268 L(L9:)
269         movel   R(a0),R(d0)
270         movel   MEM_POSTINC(sp),R(d3)
271         cfi_adjust_cfa_offset (-4)
272         cfi_restore (R(d3))
273         movel   MEM_POSTINC(sp),R(d2)
274         cfi_adjust_cfa_offset (-4)
275         cfi_restore (R(d2))
276         rts
277 END(strchr)
279 weak_alias (strchr, index)
280 libc_hidden_builtin_def (strchr)