]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/alpha/strncmp.S
update from main archive 961105
[thirdparty/glibc.git] / sysdeps / alpha / strncmp.S
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2 Contributed by Richard Henderson (rth@tamu.edu)
3
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
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 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If
18 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 Cambridge, MA 02139, USA. */
20
21 /* Bytewise compare two null-terminated strings of length no longer than N. */
22
23 #include <sysdep.h>
24
25 .set noat
26 .set noreorder
27
28 .text
29
30 ENTRY(strncmp)
31 #ifdef PROF
32 ldgp gp, 0(pv)
33 lda AT, _mcount
34 jsr AT, (AT), _mcount
35 .prologue 1
36 #else
37 .prologue 0
38 #endif
39
40 xor a0, a1, t2 # e0 : are s1 and s2 co-aligned?
41 beq a2, $zerolength # .. e1 :
42 ldq_u t0, 0(a0) # e0 : give cache time to catch up
43 ldq_u t1, 0(a1) # .. e1 :
44 and t2, 7, t2 # e0 :
45 and a0, 7, t4 # .. e1 : find s1 misalignment
46 lda t3, -1 # e0 :
47 addq a2, t4, a2 # .. e1 : bias count by s1 misalignment
48 and a2, 7, t10 # e1 : ofs of last byte in last word
49 srl a2, 3, a2 # .. e0 : remaining full words in count
50 and a1, 7, t5 # e0 : find s2 misalignment
51 bne t2, $unaligned # .. e1 :
52
53 /* On entry to this basic block:
54 t0 == the first word of s1.
55 t1 == the first word of s2.
56 t3 == -1. */
57
58 $aligned:
59 mskqh t3, a1, t3 # e0 : mask off leading garbage
60 nop # .. e1 :
61 ornot t1, t3, t1 # e0 :
62 ornot t0, t3, t0 # .. e1 :
63 cmpbge zero, t1, t7 # e0 : bits set iff null found
64 beq a2, $eoc # .. e1 : check end of count
65 unop # :
66 bne t7, $eos # e1 :
67
68 /* Aligned compare main loop.
69 On entry to this basic block:
70 t0 == an s1 word.
71 t1 == an s2 word not containing a null. */
72
73 $a_loop:
74 xor t0, t1, t2 # e0 :
75 bne t2, $wordcmp # .. e1 (zdb)
76 ldq_u t1, 0(a1) # e0 :
77 ldq_u t0, 0(a0) # .. e1 :
78 addq a1, 8, a1 # e0 :
79 addq a0, 8, a0 # .. e1 :
80 cmpbge zero, t1, t7 # e0 :
81 beq a2, $eoc # .. e1 :
82 subq a2, 1, a2 # e0 :
83 beq t7, $a_loop # .. e1 :
84 br $eos # e1 :
85
86 /* The two strings are not co-aligned. Align s1 and cope. */
87 $unaligned:
88 subq a1, t4, a1 # e0 :
89 unop # :
90
91 /* If s2 misalignment is larger than s2 misalignment, we need
92 extra startup checks to avoid SEGV. */
93
94 cmplt t4, t5, t8 # .. e1 :
95 beq t8, $u_head # e1 :
96
97 mskqh t3, t5, t3 # e0 :
98 ornot t1, t3, t3 # e0 :
99 cmpbge zero, t3, t7 # e1 : is there a zero?
100 beq t7, $u_head # e1 :
101
102 /* We've found a zero in the first partial word of s2. Align
103 our current s1 and s2 words and compare what we've got. */
104
105 extql t1, t5, t1 # e0 :
106 lda t3, -1 # .. e1 :
107 insql t1, a0, t1 # e0 :
108 mskqh t3, a0, t3 # e0 :
109 ornot t1, t3, t1 # e0 :
110 ornot t0, t3, t0 # .. e1 :
111 cmpbge zero, t1, t7 # e0 : find that zero again
112 beq a2, $eoc # .. e1 : and finish up
113 br $eos # e1 :
114
115 .align 3
116 $u_head:
117 /* We know just enough now to be able to assemble the first
118 full word of s2. We can still find a zero at the end of it.
119
120 On entry to this basic block:
121 t0 == first word of s1
122 t1 == first partial word of s2. */
123
124 ldq_u t2, 8(a1) # e0 : load second partial s2 word
125 lda t3, -1 # .. e1 : create leading garbage mask
126 extql t1, a1, t1 # e0 : create first s2 word
127 mskqh t3, a0, t3 # e0 :
128 extqh t2, a1, t4 # e0 :
129 ornot t0, t3, t0 # .. e1 : kill s1 garbage
130 or t1, t4, t1 # e0 : s2 word now complete
131 ornot t1, t3, t1 # e1 : kill s2 garbage
132 cmpbge zero, t0, t7 # e0 : find zero in first s1 word
133 beq a2, $eoc # .. e1 :
134 lda t3, -1 # e0 :
135 bne t7, $eos # .. e1 :
136 subq a2, 1, a2 # e0 :
137 xor t0, t1, t4 # .. e1 : compare aligned words
138 mskql t3, a1, t3 # e0 : mask out s2[1] bits we have seen
139 bne t4, $wordcmp # .. e1 :
140 or t2, t3, t3 # e0 :
141 cmpbge zero, t3, t7 # e1 : find zero in high bits of s2[1]
142 bne t7, $u_final # e1 :
143
144 /* Unaligned copy main loop. In order to avoid reading too much,
145 the loop is structured to detect zeros in aligned words from s2.
146 This has, unfortunately, effectively pulled half of a loop
147 iteration out into the head and half into the tail, but it does
148 prevent nastiness from accumulating in the very thing we want
149 to run as fast as possible.
150
151 On entry to this basic block:
152 t2 == the unshifted low-bits from the next s2 word. */
153
154 .align 3
155 $u_loop:
156 extql t2, a1, t3 # e0 :
157 ldq_u t2, 16(a1) # .. e1 : load next s2 high bits
158 ldq_u t0, 8(a0) # e0 : load next s1 word
159 addq a1, 8, a1 # .. e1 :
160 addq a0, 8, a0 # e0 :
161 nop # .. e1 :
162 extqh t2, a1, t1 # e0 :
163 cmpbge zero, t0, t7 # .. e1 : find zero in current s1 word
164 or t1, t3, t1 # e0 :
165 beq a2, $eoc # .. e1 : check for end of count
166 subq a2, 1, a2 # e0 :
167 bne t7, $eos # .. e1 :
168 xor t0, t1, t4 # e0 : compare the words
169 bne t4, $wordcmp # .. e1 (zdb)
170 cmpbge zero, t2, t4 # e0 : find zero in next low bits
171 beq t4, $u_loop # .. e1 (zdb)
172
173 /* We've found a zero in the low bits of the last s2 word. Get
174 the next s1 word and align them. */
175 $u_final:
176 ldq_u t0, 8(a0) # e1 :
177 extql t2, a1, t1 # .. e0 :
178 cmpbge zero, t1, t7 # e0 :
179 bne a2, $eos # .. e1 :
180
181 /* We've hit end of count. Zero everything after the count
182 and compare whats left. */
183
184 .align 3
185 $eoc:
186 mskql t0, t10, t0
187 mskql t1, t10, t1
188
189 /* We've found a zero somewhere in a word we just read.
190 On entry to this basic block:
191 t0 == s1 word
192 t1 == s2 word
193 t7 == cmpbge mask containing the zero. */
194
195 $eos:
196 negq t7, t6 # e0 : create bytemask of valid data
197 and t6, t7, t8 # e1 :
198 subq t8, 1, t6 # e0 :
199 or t6, t8, t7 # e1 :
200 zapnot t0, t7, t0 # e0 : kill the garbage
201 zapnot t1, t7, t1 # .. e1 :
202 xor t0, t1, v0 # e0 : and compare
203 beq v0, $done # .. e1 :
204
205 /* Here we have two differing co-aligned words in t0 & t1.
206 Bytewise compare them and return (t0 > t1 ? 1 : -1). */
207 $wordcmp:
208 cmpbge t0, t1, t2 # e0 : comparison yields bit mask of ge
209 cmpbge t1, t0, t3 # .. e1 :
210 xor t2, t3, t0 # e0 : bits set iff t0/t1 bytes differ
211 negq t0, t1 # e1 : clear all but least bit
212 and t0, t1, t0 # e0 :
213 lda v0, -1 # .. e1 :
214 and t0, t2, t1 # e0 : was bit set in t0 > t1?
215 cmovne t1, 1, v0 # .. e1 (zdb)
216
217 $done:
218 ret # e1 :
219
220 $zerolength:
221 clr v0
222 ret
223
224 END(strncmp)