xref: /minix3/common/lib/libc/arch/powerpc/string/memcmp.S (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc/* $NetBSD: memcmp.S,v 1.4 2013/07/04 20:57:59 matt Exp $ */
2b6cbf720SGianluca Guida
3b6cbf720SGianluca Guida/* stropt/memcmp.S, pl_string_common, pl_linux 10/11/04 11:45:35
4b6cbf720SGianluca Guida * ==========================================================================
5b6cbf720SGianluca Guida * Optimized memcmp implementation for IBM PowerPC 405/440.
6b6cbf720SGianluca Guida *
7b6cbf720SGianluca Guida *	Copyright (c) 2003, IBM Corporation
8b6cbf720SGianluca Guida *	All rights reserved.
9b6cbf720SGianluca Guida *
10b6cbf720SGianluca Guida *	Redistribution and use in source and binary forms, with or
11b6cbf720SGianluca Guida *	without modification, are permitted provided that the following
12b6cbf720SGianluca Guida *	conditions are met:
13b6cbf720SGianluca Guida *
14b6cbf720SGianluca Guida *	* Redistributions of source code must retain the above
15b6cbf720SGianluca Guida *	copyright notice, this list of conditions and the following
16b6cbf720SGianluca Guida *	disclaimer.
17b6cbf720SGianluca Guida *	* Redistributions in binary form must reproduce the above
18b6cbf720SGianluca Guida *	copyright notice, this list of conditions and the following
19b6cbf720SGianluca Guida *	disclaimer in the documentation and/or other materials
20b6cbf720SGianluca Guida *	provided with the distribution.
21b6cbf720SGianluca Guida *	* Neither the name of IBM nor the names of its contributors
22b6cbf720SGianluca Guida *	may be used to endorse or promote products derived from this
23b6cbf720SGianluca Guida *	software without specific prior written permission.
24b6cbf720SGianluca Guida *
25b6cbf720SGianluca Guida *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26b6cbf720SGianluca Guida *	CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27b6cbf720SGianluca Guida *	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28b6cbf720SGianluca Guida *	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29b6cbf720SGianluca Guida *	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
30b6cbf720SGianluca Guida *	BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31b6cbf720SGianluca Guida *	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32b6cbf720SGianluca Guida *	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33b6cbf720SGianluca Guida *	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
34b6cbf720SGianluca Guida *	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35b6cbf720SGianluca Guida *	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36b6cbf720SGianluca Guida *	USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37b6cbf720SGianluca Guida *
38b6cbf720SGianluca Guida * ==========================================================================
39b6cbf720SGianluca Guida *
40b6cbf720SGianluca Guida * Function: Compare two character strings (up to n characters)
41b6cbf720SGianluca Guida *
42b6cbf720SGianluca Guida *		int memcmp(const char *s1, const char *s2, int n)
43b6cbf720SGianluca Guida *
44b6cbf720SGianluca Guida * Input:	r3 - buffer 1 address
45b6cbf720SGianluca Guida *	 	r4 - buffer 2 address
46b6cbf720SGianluca Guida *	 	r5 - maximum characters to compare
47b6cbf720SGianluca Guida * Output: r3 <0 (less), 0 (equal), >0 (greater)
48b6cbf720SGianluca Guida *
49b6cbf720SGianluca Guida * ==========================================================================
50b6cbf720SGianluca Guida */
51b6cbf720SGianluca Guida
52b6cbf720SGianluca Guida#include <machine/asm.h>
53b6cbf720SGianluca Guida
54b6cbf720SGianluca Guida        .text
55b6cbf720SGianluca Guida        .align 4
56b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memcmp(const void *, const void *, size_t) */
57b6cbf720SGianluca GuidaENTRY(memcmp)
58b6cbf720SGianluca Guida
59b6cbf720SGianluca Guida	/*
60b6cbf720SGianluca Guida	 * Check count passed in R5. If zero, return 0; otherwise continue.
61b6cbf720SGianluca Guida	 */
62b6cbf720SGianluca Guida	cmpwi	%r5,0
63b6cbf720SGianluca Guida	beq-	ret_0;
64b6cbf720SGianluca Guida
65b6cbf720SGianluca Guida	/*
66b6cbf720SGianluca Guida	 * Most of the time the difference is found in the first
67b6cbf720SGianluca Guida	 * several bytes.  The following code minimizes the number
68b6cbf720SGianluca Guida	 * of load operations for short compares.
69b6cbf720SGianluca Guida	 */
70b6cbf720SGianluca Guida
71b6cbf720SGianluca Guida	mr	%r11, %r3		/* Save buffer 1		*/
72b6cbf720SGianluca Guida
73b6cbf720SGianluca Guidaagain:
74b6cbf720SGianluca Guida
75b6cbf720SGianluca Guida	not	%r10, %r4		/* buffer 2: bytes to page bdy	*/
76b6cbf720SGianluca Guida	rlwinm.	%r10, %r10,29,23,31	/* buffer 2: dwords to page bdy	*/
77b6cbf720SGianluca Guida	beq-	bytebybyte		/* If < 8 bytes to the page bdy */
78b6cbf720SGianluca Guida					/* do byte by byte		*/
79b6cbf720SGianluca Guida	lwz	%r8, 0(%r4)		/* load 1st buffer 2 word	*/
80b6cbf720SGianluca Guida
81b6cbf720SGianluca Guida	not	%r12, %r11		/* buffer 1: bytes to page bdy	*/
82b6cbf720SGianluca Guida	rlwinm.	%r12, %r12,29,23,31	/* buffer 1: dwords to page bdy	*/
83b6cbf720SGianluca Guida	beq-	bytebybyte		/* If < 8 bytes to the page bdy */
84b6cbf720SGianluca Guida					/* do byte by byte		*/
85b6cbf720SGianluca Guida	lwz	%r6, 0(%r11)		/* load 1st buffer 1 word	*/
86b6cbf720SGianluca Guida
87b6cbf720SGianluca Guida	cmpwi	%r5, 4			/* If remaining count <= 4	*/
88b6cbf720SGianluca Guida	ble+	first4			/* handle specially.	DWG	*/
89b6cbf720SGianluca Guida
90b6cbf720SGianluca Guida	cmplw	%r8, %r6		/* compare buffer 2 and buffer 1*/
91b6cbf720SGianluca Guida	bne+	all_done		/* different => we're done	*/
92b6cbf720SGianluca Guida
93b6cbf720SGianluca Guida	lwzu	%r9, 4(%r4)		/* load 2nd buffer 2 word	*/
94b6cbf720SGianluca Guida	lwzu	%r7, 4(%r11)		/* load 2nd buffer 1 word	*/
95b6cbf720SGianluca Guida
96b6cbf720SGianluca Guida	cmpwi	%r5, 8			/* If remaining count <= 8	*/
97b6cbf720SGianluca Guida	ble+	last4			/* handle specially.	DWG	*/
98b6cbf720SGianluca Guida
99b6cbf720SGianluca Guida	cmplw	%r9, %r7		/* compare buffer 2 and buffer 1*/
100b6cbf720SGianluca Guida	bne+	all_done		/* different => we're done	*/
101b6cbf720SGianluca Guida
102b6cbf720SGianluca Guida	addi	%r5, %r5, -8		/* Update character counter DWG */
103b6cbf720SGianluca Guida	addi	%r10, %r4, 0x0004	/* DWG*/
104b6cbf720SGianluca Guida	not	%r10, %r10		/* buffer 2: bytes to page bdy DWG */
105b6cbf720SGianluca Guida	rlwinm.	%r10, %r10,29,23,31	/* buffer 2: dwords to page bdy	DWG */
106b6cbf720SGianluca Guida	addi	%r12, %r11, 0x0004	/* DWG */
107b6cbf720SGianluca Guida	not	%r12, %r12		/* buffer 1: bytes to page bdy DWG */
108b6cbf720SGianluca Guida	rlwinm.	%r12, %r12,29,23,31	/* buffer 1: dwords to page bdy	DWG */
109b6cbf720SGianluca Guida
110b6cbf720SGianluca Guida	/* The following section prior to loop: figures out whether	*/
111b6cbf720SGianluca Guida	/* the buffer 1 or buffer 2 is closer to the page boundary.	*/
112b6cbf720SGianluca Guida	/* The main loop count is then set up to reflect the number of	*/
113b6cbf720SGianluca Guida	/* double words of the buffer that is closest			*/
114b6cbf720SGianluca Guida
115b6cbf720SGianluca Guida	cmpw	%r10, %r12		/* Find closest			*/
116b6cbf720SGianluca Guida	blt	lt
117b6cbf720SGianluca Guida
118b6cbf720SGianluca Guida	mr	%r10, %r12
119b6cbf720SGianluca Guida
120b6cbf720SGianluca Guidalt:
121b6cbf720SGianluca Guida
122b6cbf720SGianluca Guida	srwi	%r12, %r5, 3		/* Double check the total count */
123b6cbf720SGianluca Guida	cmpw	%r10, %r12		/* limitation			*/
124b6cbf720SGianluca Guida	blt	lt2
125b6cbf720SGianluca Guida
126b6cbf720SGianluca Guida	mr	%r10, %r12		/* DWG */
127b6cbf720SGianluca Guidalt2:					/* DWG */
128b6cbf720SGianluca Guida	cmpwi	%r10, 0			/* DWG */
129b6cbf720SGianluca Guida	bne	lt3			/* DWG */
130b6cbf720SGianluca Guida	addi	%r4, %r4, 0x0004	/* DWG */
131b6cbf720SGianluca Guida	addi	%r11,%r11,0x0004	/* DWG */
132b6cbf720SGianluca Guida	b	again			/* DWG */
133b6cbf720SGianluca Guidalt3:					/* DWG */
134b6cbf720SGianluca Guida	mtctr	%r10			/* dword count for loop		*/
135b6cbf720SGianluca Guida	lwzu	%r6, 4(%r11)		/* pre-load buffer 1 word	*/
136b6cbf720SGianluca Guida
137b6cbf720SGianluca Guida	b	in			/* To the loop			*/
138b6cbf720SGianluca Guida
139b6cbf720SGianluca Guidaloop:					/* main loop			*/
140b6cbf720SGianluca Guida
141b6cbf720SGianluca Guida	cmplw	%r8, %r6		/* Compare first buffer 2 word	*/
142b6cbf720SGianluca Guida	bne-	all_done		/* with first buffer 1 word	*/
143b6cbf720SGianluca Guida					/* If different, we're done	*/
144b6cbf720SGianluca Guida	cmplw	%r9, %r7		/* Compare second buffer 2 word	*/
145b6cbf720SGianluca Guida					/* with second buffer 1 word	*/
146b6cbf720SGianluca Guida	lwzu	%r6, 4(%r11)		/* pre-load buffer 1 word	*/
147b6cbf720SGianluca Guida
148b6cbf720SGianluca Guida	bne-	all_done		/* If different, we're done	*/
149b6cbf720SGianluca Guida
150b6cbf720SGianluca Guidain:
151b6cbf720SGianluca Guida
152b6cbf720SGianluca Guida	lwzu	%r7, 4(%r11)		/* pre-load buffer 1 word	*/
153b6cbf720SGianluca Guida	lwzu	%r8, 4(%r4)		/* pre-load buffer 2 word	*/
154b6cbf720SGianluca Guida	lwzu	%r9, 4(%r4)		/* pre-load buffer 2 word	*/
155b6cbf720SGianluca Guida
156b6cbf720SGianluca Guida	bdnz+	loop			/* Do more DW's if cnt > 0	*/
157b6cbf720SGianluca Guida
158b6cbf720SGianluca Guida	/*mfctr	%r12*/ /*DWG*/		/* number of dwords left	*/
159b6cbf720SGianluca Guida	/*subf	%r10, %r12, %r10*/ /*DWG*//* number of dwords compared	*/
160b6cbf720SGianluca Guida	slwi	%r10, %r10, 3
161b6cbf720SGianluca Guida	subf	%r5, %r10, %r5		/* adjust byte counter		*/
162b6cbf720SGianluca Guida	/*bne+	partial*/ /*DWG*/	/* If less than 8 bytes, handle */
163b6cbf720SGianluca Guida					/* specially			*/
164b6cbf720SGianluca Guida	/*cmpwi	%r5, 8*/		/* Removed.		 DWG */
165b6cbf720SGianluca Guida	/*blt	partial*/		/* Removed.		 DWG */
166b6cbf720SGianluca Guida
167b6cbf720SGianluca Guida	/*addic	%r5, %r5, -8*/ /*DWG*/	/* Subtract two words from count*/
168b6cbf720SGianluca Guida
169b6cbf720SGianluca Guida	cmplw	%r8, %r6		/* compare last dword		*/
170b6cbf720SGianluca Guida	addi	%r4, %r4, 4
171b6cbf720SGianluca Guida	bne-	all_done
172b6cbf720SGianluca Guida
173b6cbf720SGianluca Guida	cmplw	%r9, %r7
174b6cbf720SGianluca Guida	addi	%r11, %r11, 4
175b6cbf720SGianluca Guida	bne-	all_done
176b6cbf720SGianluca Guida
177b6cbf720SGianluca Guidabytebybyte:
178b6cbf720SGianluca Guida
179b6cbf720SGianluca Guida	/* We've gotten close to a page boundary: do a byte-byte-byte
180b6cbf720SGianluca Guida	 * compare for the following 8 bytes, and then go back to
181b6cbf720SGianluca Guida	 * the full-word compare loop.
182b6cbf720SGianluca Guida	 */
183b6cbf720SGianluca Guida
184b6cbf720SGianluca Guida	li	%r3, 8			/* loop count			*/
185b6cbf720SGianluca Guida	cmpw	%r3, %r5		/* take min(8, counter)		*/
186b6cbf720SGianluca Guida	ble	f2
187b6cbf720SGianluca Guida
188b6cbf720SGianluca Guida	mr.	%r3, %r5
189b6cbf720SGianluca Guida
190b6cbf720SGianluca Guida	beqlr
191b6cbf720SGianluca Guida
192b6cbf720SGianluca Guidaf2:
193b6cbf720SGianluca Guida
194b6cbf720SGianluca Guida	mtctr	%r3
195b6cbf720SGianluca Guida	subf	%r5, %r3, %r5		/* adjust counter		*/
196b6cbf720SGianluca Guida
197b6cbf720SGianluca Guidabbb:
198b6cbf720SGianluca Guida
199b6cbf720SGianluca Guida	lbz	%r6, 0(%r11)		/* byte copy loop		*/
200b6cbf720SGianluca Guida
201b6cbf720SGianluca Guida	addi	%r11, %r11, 1
202b6cbf720SGianluca Guida
203b6cbf720SGianluca Guida	lbz	%r8, 0(%r4)
204b6cbf720SGianluca Guida
205b6cbf720SGianluca Guida	addi	%r4, %r4, 1
206b6cbf720SGianluca Guida
207b6cbf720SGianluca Guida	cmplw	%r8, %r6
208b6cbf720SGianluca Guida
209*84d9c625SLionel Sambuc	bdnzt	eq, bbb
210b6cbf720SGianluca Guida
211b6cbf720SGianluca Guida	bne	all_done
212b6cbf720SGianluca Guida
213b6cbf720SGianluca Guida	cmpwi	%r5, 0
214b6cbf720SGianluca Guida	bgt	again			/* handle the rest		*/
215b6cbf720SGianluca Guida
216b6cbf720SGianluca Guida	xor	%r3,%r3,%r3
217b6cbf720SGianluca Guida
218b6cbf720SGianluca Guida	blr
219b6cbf720SGianluca Guida
220b6cbf720SGianluca Guida#if 0 /* Removed code section. DWG */
221b6cbf720SGianluca Guidapartial:
222b6cbf720SGianluca Guida
223b6cbf720SGianluca Guida	mr.	%r3, %r5
224b6cbf720SGianluca Guida
225b6cbf720SGianluca Guida	beqlr				/* If count -> 0, we're done	*/
226b6cbf720SGianluca Guida
227b6cbf720SGianluca Guidaf1:
228b6cbf720SGianluca Guida
229b6cbf720SGianluca Guida	subfic	%r3, %r3, 4		/* zero/end in first word?	*/
230b6cbf720SGianluca Guida	cmpwi	%r3, 0
231b6cbf720SGianluca Guida	blt	last4
232b6cbf720SGianluca Guida#endif /* DWG */
233b6cbf720SGianluca Guida
234b6cbf720SGianluca Guidafirst4:
235b6cbf720SGianluca Guida	subfic	%r3, %r5, 4		/* If count <= 4, handle 	*/
236b6cbf720SGianluca Guida	rlwinm	%r3, %r3, 3, 0, 31	/* count *= 8			*/
237b6cbf720SGianluca Guida	srw	%r6, %r6, %r3		/* align 1st buffer 1 word	*/
238b6cbf720SGianluca Guida	srw	%r8, %r8, %r3		/* align 1st buffer 2 word	*/
239b6cbf720SGianluca Guida
240b6cbf720SGianluca Guida	cmplw	%r8, %r6		/* get result			*/
241b6cbf720SGianluca Guida	bne	all_done
242b6cbf720SGianluca Guida	xor	%r3,%r3,%r3
243b6cbf720SGianluca Guida	blr
244b6cbf720SGianluca Guida
245b6cbf720SGianluca Guidalast4:
246b6cbf720SGianluca Guida	subfic	%r10, %r5, 8		/*DWG*/
247b6cbf720SGianluca Guida	rlwinm	%r10, %r10, 3, 0, 31	/* count *= 8			*/
248b6cbf720SGianluca Guida	srw	%r7, %r7, %r10		/* align 2nd buffer 1 word	*/
249b6cbf720SGianluca Guida	srw	%r9, %r9, %r10		/* align 2nd buffer 2 word	*/
250b6cbf720SGianluca Guida
251b6cbf720SGianluca Guida	cmplw	%r9, %r7		/* get result			*/
252b6cbf720SGianluca Guida	bne	all_done
253b6cbf720SGianluca Guidaret_0:
254b6cbf720SGianluca Guida	xor	%r3,%r3,%r3		/* Equal result		 */
255b6cbf720SGianluca Guida	blr
256b6cbf720SGianluca Guida
257b6cbf720SGianluca Guidaall_done:
258b6cbf720SGianluca Guida
259b6cbf720SGianluca Guida	blt	finish_lt
260b6cbf720SGianluca Guida
261b6cbf720SGianluca Guida	addi	%r3,0,-1		/* Less than result		*/
262b6cbf720SGianluca Guida
263b6cbf720SGianluca Guida	blr
264b6cbf720SGianluca Guida
265b6cbf720SGianluca Guidafinish_lt:
266b6cbf720SGianluca Guida
267b6cbf720SGianluca Guida	addi	%r3,0,1			/* Greater than result		*/
268b6cbf720SGianluca Guida
269b6cbf720SGianluca Guida	blr
270b6cbf720SGianluca GuidaEND(memcmp)
271