alpha: create kernel-features.h.
[glibc.git] / sysdeps / m68k / rawmemchr.S
blob97735f669dff1daea4ae5a60ec48fe0f034b7cb6
1 /* rawmemchr (str, ch) -- Return pointer to first occurrence of CH in STR.
2    For Motorola 68000.
3    Copyright (C) 1999, 2002 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Andreas Schwab <schwab@gnu.org>.
7    The GNU C Library is free software; you can redistribute it and/or
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.
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
15    Lesser General Public License for more details.
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
22 #include <sysdep.h>
23 #include "asm-syntax.h"
25         TEXT
26 ENTRY(__rawmemchr)
27         /* Save the callee-saved registers we use.  */
28         movel   R(d2),MEM_PREDEC(sp)
29         movel   R(d3),MEM_PREDEC(sp)
31         /* Get string pointer and character.  */
32         movel   MEM_DISP(sp,12),R(a0)
33         moveb   MEM_DISP(sp,19),R(d0)
35         /* Distribute the character to all bytes of a longword.  */
36         movel   R(d0),R(d1)
37         lsll    #8,R(d1)
38         moveb   R(d0),R(d1)
39         movel   R(d1),R(d0)
40         swap    R(d0)
41         movew   R(d1),R(d0)
43         /* First search for the character one byte at a time until the
44            pointer is aligned to a longword boundary.  */
45         movel   R(a0),R(d1)
46 #ifdef __mcoldfire__
47         andl    #3,R(d1)
48 #else
49         andw    #3,R(d1)
50 #endif
51         beq     L(L1)
52         cmpb    MEM(a0),R(d0)
53         beq     L(L9)
54         addql   #1,R(a0)
56 #ifdef __mcoldfire__
57         subql   #3,R(d1)
58 #else
59         subqw   #3,R(d1)
60 #endif
61         beq     L(L1)
62         cmpb    MEM(a0),R(d0)
63         beq     L(L9)
64         addql   #1,R(a0)
66 #ifdef __mcoldfire__
67         addql   #1,R(d1)
68 #else
69         addqw   #1,R(d1)
70 #endif
71         beq     L(L1)
72         cmpb    MEM(a0),R(d0)
73         beq     L(L9)
74         addql   #1,R(a0)
76 L(L1:)
77         /* Load the magic bits.  Unlike the generic implementation we can
78            use the carry bit as the fourth hole.  */
79         movel   #0xfefefeff,R(d3)
81       /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to
82          change any of the hole bits of LONGWORD.
84          1) Is this safe?  Will it catch all the zero bytes?
85          Suppose there is a byte with all zeros.  Any carry bits
86          propagating from its left will fall into the hole at its
87          least significant bit and stop.  Since there will be no
88          carry from its most significant bit, the LSB of the
89          byte to the left will be unchanged, and the zero will be
90          detected.
92          2) Is this worthwhile?  Will it ignore everything except
93          zero bytes?  Suppose every byte of LONGWORD has a bit set
94          somewhere.  There will be a carry into bit 8.  If bit 8
95          is set, this will carry into bit 16.  If bit 8 is clear,
96          one of bits 9-15 must be set, so there will be a carry
97          into bit 16.  Similarly, there will be a carry into bit
98          24.  If one of bits 24-31 is set, there will be a carry
99          into bit 32 (=carry flag), so all of the hole bits will
100          be changed.
102          3) But wait!  Aren't we looking for C, not zero?
103          Good point.  So what we do is XOR LONGWORD with a longword,
104          each of whose bytes is C.  This turns each byte that is C
105          into a zero.  */
107 L(L2:)
108         /* Get the longword in question.  */
109         movel   MEM_POSTINC(a0),R(d1)
110         /* XOR with the byte we search for.  */
111         eorl    R(d0),R(d1)
113         /* Add the magic value.  We get carry bits reported for each byte
114            which is not C.  */
115         movel   R(d3),R(d2)
116         addl    R(d1),R(d2)
118         /* Check the fourth carry bit before it is clobbered by the next
119            XOR.  If it is not set we have a hit.  */
120         bcc     L(L8)
122         /* We are only interested in carry bits that change due to the
123            previous add, so remove original bits.  */
124         eorl    R(d1),R(d2)
126         /* Now test for the other three overflow bits.
127            Set all non-carry bits.  */
128         orl     R(d3),R(d2)
129         /* Add 1 to get zero if all carry bits were set.  */
130         addql   #1,R(d2)
132         /* If we don't get zero then at least one byte of the word equals
133            C.  */
134         bne     L(L8)
136         /* Get the longword in question.  */
137         movel   MEM_POSTINC(a0),R(d1)
138         /* XOR with the byte we search for.  */
139         eorl    R(d0),R(d1)
141         /* Add the magic value.  We get carry bits reported for each byte
142            which is not C.  */
143         movel   R(d3),R(d2)
144         addl    R(d1),R(d2)
146         /* Check the fourth carry bit before it is clobbered by the next
147            XOR.  If it is not set we have a hit.  */
148         bcc     L(L8)
150         /* We are only interested in carry bits that change due to the
151            previous add, so remove original bits */
152         eorl    R(d1),R(d2)
154         /* Now test for the other three overflow bits.
155            Set all non-carry bits.  */
156         orl     R(d3),R(d2)
157         /* Add 1 to get zero if all carry bits were set.  */
158         addql   #1,R(d2)
160         /* If we don't get zero then at least one byte of the word equals
161            C.  */
162         beq     L(L2)
164 L(L8:)
165         /* We have a hit.  Check to see which byte it was.  First
166            compensate for the autoincrement in the loop.  */
167         subql   #4,R(a0)
169         cmpb    MEM(a0),R(d0)
170         beq     L(L9)
171         addql   #1,R(a0)
173         cmpb    MEM(a0),R(d0)
174         beq     L(L9)
175         addql   #1,R(a0)
177         cmpb    MEM(a0),R(d0)
178         beq     L(L9)
179         addql   #1,R(a0)
181         /* Otherwise the fourth byte must equal C.  */
182 L(L9:)
183         movel   R(a0),R(d0)
184         movel   MEM_POSTINC(sp),R(d3)
185         movel   MEM_POSTINC(sp),R(d2)
186         rts
187 END(__rawmemchr)
189 libc_hidden_def (__rawmemchr)
190 weak_alias (__rawmemchr, rawmemchr)