Blame sysdeps/powerpc/powerpc64/power8/strcasecmp.S

Packit 6c4009
/* Optimized strcasecmp implementation for PowerPC64.
Packit 6c4009
   Copyright (C) 2016-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <locale-defines.h>
Packit 6c4009
Packit 6c4009
/* int [r3] strcasecmp (const char *s1 [r3], const char *s2 [r4] ) */
Packit 6c4009
Packit 6c4009
#ifndef USE_AS_STRNCASECMP
Packit 6c4009
#  define __STRCASECMP __strcasecmp
Packit 6c4009
#  define STRCASECMP   strcasecmp
Packit 6c4009
#else
Packit 6c4009
#  define __STRCASECMP __strncasecmp
Packit 6c4009
#  define STRCASECMP   strncasecmp
Packit 6c4009
#endif
Packit 6c4009
/* Convert 16 bytes to lowercase and compare */
Packit 6c4009
#define TOLOWER()     \
Packit 6c4009
	vaddubm	v8, v4, v1; \
Packit 6c4009
	vaddubm	v7, v4, v3; \
Packit 6c4009
	vcmpgtub	v8, v8, v2; \
Packit 6c4009
	vsel	v4, v7, v4, v8; \
Packit 6c4009
	vaddubm	v8, v5, v1; \
Packit 6c4009
	vaddubm	v7, v5, v3; \
Packit 6c4009
	vcmpgtub	v8, v8, v2; \
Packit 6c4009
	vsel	v5, v7, v5, v8; \
Packit 6c4009
	vcmpequb.	v7, v5, v4;
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Get 16 bytes for unaligned case.
Packit 6c4009
 * reg1: Vector to hold next 16 bytes.
Packit 6c4009
 * reg2: Address to read from.
Packit 6c4009
 * reg3: Permute control vector.
Packit 6c4009
 * v8: Tmp vector used to mask unwanted bytes.
Packit 6c4009
 * v9: Tmp vector,0 when null is found on first 16 bytes
Packit 6c4009
 */
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
#define GET16BYTES(reg1, reg2, reg3) \
Packit 6c4009
	lvx	reg1, 0, reg2; \
Packit 6c4009
	vspltisb	v8, -1; \
Packit 6c4009
	vperm	v8, v8, reg1, reg3; \
Packit 6c4009
	vcmpequb.	v8, v0, v8; \
Packit 6c4009
	beq	cr6, 1f; \
Packit 6c4009
	vspltisb	v9, 0; \
Packit 6c4009
	b	2f; \
Packit 6c4009
	.align 4; \
Packit 6c4009
1: \
Packit 6c4009
	addi	r6, reg2, 16; \
Packit 6c4009
	lvx	v9, 0, r6; \
Packit 6c4009
2: \
Packit 6c4009
	vperm	reg1, v9, reg1, reg3;
Packit 6c4009
#else
Packit 6c4009
#define GET16BYTES(reg1, reg2, reg3) \
Packit 6c4009
	lvx	reg1, 0, reg2; \
Packit 6c4009
	vspltisb	 v8, -1; \
Packit 6c4009
	vperm	v8, reg1, v8,  reg3; \
Packit 6c4009
	vcmpequb.	v8, v0, v8; \
Packit 6c4009
	beq	cr6, 1f; \
Packit 6c4009
	vspltisb	v9, 0; \
Packit 6c4009
	b	2f; \
Packit 6c4009
	.align 4; \
Packit 6c4009
1: \
Packit 6c4009
	addi	r6, reg2, 16; \
Packit 6c4009
	lvx	v9, 0, r6; \
Packit 6c4009
2: \
Packit 6c4009
	vperm	reg1, reg1, v9, reg3;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Check null in v4, v5 and convert to lower.  */
Packit 6c4009
#define CHECKNULLANDCONVERT() \
Packit 6c4009
	vcmpequb.	v7, v0, v5; \
Packit 6c4009
	beq	cr6, 3f; \
Packit 6c4009
	vcmpequb.	v7, v0, v4; \
Packit 6c4009
	beq	cr6, 3f; \
Packit 6c4009
	b	L(null_found); \
Packit 6c4009
	.align  4; \
Packit 6c4009
3: \
Packit 6c4009
	TOLOWER()
