8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / lib / libc / sparc / gen / strcmp.s
bloba08693f70de655475dbeca1f0fa0651d9a859f74
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 .file "strcmp.s"
29 /* strcmp(s1, s2)
31 * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
33 * Fast assembler language version of the following C-program for strcmp
34 * which represents the `standard' for the C-library.
36 * int
37 * strcmp(s1, s2)
38 * register const char *s1;
39 * register const char *s2;
40 * {
42 * if(s1 == s2)
43 * return(0);
44 * while(*s1 == *s2++)
45 * if(*s1++ == '\0')
46 * return(0);
47 * return(*s1 - s2[-1]);
48 * }
51 #include <sys/asm_linkage.h>
53 ! This strcmp implementation first determines whether s1 is aligned.
54 ! If it is not, it attempts to align it and then checks the
55 ! alignment of the destination string. If it is possible to
56 ! align s2, this also happens and then the compare begins. Otherwise,
57 ! a different compare for non-aligned strings is used.
58 ! In this case, we have multiple routines depending upon the
59 ! degree to which a string is mis-aligned.
61 ENTRY(strcmp)
63 .align 32
65 subcc %o0, %o1, %o2 ! s1 == s2 ?
66 bz .stringsequal1 ! yup, same string, done
67 sethi %hi(0x01010101), %o5 ! start loading Mycroft's magic2
68 andcc %o0, 3, %o3 ! s1 word-aligned ?
69 or %o5, %lo(0x01010101),%o5! finish loading Mycroft's magic2
70 bz .s1aligned ! yup
71 sll %o5, 7, %o4 ! load Mycroft's magic1
72 sub %o3, 4, %o3 ! number of bytes till aligned
74 .aligns1:
75 ldub [%o1 + %o2], %o0 ! s1[]
76 ldub [%o1], %g1 ! s2[]
77 subcc %o0, %g1, %o0 ! s1[] != s2[] ?
78 bne .done ! yup, done
79 addcc %o0, %g1, %g0 ! s1[] == 0 ?
80 bz .done ! yup, done
81 inccc %o3 ! s1 aligned yet?
82 bnz .aligns1 ! nope, compare another pair of bytes
83 inc %o1 ! s1++, s2++
85 .s1aligned:
86 andcc %o1, 3, %o3 ! s2 word aligned ?
87 bz .word4 ! yup
88 cmp %o3, 2 ! s2 half-word aligned ?
89 be .word2 ! yup
90 cmp %o3, 3 ! s2 offset to dword == 3 ?
91 be,a .word3 ! yup
92 ldub [%o1], %o0 ! new lower word in s2
94 .word1:
95 lduw [%o1 - 1], %o0 ! new lower word in s2
96 sethi %hi(0xff000000), %o3 ! mask for forcing byte 1 non-zero
97 sll %o0, 8, %g1 ! partial unaligned word from s2
98 or %o0, %o3, %o0 ! force byte 1 non-zero
100 .cmp1:
101 andn %o4, %o0, %o3 ! ~word & 0x80808080
102 sub %o0, %o5, %o0 ! word - 0x01010101
103 andcc %o0, %o3, %g0 ! (word - 0x01010101) & ~word & 0x80808080
104 bz,a .doload1 ! no null byte in previous word from s2
105 lduw [%o1 + 3], %o0 ! load next aligned word from s2
106 .doload1:
107 srl %o0, 24, %o3 ! byte 1 of new aligned word from s2
108 or %g1, %o3, %g1 ! merge to get unaligned word from s2
109 lduw [%o1 + %o2], %o3 ! word from s1
110 cmp %o3, %g1 ! *s1 != *s2 ?
111 bne .wordsdiffer ! yup, find the byte that is different
112 add %o1, 4, %o1 ! s1+=4, s2+=4
113 andn %o4, %o3, %g1 ! ~word & 0x80808080
114 sub %o3, %o5, %o3 ! word - 0x01010101
115 andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080
116 bz .cmp1 ! no null-byte in s1 yet
117 sll %o0, 8, %g1 ! partial unaligned word from s2
119 ! words are equal but the end of s1 has been reached
120 ! this means the strings must be equal
121 .stringsequal1:
122 retl ! return from leaf function
123 mov %g0, %o0 ! return 0, i.e. strings are equal
124 nop ! pad for optimal alignment of .cmp2
125 nop ! pad for optimal alignment of .cmp2
127 .word2:
128 lduh [%o1], %o0 ! new lower word in s2
129 sethi %hi(0xffff0000), %o3 ! mask for forcing bytes 1,2 non-zero
130 sll %o0, 16, %g1 ! partial unaligned word from s2
131 or %o0, %o3, %o0 ! force bytes 1,2 non-zero
133 .cmp2:
134 andn %o4, %o0, %o3 ! ~word & 0x80808080
135 sub %o0, %o5, %o0 ! word - 0x01010101
136 andcc %o0, %o3, %g0 ! (word - 0x01010101) & ~word & 0x80808080
137 bz,a .doload2 ! no null byte in previous word from s2
138 lduw [%o1 + 2], %o0 ! load next aligned word from s2
139 .doload2:
140 srl %o0, 16, %o3 ! bytes 1,2 of new aligned word from s2
141 or %g1, %o3, %g1 ! merge to get unaligned word from s2
142 lduw [%o1 + %o2], %o3 ! word from s1
143 cmp %o3, %g1 ! *s1 != *s2 ?
144 bne .wordsdiffer ! yup, find the byte that is different
145 add %o1, 4, %o1 ! s1+=4, s2+=4
146 andn %o4, %o3, %g1 ! ~word & 0x80808080
147 sub %o3, %o5, %o3 ! word - 0x01010101
148 andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080
149 bz .cmp2 ! no null-byte in s1 yet
150 sll %o0, 16, %g1 ! partial unaligned word from s2
152 ! words are equal but the end of s1 has been reached
153 ! this means the strings must be equal
154 .stringsequal2:
155 retl ! return from leaf function
156 mov %g0, %o0 ! return 0, i.e. strings are equal
158 .word3:
159 sll %o0, 24, %g1 ! partial unaligned word from s2
160 nop ! pad for optimal alignment of .cmp3
161 .cmp3:
162 andcc %o0, 0xff, %g0 ! did previous word contain null-byte ?
163 bnz,a .doload3 ! nope, load next word from s2
164 lduw [%o1 + 1], %o0 ! load next aligned word from s2
165 .doload3:
166 srl %o0, 8, %o3 ! bytes 1,2,3 from new aligned s2 word
167 or %g1, %o3, %g1 ! merge to get unaligned word from s2
168 lduw [%o1 + %o2], %o3 ! word from s1
169 cmp %o3, %g1 ! *s1 != *s2 ?
170 bne .wordsdiffer ! yup, find the byte that is different
171 add %o1, 4, %o1 ! s1+=4, s2+=4
172 andn %o4, %o3, %g1 ! ~word & 0x80808080
173 sub %o3, %o5, %o3 ! word - 0x01010101
174 andcc %o3, %g1, %g0 ! (word - 0x01010101) & ~word & 0x80808080
175 bz .cmp3 ! no null-byte in s1 yet
176 sll %o0, 24, %g1 ! partial unaligned word from s2
178 ! words are equal but the end of s1 has been reached
179 ! this means the strings must be equal
180 .stringsequal3:
181 retl ! return from leaf function
182 mov %g0, %o0 ! return 0, i.e. strings are equal
184 .word4:
185 lduw [%o1 + %o2], %o3 ! load word from s1
186 nop ! pad for optimal alignment of .cmp4
187 nop ! pad for optimal alignment of .cmp4
188 nop ! pad for optimal alignment of .cmp4
190 .cmp4:
191 lduw [%o1], %g1 ! load word from s2
192 cmp %o3, %g1 ! *scr1 == *src2 ?
193 bne .wordsdiffer ! nope, find mismatching character
194 add %o1, 4, %o1 ! src1 += 4, src2 += 4
195 andn %o4, %o3, %o0 ! ~word & 0x80808080
196 sub %o3, %o5, %o3 ! word - 0x01010101
197 andcc %o3, %o0, %g0 ! (word - 0x01010101) & ~word & 0x80808080
198 bz,a .cmp4 ! no null-byte in s1 yet
199 lduw [%o1 + %o2], %o3 ! load word from s1
201 ! words are equal but the end of s1 has been reached
202 ! this means the strings must be equal
203 .stringsequal4:
204 retl ! return from leaf function
205 mov %g0, %o0 ! return 0, i.e. strings are equal
207 .wordsdiffer:
208 srl %g1, 24, %o2 ! first byte of mismatching word in s2
209 srl %o3, 24, %o1 ! first byte of mismatching word in s1
210 subcc %o1, %o2, %o0 ! *s1-*s2
211 bnz .done ! bytes differ, return difference
212 srl %g1, 16, %o2 ! second byte of mismatching word in s2
213 andcc %o1, 0xff, %o0 ! *s1 == 0 ?
214 bz .done ! yup
216 ! we know byte 1 is equal, so can compare bytes 1,2 as a group
218 srl %o3, 16, %o1 ! second byte of mismatching word in s1
219 subcc %o1, %o2, %o0 ! *s1-*s2
220 bnz .done ! bytes differ, return difference
221 srl %g1, 8, %o2 ! third byte of mismatching word in s2
222 andcc %o1, 0xff, %o0 ! *s1 == 0 ?
223 bz .done ! yup
225 ! we know bytes 1, 2 are equal, so can compare bytes 1,2,3 as a group
227 srl %o3, 8, %o1 ! third byte of mismatching word in s1
228 subcc %o1, %o2, %o0 ! *s1-*s2
229 bnz .done ! bytes differ, return difference
230 andcc %o1, 0xff, %g0 ! *s1 == 0 ?
231 bz .stringsequal1 ! yup
233 ! we know bytes 1,2,3 are equal, so can compare bytes 1,2,3,4 as group
235 subcc %o3, %g1, %o0 ! *s1-*s2
236 bz,a .done ! bytes differ, return difference
237 andcc %o3, 0xff, %o0 ! *s1 == 0 ?
239 .done:
240 retl ! return from leaf routine
241 nop ! padding
244 SET_SIZE(strcmp)