1/* Optimized strcasecmp implementation for PowerPC64.
2   Copyright (C) 2011-2022 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#include <locale-defines.h>
21
22/* int [r3] strcasecmp (const char *s1 [r3], const char *s2 [r4] )
23
24   or if defined USE_IN_EXTENDED_LOCALE_MODEL:
25
26   int [r3] strcasecmp_l (const char *s1 [r3], const char *s2 [r4],
27                          locale_t loc [r5]) */
28
29#ifndef STRCMP
30# define __STRCMP __strcasecmp
31# define STRCMP   strcasecmp
32#endif
33
34#ifndef USE_IN_EXTENDED_LOCALE_MODEL
35ENTRY (__STRCMP)
36	CALL_MCOUNT 2
37#else
38ENTRY_TOCLESS (__STRCMP)
39	CALL_MCOUNT 3
40#endif
41
42#define rRTN	r3	/* Return value */
43#define rSTR1	r5	/* 1st string */
44#define rSTR2	r4	/* 2nd string */
45#define rLOCARG	r5	/* 3rd argument: locale_t */
46#define rCHAR1	r6	/* Byte read from 1st string */
47#define rCHAR2	r7	/* Byte read from 2nd string */
48#define rADDR1	r8	/* Address of tolower(rCHAR1) */
49#define rADDR2	r12	/* Address of tolower(rCHAR2) */
50#define rLWR1	r8	/* Word tolower(rCHAR1) */
51#define rLWR2	r12	/* Word tolower(rCHAR2) */
52#define rTMP	r9
53#define rLOC	r11	/* Default locale address */
54
55	cmpd	cr7, r3, r4
56#ifndef USE_IN_EXTENDED_LOCALE_MODEL
57	ld 	rTMP, __libc_tsd_LOCALE@got@tprel(r2)
58	add 	rLOC, rTMP, __libc_tsd_LOCALE@tls
59	ld	rLOC, 0(rLOC)
60#else
61	mr	rLOC, rLOCARG
62#endif
63	ld	rLOC, LOCALE_CTYPE_TOLOWER(rLOC)
64	mr	rSTR1, rRTN
65	li	rRTN, 0
66	beqlr	cr7
67
68
69	/* Unrolling loop for POWER: loads are done with 'lbz' plus
70	offset and string descriptors are only updated in the end
71	of loop unrolling. */
72
73	lbz	rCHAR1, 0(rSTR1)	/* Load char from s1 */
74	lbz	rCHAR2, 0(rSTR2)	/* Load char from s2 */
75L(loop):
76	cmpdi	rCHAR1, 0		/* *s1 == '\0' ? */
77	sldi	rADDR1, rCHAR1, 2	/* Calculate address for tolower(*s1) */
78	sldi	rADDR2, rCHAR2, 2	/* Calculate address for tolower(*s2) */
79	lwzx	rLWR1, rLOC, rADDR1	/* Load tolower(*s1) */
80	lwzx	rLWR2, rLOC, rADDR2	/* Load tolower(*s2) */
81	cmpw	cr1, rLWR1, rLWR2	/* r = tolower(*s1) == tolower(*s2) ? */
82	crorc	4*cr1+eq,eq,4*cr1+eq	/* (*s1 != '\0') || (r == 1) */
83	beq	cr1, L(done)
84	lbz	rCHAR1, 1(rSTR1)
85	lbz	rCHAR2, 1(rSTR2)
86	cmpdi	rCHAR1, 0
87	sldi	rADDR1, rCHAR1, 2
88	sldi	rADDR2, rCHAR2, 2
89	lwzx	rLWR1, rLOC, rADDR1
90	lwzx	rLWR2, rLOC, rADDR2
91	cmpw	cr1, rLWR1, rLWR2
92	crorc	4*cr1+eq,eq,4*cr1+eq
93	beq	cr1, L(done)
94	lbz	rCHAR1, 2(rSTR1)
95	lbz	rCHAR2, 2(rSTR2)
96	cmpdi	rCHAR1, 0
97	sldi	rADDR1, rCHAR1, 2
98	sldi	rADDR2, rCHAR2, 2
99	lwzx	rLWR1, rLOC, rADDR1
100	lwzx	rLWR2, rLOC, rADDR2
101	cmpw	cr1, rLWR1, rLWR2
102	crorc	4*cr1+eq,eq,4*cr1+eq
103	beq	cr1, L(done)
104	lbz	rCHAR1, 3(rSTR1)
105	lbz	rCHAR2, 3(rSTR2)
106	cmpdi	rCHAR1, 0
107	/* Increment both string descriptors */
108	addi	rSTR1, rSTR1, 4
109	addi	rSTR2, rSTR2, 4
110	sldi	rADDR1, rCHAR1, 2
111	sldi	rADDR2, rCHAR2, 2
112	lwzx	rLWR1, rLOC, rADDR1
113	lwzx	rLWR2, rLOC, rADDR2
114	cmpw	cr1, rLWR1, rLWR2
115	crorc	4*cr1+eq,eq,4*cr1+eq
116	beq     cr1,L(done)
117	lbz	rCHAR1, 0(rSTR1)	/* Load char from s1 */
118	lbz	rCHAR2, 0(rSTR2)	/* Load char from s2 */
119	b	L(loop)
120L(done):
121	subf	r0, rLWR2, rLWR1
122	extsw	rRTN, r0
123	blr
124END (__STRCMP)
125
126weak_alias (__STRCMP, STRCMP)
127libc_hidden_builtin_def (__STRCMP)
128