Packit 6c4009
Packit 6c4009
#ifdef _ARCH_PWR8
Packit 6c4009
#  define VCLZD_V8_v7	vclzd	v8, v7;
Packit 6c4009
#  define MFVRD_R3_V1	mfvrd	r3, v1;
Packit 6c4009
#  define VSUBUDM_V9_V8	vsubudm	v9, v9, v8;
Packit 6c4009
#  define VPOPCNTD_V8_V8	vpopcntd v8, v8;
Packit 6c4009
#  define VADDUQM_V7_V8	vadduqm	v9, v7, v8;
Packit 6c4009
#else
Packit 6c4009
#  define VCLZD_V8_v7	.long	0x11003fc2
Packit 6c4009
#  define MFVRD_R3_V1	.long	0x7c230067
Packit 6c4009
#  define VSUBUDM_V9_V8	.long	0x112944c0
Packit 6c4009
#  define VPOPCNTD_V8_V8	.long	0x110047c3
Packit 6c4009
#  define VADDUQM_V7_V8	.long	0x11274100
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	.machine  power7
Packit 6c4009
Packit 6c4009
ENTRY (__STRCASECMP)
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
	CALL_MCOUNT 3
Packit 6c4009
#else
Packit 6c4009
	CALL_MCOUNT 2
Packit 6c4009
#endif
Packit 6c4009
#define rRTN	r3	/* Return value */
Packit 6c4009
#define rSTR1	r10	/* 1st string */
Packit 6c4009
#define rSTR2	r4	/* 2nd string */
Packit 6c4009
#define rCHAR1	r6	/* Byte read from 1st string */
Packit 6c4009
#define rCHAR2	r7	/* Byte read from 2nd string */
Packit 6c4009
#define rADDR1	r8	/* Address of tolower(rCHAR1) */
Packit 6c4009
#define rADDR2	r12	/* Address of tolower(rCHAR2) */
Packit 6c4009
#define rLWR1	r8	/* Word tolower(rCHAR1) */
Packit 6c4009
#define rLWR2	r12	/* Word tolower(rCHAR2) */
Packit 6c4009
#define rTMP	r9
Packit 6c4009
#define rLOC	r11	/* Default locale address */
Packit 6c4009
Packit 6c4009
	cmpd	cr7, rRTN, rSTR2
Packit 6c4009
Packit 6c4009
	/* Get locale address.  */
Packit 6c4009
	ld 	rTMP, __libc_tsd_LOCALE@got@tprel(r2)
Packit 6c4009
	add 	rLOC, rTMP, __libc_tsd_LOCALE@tls
Packit 6c4009
	ld	rLOC, 0(rLOC)
Packit 6c4009
Packit 6c4009
	mr	rSTR1, rRTN
Packit 6c4009
	li	rRTN, 0
Packit 6c4009
	beqlr	cr7
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
	cmpdi	cr7, r5, 0
Packit 6c4009
	beq	cr7, L(retnull)
Packit 6c4009
	cmpdi	cr7, r5, 16
Packit 6c4009
	blt	cr7, L(bytebybyte)
Packit 6c4009
#endif
Packit 6c4009
	vspltisb	v0, 0
Packit 6c4009
	vspltisb	v8, -1
Packit 6c4009
	/* Check for null in initial characters.
Packit 6c4009
	   Check max of 16 char depending on the alignment.
Packit 6c4009
	   If null is present, proceed byte by byte.  */
Packit 6c4009
	lvx	v4, 0, rSTR1
Packit 6c4009
#ifdef  __LITTLE_ENDIAN__
Packit 6c4009
	lvsr	v10, 0, rSTR1	/* Compute mask.  */
Packit 6c4009
	vperm	v9, v8, v4, v10	/* Mask bits that are not part of string.  */
Packit 6c4009
#else
Packit 6c4009
	lvsl	v10, 0, rSTR1
Packit 6c4009
	vperm	v9, v4, v8, v10
Packit 6c4009
#endif
Packit 6c4009
	vcmpequb.	v9, v0, v9	/* Check for null bytes.  */
Packit 6c4009
	bne	cr6, L(bytebybyte)
Packit 6c4009
	lvx	v5, 0, rSTR2
Packit 6c4009
	/* Calculate alignment.  */
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	lvsr	v6, 0, rSTR2
Packit 6c4009
	vperm	v9, v8, v5, v6	/* Mask bits that are not part of string.  */
Packit 6c4009
#else
Packit 6c4009
	lvsl	v6, 0, rSTR2
