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 /* Aligned compare main loop.
68 On entry to this basic block:
70 t1 == an s2 word not containing a null. */
74 bne t2, $wordcmp # .. e1 (zdb)
75 ldq_u t1, 8(a1) # e0 :
76 ldq_u t0, 8(a0) # .. e1 :
78 addq a0, 8, a0 # .. e1 :
79 cmpbge zero, t1, t7 # e0 :
80 beq a2, $eoc # .. e1 :
82 beq t7, $a_loop # .. e1 :
85 /* The two strings are not co-aligned. Align s1 and cope. */
87 subq a1, t4, a1 # e0 :
90 /* If s2 misalignment is larger than s2 misalignment, we need
91 extra startup checks to avoid SEGV. */
93 cmplt t4, t5, t8 # .. e1 :
94 beq t8, $u_head # e1 :
96 mskqh t3, t5, t3 # e0 :
97 ornot t1, t3, t3 # e0 :
98 cmpbge zero, t3, t7 # e1 : is there a zero?
99 beq t7, $u_head # e1 :
101 /* We've found a zero in the first partial word of s2. Align
102 our current s1 and s2 words and compare what we've got. */
104 extql t1, t5, t1 # e0 :
106 insql t1, a0, t1 # e0 :
107 mskqh t3, a0, t3 # e0 :
108 ornot t1, t3, t1 # e0 :
109 ornot t0, t3, t0 # .. e1 :
110 cmpbge zero, t1, t7 # e0 : find that zero again
111 beq a2, $eoc # .. e1 : and finish up
116 /* We know just enough now to be able to assemble the first
117 full word of s2. We can still find a zero at the end of it.
119 On entry to this basic block:
120 t0 == first word of s1
121 t1 == first partial word of s2. */
123 ldq_u t2, 8(a1) # e0 : load second partial s2 word
124 lda t3, -1 # .. e1 : create leading garbage mask
125 extql t1, a1, t1 # e0 : create first s2 word
126 mskqh t3, a0, t3 # e0 :
127 extqh t2, a1, t4 # e0 :
128 ornot t0, t3, t0 # .. e1 : kill s1 garbage
129 or t1, t4, t1 # e0 : s2 word now complete
130 ornot t1, t3, t1 # e1 : kill s2 garbage
131 cmpbge zero, t0, t7 # e0 : find zero in first s1 word
132 beq a2, $eoc # .. e1 :
134 bne t7, $eos # .. e1 :
135 subq a2, 1, a2 # e0 :
136 xor t0, t1, t4 # .. e1 : compare aligned words
137 mskql t3, a1, t3 # e0 : mask out s2[1] bits we have seen
138 bne t4, $wordcmp # .. e1 :
140 cmpbge zero, t3, t7 # e1 : find zero in high bits of s2[1]
141 bne t7, $u_final # e1 :
143 /* Unaligned copy main loop. In order to avoid reading too much,
144 the loop is structured to detect zeros in aligned words from s2.
145 This has, unfortunately, effectively pulled half of a loop
146 iteration out into the head and half into the tail, but it does
147 prevent nastiness from accumulating in the very thing we want
148 to run as fast as possible.
150 On entry to this basic block:
151 t2 == the unshifted low-bits from the next s2 word. */
155 extql t2, a1, t3 # e0 :
156 ldq_u t2, 16(a1) # .. e1 : load next s2 high bits
157 ldq_u t0, 8(a0) # e0 : load next s1 word
158 addq a1, 8, a1 # .. e1 :
159 addq a0, 8, a0 # e0 :
161 extqh t2, a1, t1 # e0 :
162 cmpbge zero, t0, t7 # .. e1 : find zero in current s1 word
164 beq a2, $eoc # .. e1 : check for end of count
165 subq a2, 1, a2 # e0 :
166 bne t7, $eos # .. e1 :
167 xor t0, t1, t4 # e0 : compare the words
168 bne t4, $wordcmp # .. e1 (zdb)
169 cmpbge zero, t2, t4 # e0 : find zero in next low bits
170 beq t4, $u_loop # .. e1 (zdb)
172 /* We've found a zero in the low bits of the last s2 word. Get
173 the next s1 word and align them. */
175 ldq_u t0, 8(a0) # e1 :
176 extql t2, a1, t1 # .. e0 :
177 cmpbge zero, t1, t7 # e0 :
178 bne a2, $eos # .. e1 :
180 /* We've hit end of count. Zero everything after the count
181 and compare whats left. */
188 /* We've found a zero somewhere in a word we just read.
189 On entry to this basic block:
192 t7 == cmpbge mask containing the zero. */
195 negq t7, t6 # e0 : create bytemask of valid data
196 and t6, t7, t8 # e1 :
197 subq t8, 1, t6 # e0 :
199 zapnot t0, t7, t0 # e0 : kill the garbage
200 zapnot t1, t7, t1 # .. e1 :
201 xor t0, t1, v0 # e0 : and compare
202 beq v0, $done # .. e1 :
204 /* Here we have two differing co-aligned words in t0 & t1.
205 Bytewise compare them and return (t0 > t1 ? 1 : -1). */
207 cmpbge t0, t1, t2 # e0 : comparison yields bit mask of ge
208 cmpbge t1, t0, t3 # .. e1 :
209 xor t2, t3, t0 # e0 : bits set iff t0/t1 bytes differ
210 negq t0, t1 # e1 : clear all but least bit
211 and t0, t1, t0 # e0 :
213 and t0, t2, t1 # e0 : was bit set in t0 > t1?
214 cmovne t1, 1, v0 # .. e1 (zdb)
224 libc_hidden_builtin_def (strncmp)