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