Packit 6c4009
	vperm	v9, v5, v8, v6
Packit 6c4009
#endif
Packit 6c4009
	vcmpequb.	v9, v0, v9	/* Check for null bytes.  */
Packit 6c4009
	bne	cr6, L(bytebybyte)
Packit 6c4009
	/* Check if locale has non ascii characters.  */
Packit 6c4009
	ld	rTMP, 0(rLOC)
Packit 6c4009
	addi r6, rTMP,LOCALE_DATA_VALUES+_NL_CTYPE_NONASCII_CASE*SIZEOF_VALUES
Packit 6c4009
	lwz	rTMP, 0(r6)
Packit 6c4009
	cmpdi	cr7, rTMP, 1
Packit 6c4009
	beq	cr7, L(bytebybyte)
Packit 6c4009
Packit 6c4009
	/* Load vector registers with values used for TOLOWER.  */
Packit 6c4009
	/* Load v1 = 0xbf, v2 = 0x19 v3 = 0x20 in each byte.  */
Packit 6c4009
	vspltisb	v3, 2
Packit 6c4009
	vspltisb	v9, 4
Packit 6c4009
	vsl	v3, v3, v9
Packit 6c4009
	vaddubm	v1, v3, v3
Packit 6c4009
	vnor	v1, v1, v1
Packit 6c4009
	vspltisb	v2, 7
Packit 6c4009
	vsububm	v2, v3, v2
Packit 6c4009
Packit 6c4009
	andi.	rADDR1, rSTR1, 0xF
Packit 6c4009
	beq	cr0, L(align)
Packit 6c4009
	addi	r6, rSTR1, 16
Packit 6c4009
	lvx	v9, 0, r6
Packit 6c4009
	/* Compute 16 bytes from previous two loads.  */
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	vperm	v4, v9, v4, v10
Packit 6c4009
#else
Packit 6c4009
	vperm	v4, v4, v9, v10
Packit 6c4009
#endif
Packit 6c4009
L(align):
Packit 6c4009
	andi.	rADDR2, rSTR2, 0xF
Packit 6c4009
	beq	cr0, L(align1)
Packit 6c4009
	addi	r6, rSTR2, 16
Packit 6c4009
	lvx	v9, 0, r6
Packit 6c4009
	/* Compute 16 bytes from previous two loads.  */
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	vperm	v5, v9, v5, v6
Packit 6c4009
#else
Packit 6c4009
	vperm	v5, v5, v9, v6
Packit 6c4009
#endif
Packit 6c4009
L(align1):
Packit 6c4009
	CHECKNULLANDCONVERT()
Packit 6c4009
	blt	cr6, L(match)
Packit 6c4009
	b	L(different)
Packit 6c4009
	.align 	4
Packit 6c4009
L(match):
Packit 6c4009
	clrldi	r6, rSTR1, 60
Packit 6c4009
	subfic	r7, r6, 16
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
	sub	r5, r5, r7
Packit 6c4009
#endif
Packit 6c4009
	add	rSTR1, rSTR1, r7
Packit 6c4009
	add	rSTR2, rSTR2, r7
Packit 6c4009
	andi.	rADDR2, rSTR2, 0xF
Packit 6c4009
	addi	rSTR1, rSTR1, -16
Packit 6c4009
	addi	rSTR2, rSTR2, -16
Packit 6c4009
	beq	cr0, L(aligned)
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	lvsr	v6, 0, rSTR2
Packit 6c4009
#else
Packit 6c4009
	lvsl	v6, 0, rSTR2
Packit 6c4009
#endif
Packit 6c4009
	/* There are 2 loops depending on the input alignment.
Packit 6c4009
	   Each loop gets 16 bytes from s1 and s2, check for null,
Packit 6c4009
	   convert to lowercase and compare. Loop till difference
Packit 6c4009
	   or null occurs. */
Packit 6c4009
L(s1_align):
Packit 6c4009
	addi	rSTR1, rSTR1, 16
Packit 6c4009
	addi	rSTR2, rSTR2, 16
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
	cmpdi	cr7, r5, 16
Packit 6c4009
	blt	cr7, L(bytebybyte)
Packit 6c4009
	addi	r5, r5, -16
Packit 6c4009
#endif
Packit 6c4009
	lvx	v4, 0, rSTR1
