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