1 |
148 |
jeremybenn |
/*
|
2 |
|
|
* (c) Copyright 1986 HEWLETT-PACKARD COMPANY
|
3 |
|
|
*
|
4 |
|
|
* To anyone who acknowledges that this file is provided "AS IS"
|
5 |
|
|
* without any express or implied warranty:
|
6 |
|
|
* permission to use, copy, modify, and distribute this file
|
7 |
|
|
* for any purpose is hereby granted without fee, provided that
|
8 |
|
|
* the above copyright notice and this notice appears in all
|
9 |
|
|
* copies, and that the name of Hewlett-Packard Company not be
|
10 |
|
|
* used in advertising or publicity pertaining to distribution
|
11 |
|
|
* of the software without specific, written prior permission.
|
12 |
|
|
* Hewlett-Packard Company makes no representations about the
|
13 |
|
|
* suitability of this software for any purpose.
|
14 |
|
|
*/
|
15 |
|
|
|
16 |
|
|
/*
|
17 |
|
|
|
18 |
|
|
strcmp
|
19 |
|
|
|
20 |
|
|
Jerry Huck
|
21 |
|
|
Edgar Circenis
|
22 |
|
|
|
23 |
|
|
*/
|
24 |
|
|
/*
|
25 |
|
|
* strcmp(s1, s2)
|
26 |
|
|
*
|
27 |
|
|
* returns integer: < 0 iff s1 lexicographically less than s2
|
28 |
|
|
* > 0 iff s1 lexicographically greater than s2
|
29 |
|
|
* = 0 iff s1 lexicographically equal to s2
|
30 |
|
|
*/
|
31 |
|
|
|
32 |
|
|
#include "DEFS.h"
|
33 |
|
|
|
34 |
|
|
#define s1 26
|
35 |
|
|
#define s2 25
|
36 |
|
|
#define tmp1 19
|
37 |
|
|
#define s2word 20
|
38 |
|
|
#define tmp3 21
|
39 |
|
|
#define tmp7 22
|
40 |
|
|
#define s1word 23
|
41 |
|
|
#define save 1
|
42 |
|
|
#define tmp6 24
|
43 |
|
|
#define tmp5 28
|
44 |
|
|
|
45 |
|
|
ENTRY(strcmp)
|
46 |
|
|
comb,=,n s1,s2,samestring
|
47 |
|
|
comib,=,n 0,s1,s1isnull
|
48 |
|
|
comib,=,n 0,s2,s2isnull
|
49 |
|
|
/* Hope for word alignment. Pick up low two bits of each adress */
|
50 |
|
|
extru,<> s1,31,2,tmp1
|
51 |
|
|
ldwm 4(s1),s1word
|
52 |
|
|
dep,= s2,29,2,tmp1
|
53 |
|
|
b,n case_analysis
|
54 |
|
|
|
55 |
|
|
/* Start looping until null is found in s1 or they mis-compare */
|
56 |
|
|
loop:
|
57 |
|
|
ldwm 4(s2),s2word
|
58 |
|
|
loop_plus:
|
59 |
|
|
uxor,nbz s1word,r0,r0 /* Null in this? */
|
60 |
|
|
b,n nullins1
|
61 |
|
|
comb,=,n s1word,s2word,loop
|
62 |
|
|
ldwm 4(s1),s1word
|
63 |
|
|
|
64 |
|
|
/* The words do not compare equal and s1 does not have a null.
|
65 |
|
|
Need to treat words as unsigned and generate either a positive
|
66 |
|
|
or negative return value */
|
67 |
|
|
wordcomparereturn:
|
68 |
|
|
comclr,>> s1word,s2word,ret0 /*Set ret0 to 0 and skip if greater*/
|
69 |
|
|
ldi -2,ret0 /*Set ret0 to -2 when less */
|
70 |
|
|
bv r0(rp)
|
71 |
|
|
addi 1,ret0,ret0 /*Fix return value to be -1 or +1 */
|
72 |
|
|
|
73 |
|
|
/* s1 has a null. s2 has not been checked. */
|
74 |
|
|
nullins1:
|
75 |
|
|
/*If s2 has no nulls this is simple, but assume that it might
|
76 |
|
|
and fix up s1 to allow the word comparision to work by
|
77 |
|
|
scanning s1 and duplicating all the bytes in s2 below that byte into
|
78 |
|
|
the remainder of s1. A remainder only exists if the zero byte
|
79 |
|
|
is found in the upper three bytes */
|
80 |
|
|
extru,<> s1word,7,8,r0 /*in the first byte? */
|
81 |
|
|
dep,tr s2word,31,24,s1word /*copy low 3 bytes of *s2 into *s1 */
|
82 |
|
|
extru,<> s1word,15,8,r0 /*in the second byte? */
|
83 |
|
|
dep,tr s2word,31,16,s1word /*copy low 2 bytes of *s2 into *s1 */
|
84 |
|
|
extru,<> s1word,23,8,r0 /*in the third byte? */
|
85 |
|
|
dep s2word,31,8,s1word /*copy low 1 byte of *s2 into *s1 */
|
86 |
|
|
/* Do the normal unsigned compare and return */
|
87 |
|
|
comclr,<> s1word,s2word,ret0 /*Set ret0 to 0 and skip if not equal */
|
88 |
|
|
bv,n r0(rp)
|
89 |
|
|
comclr,>> s1word,s2word,ret0 /*Set ret0 to 0 and skip if greater*/
|
90 |
|
|
ldi -2,ret0 /*Set ret0 to -2 when less */
|
91 |
|
|
bv r0(rp)
|
92 |
|
|
addi 1,ret0,ret0 /*Fix return value to be -1 or +1 */
|
93 |
|
|
|
94 |
|
|
/* s1 and s2 are the same string and therefore equal */
|
95 |
|
|
samestring:
|
96 |
|
|
bv r0(rp)
|
97 |
|
|
copy r0,ret0
|
98 |
|
|
/* s1 is null. Treat as string of nulls. Therefore return
|
99 |
|
|
the negative of s2's first byte. s2 cannot be zero. */
|
100 |
|
|
s1isnull:
|
101 |
|
|
ldbs 0(0,s2),ret0
|
102 |
|
|
bv r0(rp)
|
103 |
|
|
sub 0,ret0,ret0
|
104 |
|
|
/* s2 is null. Treat as string of nulls. Therefore return
|
105 |
|
|
s1's first byte. s1 cannot be zero. */
|
106 |
|
|
s2isnull:
|
107 |
|
|
bv r0(rp)
|
108 |
|
|
ldbs 0(0,s1),ret0
|
109 |
|
|
|
110 |
|
|
case_analysis:
|
111 |
|
|
blr tmp1,r0
|
112 |
|
|
nop
|
113 |
|
|
|
114 |
|
|
/*
|
115 |
|
|
Case statement for non-aligned cases (we've already
|
116 |
|
|
checked the aligned case.
|
117 |
|
|
NOTE: for non-aligned cases, the absolute shift value
|
118 |
|
|
gets loaded into tmp3.
|
119 |
|
|
*/
|
120 |
|
|
|
121 |
|
|
/* S2 S1 */
|
122 |
|
|
nop /* 00 00 can't happen */
|
123 |
|
|
nop
|
124 |
|
|
b shifts2 /* 00 01 */
|
125 |
|
|
ldi 8,tmp3 /* load shift count (delay slot) */
|
126 |
|
|
b shifts2 /* 00 10 */
|
127 |
|
|
ldi 16,tmp3 /* load shift count (delay slot) */
|
128 |
|
|
b shifts2 /* 00 11 */
|
129 |
|
|
ldi 24,tmp3 /* load shift count (delay slot) */
|
130 |
|
|
b shifts1_0 /* 01 00 */
|
131 |
|
|
ldi 8,tmp3 /* load shift count (delay slot) */
|
132 |
|
|
b eq_align1 /* 01 01 */
|
133 |
|
|
ldbs,ma 1(s1),s1word
|
134 |
|
|
b shifts2 /* 01 10 */
|
135 |
|
|
ldi 8,tmp3 /* load shift count (delay slot) */
|
136 |
|
|
b shifts2 /* 01 11 */
|
137 |
|
|
ldi 16,tmp3 /* load shift count (delay slot) */
|
138 |
|
|
b shifts1_0 /* 10 00 */
|
139 |
|
|
ldi 16,tmp3 /* load shift count (delay slot) */
|
140 |
|
|
b shifts1 /* 10 01 */
|
141 |
|
|
ldi 8,tmp3 /* load shift count (delay slot) */
|
142 |
|
|
b eq_align2 /* 10 10 */
|
143 |
|
|
ldhs,ma 2(s1),s1word
|
144 |
|
|
b shifts2 /* 10 11 */
|
145 |
|
|
ldi 8,tmp3 /* load shift count (delay slot) */
|
146 |
|
|
b shifts1_0 /* 11 00 */
|
147 |
|
|
ldi 24,tmp3 /* load shift count (delay slot) */
|
148 |
|
|
b shifts1 /* 11 01 */
|
149 |
|
|
ldi 16,tmp3 /* load shift count (delay slot) */
|
150 |
|
|
b shifts1 /* 11 10 */
|
151 |
|
|
ldi 8,tmp3 /* load shift count (delay slot) */
|
152 |
|
|
ldbs,ma 1(s1),s1word /* 11 11 */
|
153 |
|
|
ldbs,ma 1(s2),s2word
|
154 |
|
|
sub,= s1word,s2word,ret0 /* if not equal, we can return now */
|
155 |
|
|
bv,n r0(rp)
|
156 |
|
|
comclr,<> s1word,r0,ret0
|
157 |
|
|
bv,n r0(rp)
|
158 |
|
|
b loop /* fall into main loop */
|
159 |
|
|
ldwm 4(s1),s1word
|
160 |
|
|
|
161 |
|
|
eq_align1:
|
162 |
|
|
ldbs,ma 1(s2),s2word
|
163 |
|
|
sub,= s1word,s2word,ret0 /* if not equal, we can return now */
|
164 |
|
|
bv,n r0(rp)
|
165 |
|
|
comclr,<> s1word,r0,ret0
|
166 |
|
|
bv,n r0(rp)
|
167 |
|
|
/* fall through to half-word aligned case */
|
168 |
|
|
ldhs,ma 2(s1),s1word /* load next halfword */
|
169 |
|
|
eq_align2:
|
170 |
|
|
ldhs,ma 2(s2),s2word /* load next halfword */
|
171 |
|
|
/* form the mask: 0xffff0000 and mask leading nulls in s1word and s2word
|
172 |
|
|
so that we can fall into the main loop with word aligned data */
|
173 |
|
|
ldi 16,save
|
174 |
|
|
mtctl save,r11
|
175 |
|
|
zvdepi -2,32,save
|
176 |
|
|
or save,s1word,s1word
|
177 |
|
|
b loop_plus /* fall into main loop */
|
178 |
|
|
or save,s2word,s2word
|
179 |
|
|
|
180 |
|
|
/* s2's alignment is greater than s1's alignment, so we will shift s1 */
|
181 |
|
|
shifts1_0:
|
182 |
|
|
addi -4,s1,s1 /* fix up s1 due to earlier read */
|
183 |
|
|
shifts1:
|
184 |
|
|
extru s1,31,2,tmp1
|
185 |
|
|
extru s2,31,2,tmp5
|
186 |
|
|
dep r0,31,2,s1 /* Compute word address of s1 */
|
187 |
|
|
dep r0,31,2,s2 /* Compute word address of s2 */
|
188 |
|
|
ldwm 4(s1),s1word /* get first word of s1 */
|
189 |
|
|
ldwm 4(s2),s2word /* get first word of s2 */
|
190 |
|
|
combt,=,n r0,tmp1,masks2 /* Do we need to mask beginning of s1 */
|
191 |
|
|
sh3add tmp1,r0,save /* save now has number of bits to mask */
|
192 |
|
|
mtctl save,r11
|
193 |
|
|
zvdepi -2,32,save /* load save with proper mask */
|
194 |
|
|
or save,s1word,s1word
|
195 |
|
|
masks2:
|
196 |
|
|
sh3add tmp5,r0,save /* save now has number of bits to mask */
|
197 |
|
|
mtctl save,r11
|
198 |
|
|
zvdepi -2,32,save /* load save with proper mask */
|
199 |
|
|
or save,s2word,s2word
|
200 |
|
|
ldi -1,tmp7 /* load tmp7 with 0xffffffff */
|
201 |
|
|
mtctl tmp3,r11 /* Move shift amount to CR11 */
|
202 |
|
|
more: uxor,nbz s1word,r0,r0 /* Is there a null in s1? */
|
203 |
|
|
b ends1
|
204 |
|
|
vshd tmp7,s1word,save
|
205 |
|
|
combf,=,n save,s2word,cmps1
|
206 |
|
|
ldwm 4(s1),tmp7
|
207 |
|
|
ldwm 4(s2),s2word
|
208 |
|
|
uxor,nbz tmp7,r0,r0 /* is there a null in s1? */
|
209 |
|
|
b ends1_0
|
210 |
|
|
vshd s1word,tmp7,save
|
211 |
|
|
combf,=,n save,s2word,cmps1
|
212 |
|
|
ldwm 4(s1),s1word
|
213 |
|
|
b more
|
214 |
|
|
ldwm 4(s2),s2word
|
215 |
|
|
|
216 |
|
|
cmps1: movb,tr save,s1word,wordcomparereturn
|
217 |
|
|
nop
|
218 |
|
|
|
219 |
|
|
ends1_0:
|
220 |
|
|
copy tmp7,s1word /* move tmp7 to s1word */
|
221 |
|
|
ends1:
|
222 |
|
|
combf,=,n save,s2word,nullins1 /* branch if no match */
|
223 |
|
|
copy save,s1word /* delay slot */
|
224 |
|
|
/* At this point, we know that we've read a null */
|
225 |
|
|
/* from s1, so we can't read more from s1 */
|
226 |
|
|
uxor,nbz save,r0,r0 /* are the strings equal? */
|
227 |
|
|
b,n samestring
|
228 |
|
|
vshd s1word,r0,s1word
|
229 |
|
|
b nullins1
|
230 |
|
|
ldwm 4(s2),s2word
|
231 |
|
|
|
232 |
|
|
/* s1's alignment is greater than s2's alignment, so we will shift s2 */
|
233 |
|
|
shifts2:
|
234 |
|
|
extru s1,31,2,tmp1
|
235 |
|
|
extru s2,31,2,tmp5
|
236 |
|
|
dep r0,31,2,s1 /* Compute word address of s1 */
|
237 |
|
|
dep r0,31,2,s2 /* Compute word address of s2 */
|
238 |
|
|
ldwm 4(s2),s2word /* get first word of s2 */
|
239 |
|
|
ldwm 4(s1),s1word /* get first word of s1 */
|
240 |
|
|
combt,=,n r0,tmp5,masks1 /* Do we need to mask beginning of s2 */
|
241 |
|
|
sh3add tmp5,r0,save /* save now has number of bits to mask */
|
242 |
|
|
mtctl save,r11
|
243 |
|
|
zvdepi -2,32,save /* load save with proper mask */
|
244 |
|
|
or save,s2word,s2word
|
245 |
|
|
masks1:
|
246 |
|
|
sh3add tmp1,r0,save /* save now has number of bits to mask */
|
247 |
|
|
mtctl save,r11
|
248 |
|
|
zvdepi -2,32,save /* load save with proper mask */
|
249 |
|
|
or save,s1word,s1word
|
250 |
|
|
ldi -1,tmp7 /* load tmp7 with 0xffffffff */
|
251 |
|
|
mtctl tmp3,r11 /* Move shift amount to CR11 */
|
252 |
|
|
more1: uxor,nbz s2word,r0,r0 /* is there a null in s2? */
|
253 |
|
|
b ends2
|
254 |
|
|
vshd tmp7,s2word,save
|
255 |
|
|
combf,=,n s1word,save,cmps2
|
256 |
|
|
ldwm 4(s2),tmp7
|
257 |
|
|
ldwm 4(s1),s1word
|
258 |
|
|
uxor,nbz tmp7,r0,r0 /* is there a null in s2? */
|
259 |
|
|
b ends2_0
|
260 |
|
|
vshd s2word,tmp7,save
|
261 |
|
|
combf,=,n s1word,save,cmps2
|
262 |
|
|
ldwm 4(s2),s2word
|
263 |
|
|
b more1
|
264 |
|
|
ldwm 4(s1),s1word
|
265 |
|
|
|
266 |
|
|
cmps2: movb,tr save,s2word,wordcomparereturn
|
267 |
|
|
nop
|
268 |
|
|
|
269 |
|
|
ends2_0:
|
270 |
|
|
copy tmp7,s2word /* move tmp7 to s2word */
|
271 |
|
|
ends2:
|
272 |
|
|
combf,=,n s1word,save,nullins1 /* branch if no match */
|
273 |
|
|
copy save,s2word /* delay slot */
|
274 |
|
|
/* At this point, we know that we've read a null */
|
275 |
|
|
/* from s2, so we can't read more from s2 */
|
276 |
|
|
uxor,nbz save,r0,r0 /* are the strings equal? */
|
277 |
|
|
b,n samestring
|
278 |
|
|
vshd s2word,r0,s2word
|
279 |
|
|
b nullins1
|
280 |
|
|
ldwm 4(s1),s1word
|
281 |
|
|
|
282 |
|
|
EXIT(strcmp)
|