Packit 6c4009
	GET16BYTES(v5, rSTR2, v6)
Packit 6c4009
	CHECKNULLANDCONVERT()
Packit 6c4009
	blt	cr6, L(s1_align)
Packit 6c4009
	b	L(different)
Packit 6c4009
	.align 	4
Packit 6c4009
L(aligned):
Packit 6c4009
	addi	rSTR1, rSTR1, 16
Packit 6c4009
	addi	rSTR2, rSTR2, 16
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
	cmpdi	cr7, r5, 16
Packit 6c4009
	blt	cr7, L(bytebybyte)
Packit 6c4009
	addi	r5, r5, -16
Packit 6c4009
#endif
Packit 6c4009
	lvx	v4, 0, rSTR1
Packit 6c4009
	lvx	v5, 0, rSTR2
Packit 6c4009
	CHECKNULLANDCONVERT()
Packit 6c4009
	blt	cr6, L(aligned)
Packit 6c4009
Packit 6c4009
	/* Calculate and return the difference. */
Packit 6c4009
L(different):
Packit 6c4009
	vaddubm	v1, v3, v3
Packit 6c4009
	vcmpequb	v7, v0, v7
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	/* Count trailing zero.  */
Packit 6c4009
	vspltisb	v8, -1
Packit 6c4009
	VADDUQM_V7_V8
Packit 6c4009
	vandc	v8, v9, v7
Packit 6c4009
	VPOPCNTD_V8_V8
Packit 6c4009
	vspltb	v6, v8, 15
Packit 6c4009
	vcmpequb.	v6, v6, v1
Packit 6c4009
	blt	cr6, L(shift8)
Packit 6c4009
#else
Packit 6c4009
	/* Count leading zero.  */
Packit 6c4009
	VCLZD_V8_v7
Packit 6c4009
	vspltb	v6, v8, 7
Packit 6c4009
	vcmpequb.	v6, v6, v1
Packit 6c4009
	blt	cr6, L(shift8)
Packit 6c4009
	vsro	v8, v8, v1
Packit 6c4009
#endif
Packit 6c4009
	b	L(skipsum)
Packit 6c4009
	.align  4
Packit 6c4009
L(shift8):
Packit 6c4009
	vsumsws		v8, v8, v0
Packit 6c4009
L(skipsum):
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	/* Shift registers based on leading zero count.  */
Packit 6c4009
	vsro	v6, v5, v8
Packit 6c4009
	vsro	v7, v4, v8
Packit 6c4009
	/* Merge and move to GPR.  */
Packit 6c4009
	vmrglb	v6, v6, v7
Packit 6c4009
	vslo	v1, v6, v1
Packit 6c4009
	MFVRD_R3_V1
Packit 6c4009
	/* Place the characters that are different in first position.  */
Packit 6c4009
	sldi	rSTR2, rRTN, 56
Packit 6c4009
	srdi	rSTR2, rSTR2, 56
Packit 6c4009
	sldi	rSTR1, rRTN, 48
Packit 6c4009
	srdi	rSTR1, rSTR1, 56
Packit 6c4009
#else
Packit 6c4009
	vslo	v6, v5, v8
Packit 6c4009
	vslo	v7, v4, v8
Packit 6c4009
	vmrghb	v1, v6, v7
Packit 6c4009
	MFVRD_R3_V1
Packit 6c4009
	srdi	rSTR2, rRTN, 48
Packit 6c4009
	sldi	rSTR2, rSTR2, 56
Packit 6c4009
	srdi	rSTR2, rSTR2, 56
Packit 6c4009
	srdi	rSTR1, rRTN, 56
Packit 6c4009
#endif
Packit 6c4009
	subf  	rRTN, rSTR1, rSTR2
Packit 6c4009
	extsw 	rRTN, rRTN
Packit 6c4009
	blr
Packit 6c4009
Packit 6c4009
	.align  4
Packit 6c4009
	/* OK. We've hit the end of the string. We need to be careful that
Packit 6c4009
	   we don't compare two strings as different because of junk beyond
Packit 6c4009
	   the end of the strings...  */
Packit 6c4009
L(null_found):
Packit 6c4009
	vaddubm	v10, v3, v3
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	/* Count trailing zero.  */
Packit 6c4009
	vspltisb	v8, -1
Packit 6c4009
	VADDUQM_V7_V8
Packit 6c4009
	vandc	v8, v9, v7
