1/* Optimized strcmp implementation for PowerPC.
2   Copyright (C) 1997-2021 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library; if not, see
17   <https://www.gnu.org/licenses/>.  */
18
19#include <sysdep.h>
20
21/* See strlen.s for comments on how the end-of-string testing works.  */
22
23/* int [r3] strcmp (const char *s1 [r3], const char *s2 [r4])  */
24
25EALIGN (strcmp, 4, 0)
26
27#define rTMP2	r0
28#define rRTN	r3
29#define rSTR1	r3	/* first string arg */
30#define rSTR2	r4	/* second string arg */
31#define rWORD1	r5	/* current word in s1 */
32#define rWORD2	r6	/* current word in s2 */
33#define rFEFE	r7	/* constant 0xfefefeff (-0x01010101) */
34#define r7F7F	r8	/* constant 0x7f7f7f7f */
35#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f) */
36#define rBITDIF	r10	/* bits that differ in s1 & s2 words */
37#define rTMP	r11
38
39
40	or	rTMP, rSTR2, rSTR1
41	clrlwi.	rTMP, rTMP, 30
42	lis	rFEFE, -0x101
43	bne	L(unaligned)
44
45	lwz	rWORD1, 0(rSTR1)
46	lwz	rWORD2, 0(rSTR2)
47	lis	r7F7F, 0x7f7f
48	addi	rFEFE, rFEFE, -0x101
49	addi	r7F7F, r7F7F, 0x7f7f
50	b	L(g1)
51
52L(g0):	lwzu	rWORD1, 4(rSTR1)
53	bne	cr1, L(different)
54	lwzu	rWORD2, 4(rSTR2)
55L(g1):	add	rTMP, rFEFE, rWORD1
56	nor	rNEG, r7F7F, rWORD1
57	and.	rTMP, rTMP, rNEG
58	cmpw	cr1, rWORD1, rWORD2
59	beq+	L(g0)
60
61/* OK. We've hit the end of the string. We need to be careful that
62   we don't compare two strings as different because of gunk beyond
63   the end of the strings...  */
64#ifdef __LITTLE_ENDIAN__
65L(endstring):
66	addi    rTMP2, rTMP, -1
67	andc    rTMP2, rTMP2, rTMP
68	rlwimi	rTMP2, rTMP2, 1, 0, 30
69	and	rWORD2, rWORD2, rTMP2		/* Mask off gunk.  */
70	and	rWORD1, rWORD1, rTMP2
71	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
72	rlwinm	rTMP, rWORD1, 8, 0xffffffff
73	rlwimi	rTMP2, rWORD2, 24, 0, 7
74	rlwimi	rTMP, rWORD1, 24, 0, 7
75	rlwimi	rTMP2, rWORD2, 24, 16, 23
76	rlwimi	rTMP, rWORD1, 24, 16, 23
77	xor.	rBITDIF, rTMP, rTMP2
78	sub	rRTN, rTMP, rTMP2
79	bgelr+
80	ori	rRTN, rTMP2, 1
81	blr
82
83L(different):
84	lwz	rWORD1, -4(rSTR1)
85	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
86	rlwinm	rTMP, rWORD1, 8, 0xffffffff
87	rlwimi	rTMP2, rWORD2, 24, 0, 7
88	rlwimi	rTMP, rWORD1, 24, 0, 7
89	rlwimi	rTMP2, rWORD2, 24, 16, 23
90	rlwimi	rTMP, rWORD1, 24, 16, 23
91	xor.	rBITDIF, rTMP, rTMP2
92	sub	rRTN, rTMP, rTMP2
93	bgelr+
94	ori	rRTN, rTMP2, 1
95	blr
96
97#else
98L(endstring):
99	and	rTMP, r7F7F, rWORD1
100	beq	cr1, L(equal)
101	add	rTMP, rTMP, r7F7F
102	xor.	rBITDIF, rWORD1, rWORD2
103	andc	rNEG, rNEG, rTMP
104	blt-	L(highbit)
105	cntlzw	rBITDIF, rBITDIF
106	cntlzw	rNEG, rNEG
107	addi	rNEG, rNEG, 7
108	cmpw	cr1, rNEG, rBITDIF
109	sub	rRTN, rWORD1, rWORD2
110	bgelr+	cr1
111L(equal):
112	li	rRTN, 0
113	blr
114
115L(different):
116	lwz	rWORD1, -4(rSTR1)
117	xor.	rBITDIF, rWORD1, rWORD2
118	sub	rRTN, rWORD1, rWORD2
119	bgelr+
120L(highbit):
121	ori	rRTN, rWORD2, 1
122	blr
123#endif
124
125/* Oh well.  In this case, we just do a byte-by-byte comparison.  */
126	.align 4
127L(unaligned):
128	lbz	rWORD1, 0(rSTR1)
129	lbz	rWORD2, 0(rSTR2)
130	b	L(u1)
131
132L(u0):	lbzu	rWORD1, 1(rSTR1)
133	bne-	L(u4)
134	lbzu	rWORD2, 1(rSTR2)
135L(u1):	cmpwi	cr1, rWORD1, 0
136	beq-	cr1, L(u3)
137	cmpw	rWORD1, rWORD2
138	bne-	L(u3)
139	lbzu	rWORD1, 1(rSTR1)
140	lbzu	rWORD2, 1(rSTR2)
141	cmpwi	cr1, rWORD1, 0
142	cmpw	rWORD1, rWORD2
143	bne+	cr1, L(u0)
144L(u3):	sub	rRTN, rWORD1, rWORD2
145	blr
146L(u4):	lbz	rWORD1, -1(rSTR1)
147	sub	rRTN, rWORD1, rWORD2
148	blr
149END (strcmp)
150libc_hidden_builtin_def (strcmp)
151