1 /* Copyright (C) 1996, 1997, 2003 Free Software Foundation, Inc.
2 Contributed by Richard Henderson (rth@tamu.edu)
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 /* Bytewise compare two null-terminated strings of length no longer than N. */
39 xor a0, a1, t2 # e0 : are s1 and s2 co-aligned?
40 beq a2, $zerolength # .. e1 :
41 ldq_u t0, 0(a0) # e0 : give cache time to catch up
42 ldq_u t1, 0(a1) # .. e1 :
44 and a0, 7, t4 # .. e1 : find s1 misalignment
46 addq a2, t4, a2 # .. e1 : bias count by s1 misalignment
47 and a2, 7, t10 # e1 : ofs of last byte in last word
48 srl a2, 3, a2 # .. e0 : remaining full words in count
49 and a1, 7, t5 # e0 : find s2 misalignment
50 bne t2, $unaligned # .. e1 :
52 /* On entry to this basic block:
53 t0 == the first word of s1.
54 t1 == the first word of s2.
58 mskqh t3, a1, t3 # e0 : mask off leading garbage
60 ornot t1, t3, t1 # e0 :
61 ornot t0, t3, t0 # .. e1 :
62 cmpbge zero, t1, t7 # e0 : bits set iff null found
63 beq a2, $eoc # .. e1 : check end of count
65 bne t7, $eos # .. e1 :
67 beq t10, $ant_loop # .. e1 :
69 /* Aligned compare main loop.
70 On entry to this basic block:
72 t1 == an s2 word not containing a null. */
76 bne t2, $wordcmp # .. e1 (zdb)
77 ldq_u t1, 8(a1) # e0 :
78 ldq_u t0, 8(a0) # .. e1 :
80 addq a1, 8, a1 # .. e1 :
82 beq a2, $eoc # .. e1 :
83 cmpbge zero, t1, t7 # e0 :
84 beq t7, $a_loop # .. e1 :
88 /* Alternate aligned compare loop, for when there's no trailing
89 bytes on the count. We have to avoid reading too much data. */
92 bne t2, $wordcmp # .. e1 (zdb)
94 beq a2, $zerolength # .. e1 :
95 ldq_u t1, 8(a1) # e0 :
96 ldq_u t0, 8(a0) # .. e1 :
98 addq a0, 8, a0 # .. e1 :
99 cmpbge zero, t1, t7 # e0 :
100 beq t7, $ant_loop # .. e1 :
104 /* The two strings are not co-aligned. Align s1 and cope. */
106 subq a1, t4, a1 # e0 :
109 /* If s2 misalignment is larger than s2 misalignment, we need
110 extra startup checks to avoid SEGV. */
112 cmplt t4, t5, t8 # .. e1 :
113 beq t8, $u_head # e1 :
115 mskqh t3, t5, t3 # e0 :
116 ornot t1, t3, t3 # e0 :
117 cmpbge zero, t3, t7 # e1 : is there a zero?
118 beq t7, $u_head # e1 :
120 /* We've found a zero in the first partial word of s2. Align
121 our current s1 and s2 words and compare what we've got. */
123 extql t1, t5, t1 # e0 :
125 insql t1, a0, t1 # e0 :
126 mskqh t3, a0, t3 # e0 :
127 ornot t1, t3, t1 # e0 :
128 ornot t0, t3, t0 # .. e1 :
129 cmpbge zero, t1, t7 # e0 : find that zero again
130 beq a2, $eoc # .. e1 : and finish up
135 /* We know just enough now to be able to assemble the first
136 full word of s2. We can still find a zero at the end of it.
138 On entry to this basic block:
139 t0 == first word of s1
140 t1 == first partial word of s2. */
142 ldq_u t2, 8(a1) # e0 : load second partial s2 word
143 lda t3, -1 # .. e1 : create leading garbage mask
144 extql t1, a1, t1 # e0 : create first s2 word
145 mskqh t3, a0, t3 # e0 :
146 extqh t2, a1, t4 # e0 :
147 ornot t0, t3, t0 # .. e1 : kill s1 garbage
148 or t1, t4, t1 # e0 : s2 word now complete
149 ornot t1, t3, t1 # e1 : kill s2 garbage
150 cmpbge zero, t0, t7 # e0 : find zero in first s1 word
151 beq a2, $eoc # .. e1 :
153 bne t7, $eos # .. e1 :
154 subq a2, 1, a2 # e0 :
155 xor t0, t1, t4 # .. e1 : compare aligned words
156 mskql t3, a1, t3 # e0 : mask out s2[1] bits we have seen
157 bne t4, $wordcmp # .. e1 :
159 cmpbge zero, t3, t7 # e1 : find zero in high bits of s2[1]
160 bne t7, $u_final # e1 :
162 /* Unaligned copy main loop. In order to avoid reading too much,
163 the loop is structured to detect zeros in aligned words from s2.
164 This has, unfortunately, effectively pulled half of a loop
165 iteration out into the head and half into the tail, but it does
166 prevent nastiness from accumulating in the very thing we want
167 to run as fast as possible.
169 On entry to this basic block:
170 t2 == the unshifted low-bits from the next s2 word. */
174 extql t2, a1, t3 # e0 :
175 ldq_u t2, 16(a1) # .. e1 : load next s2 high bits
176 ldq_u t0, 8(a0) # e0 : load next s1 word
177 addq a1, 8, a1 # .. e1 :
178 addq a0, 8, a0 # e0 :
180 extqh t2, a1, t1 # e0 :
181 cmpbge zero, t0, t7 # .. e1 : find zero in current s1 word
183 beq a2, $eoc # .. e1 : check for end of count
184 subq a2, 1, a2 # e0 :
185 bne t7, $eos # .. e1 :
186 xor t0, t1, t4 # e0 : compare the words
187 bne t4, $wordcmp # .. e1 (zdb)
188 cmpbge zero, t2, t4 # e0 : find zero in next low bits
189 beq t4, $u_loop # .. e1 (zdb)
191 /* We've found a zero in the low bits of the last s2 word. Get
192 the next s1 word and align them. */
194 ldq_u t0, 8(a0) # e1 :
195 extql t2, a1, t1 # .. e0 :
196 cmpbge zero, t1, t7 # e0 :
197 bne a2, $eos # .. e1 :
199 /* We've hit end of count. Zero everything after the count
200 and compare whats left. */
209 /* We've found a zero somewhere in a word we just read.
210 On entry to this basic block:
213 t7 == cmpbge mask containing the zero. */
216 negq t7, t6 # e0 : create bytemask of valid data
217 and t6, t7, t8 # e1 :
218 subq t8, 1, t6 # e0 :
220 zapnot t0, t7, t0 # e0 : kill the garbage
221 zapnot t1, t7, t1 # .. e1 :
222 xor t0, t1, v0 # e0 : and compare
223 beq v0, $done # .. e1 :
225 /* Here we have two differing co-aligned words in t0 & t1.
226 Bytewise compare them and return (t0 > t1 ? 1 : -1). */
229 cmpbge t0, t1, t2 # e0 : comparison yields bit mask of ge
230 cmpbge t1, t0, t3 # .. e1 :
231 xor t2, t3, t0 # e0 : bits set iff t0/t1 bytes differ
232 negq t0, t1 # e1 : clear all but least bit
233 and t0, t1, t0 # e0 :
235 and t0, t2, t1 # e0 : was bit set in t0 > t1?
236 cmovne t1, 1, v0 # .. e1 (zdb)
247 libc_hidden_builtin_def (strncmp)