Packit 6c4009
	VPOPCNTD_V8_V8
Packit 6c4009
	vspltb	v6, v8, 15
Packit 6c4009
	vcmpequb.	v6, v6, v10
Packit 6c4009
	blt	cr6, L(shift_8)
Packit 6c4009
#else
Packit 6c4009
	/* Count leading zero.  */
Packit 6c4009
	VCLZD_V8_v7
Packit 6c4009
	vspltb	v6, v8, 7
Packit 6c4009
	vcmpequb.	v6, v6, v10
Packit 6c4009
	blt	cr6, L(shift_8)
Packit 6c4009
	vsro	v8, v8, v10
Packit 6c4009
#endif
Packit 6c4009
	b	L(skipsum1)
Packit 6c4009
	.align  4
Packit 6c4009
L(shift_8):
Packit 6c4009
	vsumsws	v8, v8, v0
Packit 6c4009
L(skipsum1):
Packit 6c4009
	/* Calculate shift count based on count of zero.  */
Packit 6c4009
	vspltisb	v10, 7
Packit 6c4009
	vslb	v10, v10, v10
Packit 6c4009
	vsldoi	v9, v0, v10, 1
Packit 6c4009
	VSUBUDM_V9_V8
Packit 6c4009
	vspltisb	v8, 8
Packit 6c4009
	vsldoi	v8, v0, v8, 1
Packit 6c4009
	VSUBUDM_V9_V8
Packit 6c4009
	/* Shift and remove junk after null character.  */
Packit 6c4009
#ifdef __LITTLE_ENDIAN__
Packit 6c4009
	vslo	v5, v5, v9
Packit 6c4009
	vslo	v4, v4, v9
Packit 6c4009
#else
Packit 6c4009
	vsro	v5, v5, v9
Packit 6c4009
	vsro	v4, v4, v9
Packit 6c4009
#endif
Packit 6c4009
	/* Convert and compare 16 bytes.  */
Packit 6c4009
	TOLOWER()
Packit 6c4009
	blt	cr6, L(retnull)
Packit 6c4009
	b	L(different)
Packit 6c4009
	.align  4
Packit 6c4009
L(retnull):
Packit 6c4009
	li	rRTN, 0
Packit 6c4009
	blr
Packit 6c4009
	.align  4
Packit 6c4009
L(bytebybyte):
Packit 6c4009
	/* Unrolling loop for POWER: loads are done with 'lbz' plus
Packit 6c4009
	offset and string descriptors are only updated in the end
Packit 6c4009
	of loop unrolling. */
Packit 6c4009
	ld	rLOC, LOCALE_CTYPE_TOLOWER(rLOC)
Packit 6c4009
	lbz	rCHAR1, 0(rSTR1)	/* Load char from s1 */
Packit 6c4009
	lbz	rCHAR2, 0(rSTR2)	/* Load char from s2 */
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
	rldicl	rTMP, r5, 62, 2
Packit 6c4009
	cmpdi	cr7, rTMP, 0
Packit 6c4009
	beq	cr7, L(lessthan4)
Packit 6c4009
	mtctr	rTMP
Packit 6c4009
#endif
Packit 6c4009
L(loop):
Packit 6c4009
	cmpdi	rCHAR1, 0		/* *s1 == '\0' ? */
Packit 6c4009
	sldi	rADDR1, rCHAR1, 2	/* Calculate address for tolower(*s1) */
Packit 6c4009
	sldi	rADDR2, rCHAR2, 2	/* Calculate address for tolower(*s2) */
Packit 6c4009
	lwzx	rLWR1, rLOC, rADDR1	/* Load tolower(*s1) */
Packit 6c4009
	lwzx	rLWR2, rLOC, rADDR2	/* Load tolower(*s2) */
Packit 6c4009
	cmpw	cr1, rLWR1, rLWR2	/* r = tolower(*s1) == tolower(*s2) ? */
Packit 6c4009
	crorc	4*cr1+eq,eq,4*cr1+eq	/* (*s1 != '\0') || (r == 1) */
Packit 6c4009
	beq	cr1, L(done)
Packit 6c4009
	lbz	rCHAR1, 1(rSTR1)
Packit 6c4009
	lbz	rCHAR2, 1(rSTR2)
Packit 6c4009
	cmpdi	rCHAR1, 0
Packit 6c4009
	sldi	rADDR1, rCHAR1, 2
