update from main arcive 961210
[kopensolaris-gnu/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         subq    a2, 1, a2       # e0    :
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, 8(a1)       # e0    :
77         ldq_u   t0, 8(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)