Packit 6c4009
	sldi	rADDR2, rCHAR2, 2
Packit 6c4009
	lwzx	rLWR1, rLOC, rADDR1
Packit 6c4009
	lwzx	rLWR2, rLOC, rADDR2
Packit 6c4009
	cmpw	cr1, rLWR1, rLWR2
Packit 6c4009
	crorc	4*cr1+eq,eq,4*cr1+eq
Packit 6c4009
	beq	cr1, L(done)
Packit 6c4009
	lbz	rCHAR1, 2(rSTR1)
Packit 6c4009
	lbz	rCHAR2, 2(rSTR2)
Packit 6c4009
	cmpdi	rCHAR1, 0
Packit 6c4009
	sldi	rADDR1, rCHAR1, 2
Packit 6c4009
	sldi	rADDR2, rCHAR2, 2
Packit 6c4009
	lwzx	rLWR1, rLOC, rADDR1
Packit 6c4009
	lwzx	rLWR2, rLOC, rADDR2
Packit 6c4009
	cmpw	cr1, rLWR1, rLWR2
Packit 6c4009
	crorc	4*cr1+eq,eq,4*cr1+eq
Packit 6c4009
	beq	cr1, L(done)
Packit 6c4009
	lbz	rCHAR1, 3(rSTR1)
Packit 6c4009
	lbz	rCHAR2, 3(rSTR2)
Packit 6c4009
	cmpdi	rCHAR1, 0
Packit 6c4009
	/* Increment both string descriptors */
Packit 6c4009
	addi	rSTR1, rSTR1, 4
Packit 6c4009
	addi	rSTR2, rSTR2, 4
Packit 6c4009
	sldi	rADDR1, rCHAR1, 2
Packit 6c4009
	sldi	rADDR2, rCHAR2, 2
Packit 6c4009
	lwzx	rLWR1, rLOC, rADDR1
Packit 6c4009
	lwzx	rLWR2, rLOC, rADDR2
Packit 6c4009
	cmpw	cr1, rLWR1, rLWR2
Packit 6c4009
	crorc	4*cr1+eq,eq,4*cr1+eq
Packit 6c4009
	beq     cr1, L(done)
Packit 6c4009
	lbz	rCHAR1, 0(rSTR1)	/* Load char from s1 */
Packit 6c4009
	lbz	rCHAR2, 0(rSTR2)	/* Load char from s2 */
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
	bdnz	L(loop)
Packit 6c4009
#else
Packit 6c4009
	b	L(loop)
Packit 6c4009
#endif
Packit 6c4009
#ifdef USE_AS_STRNCASECMP
Packit 6c4009
L(lessthan4):
Packit 6c4009
	clrldi	r5, r5, 62
Packit 6c4009
	cmpdi	cr7, r5, 0
Packit 6c4009
	beq	cr7, L(retnull)
Packit 6c4009
	mtctr	r5
Packit 6c4009
L(loop1):
Packit 6c4009
	cmpdi	rCHAR1, 0
Packit 6c4009
	sldi	rADDR1, rCHAR1, 2
Packit 6c4009
	sldi	rADDR2, rCHAR2, 2
Packit 6c4009
	lwzx	rLWR1, rLOC, rADDR1
Packit 6c4009
	lwzx	rLWR2, rLOC, rADDR2
Packit 6c4009
	cmpw	cr1, rLWR1, rLWR2
Packit 6c4009
	crorc	4*cr1+eq,eq,4*cr1+eq
Packit 6c4009
	beq	cr1, L(done)
Packit 6c4009
	addi	rSTR1, rSTR1, 1
Packit 6c4009
	addi	rSTR2, rSTR2, 1
Packit 6c4009
	lbz	rCHAR1, 0(rSTR1)
Packit 6c4009
	lbz	rCHAR2, 0(rSTR2)
Packit 6c4009
	bdnz	L(loop1)
Packit 6c4009
#endif
Packit 6c4009
L(done):
Packit 6c4009
	subf	r0, rLWR2, rLWR1
Packit 6c4009
	extsw	rRTN, r0
Packit 6c4009
	blr
Packit 6c4009
END (__STRCASECMP)
Packit 6c4009
Packit 6c4009
weak_alias (__STRCASECMP, STRCASECMP)
Packit 6c4009
libc_hidden_builtin_def (__STRCASECMP)