Blame sysdeps/arm/armv7/strcmp.S

Packit 6c4009
/* strcmp implementation for ARMv7-A, optimized for Cortex-A15.
Packit 6c4009
   Copyright (C) 2012-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 <arm-features.h>
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
Packit 6c4009
/* Implementation of strcmp for ARMv7 when DSP instructions are
Packit 6c4009
   available.  Use ldrd to support wider loads, provided the data
Packit 6c4009
   is sufficiently aligned.  Use saturating arithmetic to optimize
Packit 6c4009
   the compares.  */
Packit 6c4009
Packit 6c4009
/* Build Options:
Packit 6c4009
   STRCMP_PRECHECK: Run a quick pre-check of the first byte in the
Packit 6c4009
   string.  If comparing completely random strings the pre-check will
Packit 6c4009
   save time, since there is a very high probability of a mismatch in
Packit 6c4009
   the first character: we save significant overhead if this is the
Packit 6c4009
   common case.  However, if strings are likely to be identical (e.g.
Packit 6c4009
   because we're verifying a hit in a hash table), then this check
Packit 6c4009
   is largely redundant.  */
Packit 6c4009
Packit 6c4009
#define STRCMP_PRECHECK	1
Packit 6c4009
Packit 6c4009
	.syntax unified
Packit 6c4009
Packit 6c4009
#ifdef __ARM_BIG_ENDIAN
Packit 6c4009
# define S2LO lsl
Packit 6c4009
# define S2LOEQ lsleq
Packit 6c4009
# define S2HI lsr
Packit 6c4009
# define MSB 0x000000ff
Packit 6c4009
# define LSB 0xff000000
Packit 6c4009
# define BYTE0_OFFSET 24
Packit 6c4009
# define BYTE1_OFFSET 16
Packit 6c4009
# define BYTE2_OFFSET 8
Packit 6c4009
# define BYTE3_OFFSET 0
Packit 6c4009
#else /* not  __ARM_BIG_ENDIAN */
Packit 6c4009
# define S2LO lsr
Packit 6c4009
# define S2LOEQ lsreq
Packit 6c4009
# define S2HI lsl
Packit 6c4009
# define BYTE0_OFFSET 0
Packit 6c4009
# define BYTE1_OFFSET 8
Packit 6c4009
# define BYTE2_OFFSET 16
Packit 6c4009
# define BYTE3_OFFSET 24
Packit 6c4009
# define MSB 0xff000000
Packit 6c4009
# define LSB 0x000000ff
Packit 6c4009
#endif /* not  __ARM_BIG_ENDIAN */
Packit 6c4009
Packit 6c4009
/* Parameters and result.  */
Packit 6c4009
#define src1		r0
Packit 6c4009
#define src2		r1
Packit 6c4009
#define result		r0	/* Overlaps src1.  */
Packit 6c4009
Packit 6c4009
/* Internal variables.  */
Packit 6c4009
#define tmp1		r4
Packit 6c4009
#define tmp2		r5
Packit 6c4009
#define const_m1	r12
Packit 6c4009
Packit 6c4009
/* Additional internal variables for 64-bit aligned data.  */
Packit 6c4009
#define data1a		r2
Packit 6c4009
#define data1b		r3
Packit 6c4009
#define data2a		r6
Packit 6c4009
#define data2b		r7
Packit 6c4009
#define syndrome_a	tmp1
Packit 6c4009
#define syndrome_b	tmp2
Packit 6c4009
Packit 6c4009
/* Additional internal variables for 32-bit aligned data.  */
Packit 6c4009
#define data1		r2
Packit 6c4009
#define data2		r3
Packit 6c4009
#define syndrome	tmp2
Packit 6c4009
Packit 6c4009
Packit 6c4009
	.thumb
Packit 6c4009
Packit 6c4009
/* In Thumb code we can't use MVN with a register shift, but we do have ORN.  */
Packit 6c4009
.macro prepare_mask mask_reg, nbits_reg
Packit 6c4009
	S2HI \mask_reg, const_m1, \nbits_reg
Packit 6c4009
.endm
Packit 6c4009
.macro apply_mask data_reg, mask_reg
Packit 6c4009
	orn \data_reg, \data_reg, \mask_reg
Packit 6c4009
.endm
Packit 6c4009
Packit 6c4009
	/* Macro to compute and return the result value for word-aligned
Packit 6c4009
	   cases.  */
Packit 6c4009
	.macro strcmp_epilogue_aligned synd d1 d2 restore_r6
Packit 6c4009
#ifdef __ARM_BIG_ENDIAN
Packit 6c4009
	/* If data1 contains a zero byte, then syndrome will contain a 1 in
Packit 6c4009
	   bit 7 of that byte.  Otherwise, the highest set bit in the
Packit 6c4009
	   syndrome will highlight the first different bit.  It is therefore
Packit 6c4009
	   sufficient to extract the eight bits starting with the syndrome
Packit 6c4009
	   bit.  */
Packit 6c4009
	clz	tmp1, \synd
Packit 6c4009
	lsl	r1, \d2, tmp1
Packit 6c4009
	.if \restore_r6
Packit 6c4009
	ldrd	r6, r7, [sp, #8]
Packit 6c4009
	.endif
Packit 6c4009
	lsl	\d1, \d1, tmp1
Packit 6c4009
	lsr	result, \d1, #24
Packit 6c4009
	ldrd	r4, r5, [sp], #16
Packit 6c4009
	cfi_remember_state
Packit 6c4009
	cfi_def_cfa_offset (0)
Packit 6c4009
	cfi_restore (r4)
Packit 6c4009
	cfi_restore (r5)
Packit 6c4009
	cfi_restore (r6)
Packit 6c4009
	cfi_restore (r7)
Packit 6c4009
	sub	result, result, r1, lsr #24
Packit 6c4009
	bx	lr
Packit 6c4009
#else
Packit 6c4009
	/* To use the big-endian trick we'd have to reverse all three words.
Packit 6c4009
	   that's slower than this approach.  */
Packit 6c4009
	rev	\synd, \synd
Packit 6c4009
	clz	tmp1, \synd
Packit 6c4009
	bic	tmp1, tmp1, #7
Packit 6c4009
	lsr	r1, \d2, tmp1
Packit 6c4009
	.if \restore_r6
Packit 6c4009
	ldrd	r6, r7, [sp, #8]
Packit 6c4009
	.endif
Packit 6c4009
	lsr	\d1, \d1, tmp1
Packit 6c4009
	and	result, \d1, #255
Packit 6c4009
	and	r1, r1, #255
Packit 6c4009
	ldrd	r4, r5, [sp], #16
Packit 6c4009
	cfi_remember_state
Packit 6c4009
	cfi_def_cfa_offset (0)
Packit 6c4009
	cfi_restore (r4)
Packit 6c4009
	cfi_restore (r5)
Packit 6c4009
	cfi_restore (r6)
Packit 6c4009
	cfi_restore (r7)
Packit 6c4009
	sub	result, result, r1
Packit 6c4009
Packit 6c4009
	bx	lr
Packit 6c4009
#endif
Packit 6c4009
	.endm
Packit 6c4009
Packit 6c4009
	.text
Packit 6c4009
	.p2align	5
Packit 6c4009
.Lstrcmp_start_addr:
Packit 6c4009
#if STRCMP_PRECHECK == 1
Packit 6c4009
.Lfastpath_exit:
Packit 6c4009
	sub	r0, r2, r3
Packit 6c4009
	bx	lr
Packit 6c4009
	nop
Packit 6c4009
#endif
Packit 6c4009
ENTRY (strcmp)
Packit 6c4009
#if STRCMP_PRECHECK == 1
Packit 6c4009
	ldrb	r2, [src1]
Packit 6c4009
	ldrb	r3, [src2]
Packit 6c4009
	cmp	r2, #1
Packit 6c4009
	it	cs
Packit 6c4009
	cmpcs	r2, r3
Packit 6c4009
	bne	.Lfastpath_exit
Packit 6c4009
#endif
Packit 6c4009
	strd	r4, r5, [sp, #-16]!
Packit 6c4009
	cfi_def_cfa_offset (16)
Packit 6c4009
	cfi_offset (r4, -16)
Packit 6c4009
	cfi_offset (r5, -12)
Packit 6c4009
	orr	tmp1, src1, src2
Packit 6c4009
	strd	r6, r7, [sp, #8]
Packit 6c4009
	cfi_offset (r6, -8)
Packit 6c4009
	cfi_offset (r7, -4)
Packit 6c4009
	mvn	const_m1, #0
Packit 6c4009
	lsl	r2, tmp1, #29
Packit 6c4009
	cbz	r2, .Lloop_aligned8
Packit 6c4009
Packit 6c4009
.Lnot_aligned:
Packit 6c4009
	eor	tmp1, src1, src2
Packit 6c4009
	tst	tmp1, #7
Packit 6c4009
	bne	.Lmisaligned8
Packit 6c4009
Packit 6c4009
	/* Deal with mutual misalignment by aligning downwards and then
Packit 6c4009
	   masking off the unwanted loaded data to prevent a difference.  */
Packit 6c4009
	and	tmp1, src1, #7
Packit 6c4009
	bic	src1, src1, #7
Packit 6c4009
	and	tmp2, tmp1, #3
Packit 6c4009
	bic	src2, src2, #7
Packit 6c4009
	lsl	tmp2, tmp2, #3	/* Bytes -> bits.  */
Packit 6c4009
	ldrd	data1a, data1b, [src1], #16
Packit 6c4009
	tst	tmp1, #4
Packit 6c4009
	ldrd	data2a, data2b, [src2], #16
Packit 6c4009
	prepare_mask tmp1, tmp2
Packit 6c4009
	apply_mask data1a, tmp1
Packit 6c4009
	apply_mask data2a, tmp1
Packit 6c4009
	beq	.Lstart_realigned8
Packit 6c4009
	apply_mask data1b, tmp1
Packit 6c4009
	mov	data1a, const_m1
Packit 6c4009
	apply_mask data2b, tmp1
Packit 6c4009
	mov	data2a, const_m1
Packit 6c4009
	b	.Lstart_realigned8
Packit 6c4009
Packit 6c4009
	/* Unwind the inner loop by a factor of 2, giving 16 bytes per
Packit 6c4009
	   pass.  */
Packit 6c4009
	.p2align 5,,12  /* Don't start in the tail bytes of a cache line.  */
Packit 6c4009
	.p2align 2	/* Always word aligned.  */
Packit 6c4009
.Lloop_aligned8:
Packit 6c4009
	ldrd	data1a, data1b, [src1], #16
Packit 6c4009
	ldrd	data2a, data2b, [src2], #16
Packit 6c4009
.Lstart_realigned8:
Packit 6c4009
	uadd8	syndrome_b, data1a, const_m1	/* Only want GE bits,  */
Packit 6c4009
	eor	syndrome_a, data1a, data2a
Packit 6c4009
	sel	syndrome_a, syndrome_a, const_m1
Packit 6c4009
	cbnz	syndrome_a, .Ldiff_in_a
Packit 6c4009
	uadd8	syndrome_b, data1b, const_m1	/* Only want GE bits.  */
Packit 6c4009
	eor	syndrome_b, data1b, data2b
Packit 6c4009
	sel	syndrome_b, syndrome_b, const_m1
Packit 6c4009
	cbnz	syndrome_b, .Ldiff_in_b
Packit 6c4009
Packit 6c4009
	ldrd	data1a, data1b, [src1, #-8]
Packit 6c4009
	ldrd	data2a, data2b, [src2, #-8]
Packit 6c4009
	uadd8	syndrome_b, data1a, const_m1	/* Only want GE bits,  */
Packit 6c4009
	eor	syndrome_a, data1a, data2a
Packit 6c4009
	sel	syndrome_a, syndrome_a, const_m1
Packit 6c4009
	uadd8	syndrome_b, data1b, const_m1	/* Only want GE bits.  */
Packit 6c4009
	eor	syndrome_b, data1b, data2b
Packit 6c4009
	sel	syndrome_b, syndrome_b, const_m1
Packit 6c4009
	/* Can't use CBZ for backwards branch.  */
Packit 6c4009
	orrs	syndrome_b, syndrome_b, syndrome_a /* Only need if s_a == 0 */
Packit 6c4009
	beq	.Lloop_aligned8
Packit 6c4009
Packit 6c4009
.Ldiff_found:
Packit 6c4009
	cbnz	syndrome_a, .Ldiff_in_a
Packit 6c4009
Packit 6c4009
.Ldiff_in_b:
Packit 6c4009
	strcmp_epilogue_aligned syndrome_b, data1b, data2b 1
Packit 6c4009
Packit 6c4009
.Ldiff_in_a:
Packit 6c4009
	cfi_restore_state
Packit 6c4009
	strcmp_epilogue_aligned syndrome_a, data1a, data2a 1
Packit 6c4009
Packit 6c4009
	cfi_restore_state
Packit 6c4009
.Lmisaligned8:
Packit 6c4009
	tst	tmp1, #3
Packit 6c4009
	bne	.Lmisaligned4
Packit 6c4009
	ands	tmp1, src1, #3
Packit 6c4009
	bne	.Lmutual_align4
Packit 6c4009
Packit 6c4009
	/* Unrolled by a factor of 2, to reduce the number of post-increment
Packit 6c4009
	   operations.  */
Packit 6c4009
.Lloop_aligned4:
Packit 6c4009
	ldr	data1, [src1], #8
Packit 6c4009
	ldr	data2, [src2], #8
Packit 6c4009
.Lstart_realigned4:
Packit 6c4009
	uadd8	syndrome, data1, const_m1	/* Only need GE bits.  */
Packit 6c4009
	eor	syndrome, data1, data2
Packit 6c4009
	sel	syndrome, syndrome, const_m1
Packit 6c4009
	cbnz	syndrome, .Laligned4_done
Packit 6c4009
	ldr	data1, [src1, #-4]
Packit 6c4009
	ldr	data2, [src2, #-4]
Packit 6c4009
	uadd8	syndrome, data1, const_m1
Packit 6c4009
	eor	syndrome, data1, data2
Packit 6c4009
	sel	syndrome, syndrome, const_m1
Packit 6c4009
	cmp	syndrome, #0
Packit 6c4009
	beq	.Lloop_aligned4
Packit 6c4009
Packit 6c4009
.Laligned4_done:
Packit 6c4009
	strcmp_epilogue_aligned syndrome, data1, data2, 0
Packit 6c4009
Packit 6c4009
.Lmutual_align4:
Packit 6c4009
	cfi_restore_state
Packit 6c4009
	/* Deal with mutual misalignment by aligning downwards and then
Packit 6c4009
	   masking off the unwanted loaded data to prevent a difference.  */
Packit 6c4009
	lsl	tmp1, tmp1, #3	/* Bytes -> bits.  */
Packit 6c4009
	bic	src1, src1, #3
Packit 6c4009
	ldr	data1, [src1], #8
Packit 6c4009
	bic	src2, src2, #3
Packit 6c4009
	ldr	data2, [src2], #8
Packit 6c4009
Packit 6c4009
	prepare_mask tmp1, tmp1
Packit 6c4009
	apply_mask data1, tmp1
Packit 6c4009
	apply_mask data2, tmp1
Packit 6c4009
	b	.Lstart_realigned4
Packit 6c4009
Packit 6c4009
.Lmisaligned4:
Packit 6c4009
	ands	tmp1, src1, #3
Packit 6c4009
	beq	.Lsrc1_aligned
Packit 6c4009
	sub	src2, src2, tmp1
Packit 6c4009
	bic	src1, src1, #3
Packit 6c4009
	lsls	tmp1, tmp1, #31
Packit 6c4009
	ldr	data1, [src1], #4
Packit 6c4009
	beq	.Laligned_m2
Packit 6c4009
	bcs	.Laligned_m1
Packit 6c4009
Packit 6c4009
#if STRCMP_PRECHECK == 0
Packit 6c4009
	ldrb	data2, [src2, #1]
Packit 6c4009
	uxtb	tmp1, data1, ror #BYTE1_OFFSET
Packit 6c4009
	subs	tmp1, tmp1, data2
Packit 6c4009
	bne	.Lmisaligned_exit
Packit 6c4009
	cbz	data2, .Lmisaligned_exit
Packit 6c4009
Packit 6c4009
.Laligned_m2:
Packit 6c4009
	ldrb	data2, [src2, #2]
Packit 6c4009
	uxtb	tmp1, data1, ror #BYTE2_OFFSET
Packit 6c4009
	subs	tmp1, tmp1, data2
Packit 6c4009
	bne	.Lmisaligned_exit
Packit 6c4009
	cbz	data2, .Lmisaligned_exit
Packit 6c4009
Packit 6c4009
.Laligned_m1:
Packit 6c4009
	ldrb	data2, [src2, #3]
Packit 6c4009
	uxtb	tmp1, data1, ror #BYTE3_OFFSET
Packit 6c4009
	subs	tmp1, tmp1, data2
Packit 6c4009
	bne	.Lmisaligned_exit
Packit 6c4009
	add	src2, src2, #4
Packit 6c4009
	cbnz	data2, .Lsrc1_aligned
Packit 6c4009
#else  /* STRCMP_PRECHECK */
Packit 6c4009
	/* If we've done the pre-check, then we don't need to check the
Packit 6c4009
	   first byte again here.  */
Packit 6c4009
	ldrb	data2, [src2, #2]
Packit 6c4009
	uxtb	tmp1, data1, ror #BYTE2_OFFSET
Packit 6c4009
	subs	tmp1, tmp1, data2
Packit 6c4009
	bne	.Lmisaligned_exit
Packit 6c4009
	cbz	data2, .Lmisaligned_exit
Packit 6c4009
Packit 6c4009
.Laligned_m2:
Packit 6c4009
	ldrb	data2, [src2, #3]
Packit 6c4009
	uxtb	tmp1, data1, ror #BYTE3_OFFSET
Packit 6c4009
	subs	tmp1, tmp1, data2
Packit 6c4009
	bne	.Lmisaligned_exit
Packit 6c4009
	cbnz	data2, .Laligned_m1
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
.Lmisaligned_exit:
Packit 6c4009
	mov	result, tmp1
Packit 6c4009
	ldr	r4, [sp], #16
Packit 6c4009
	cfi_remember_state
Packit 6c4009
	cfi_def_cfa_offset (0)
Packit 6c4009
	cfi_restore (r4)
Packit 6c4009
	cfi_restore (r5)
Packit 6c4009
	cfi_restore (r6)
Packit 6c4009
	cfi_restore (r7)
Packit 6c4009
	bx	lr
Packit 6c4009
Packit 6c4009
#if STRCMP_PRECHECK == 1
Packit 6c4009
.Laligned_m1:
Packit 6c4009
	add	src2, src2, #4
Packit 6c4009
#endif
Packit 6c4009
.Lsrc1_aligned:
Packit 6c4009
	cfi_restore_state
Packit 6c4009
	/* src1 is word aligned, but src2 has no common alignment
Packit 6c4009
	   with it.  */
Packit 6c4009
	ldr	data1, [src1], #4
Packit 6c4009
	lsls	tmp1, src2, #31		/* C=src2[1], Z=src2[0].  */
Packit 6c4009
Packit 6c4009
	bic	src2, src2, #3
Packit 6c4009
	ldr	data2, [src2], #4
Packit 6c4009
	bhi	.Loverlap1		/* C=1, Z=0 => src2[1:0] = 0b11.  */
Packit 6c4009
	bcs	.Loverlap2		/* C=1, Z=1 => src2[1:0] = 0b10.  */
Packit 6c4009
Packit 6c4009
	/* (overlap3) C=0, Z=0 => src2[1:0] = 0b01.  */
Packit 6c4009
.Loverlap3:
Packit 6c4009
	bic	tmp1, data1, #MSB
Packit 6c4009
	uadd8	syndrome, data1, const_m1
Packit 6c4009
	eors	syndrome, tmp1, data2, S2LO #8
Packit 6c4009
	sel	syndrome, syndrome, const_m1
Packit 6c4009
	bne	4f
Packit 6c4009
	cbnz	syndrome, 5f
Packit 6c4009
	ldr	data2, [src2], #4
Packit 6c4009
	eor	tmp1, tmp1, data1
Packit 6c4009
	cmp	tmp1, data2, S2HI #24
Packit 6c4009
	bne	6f
Packit 6c4009
	ldr	data1, [src1], #4
Packit 6c4009
	b	.Loverlap3
Packit 6c4009
4:
Packit 6c4009
	S2LO	data2, data2, #8
Packit 6c4009
	b	.Lstrcmp_tail
Packit 6c4009
Packit 6c4009
5:
Packit 6c4009
	bics	syndrome, syndrome, #MSB
Packit 6c4009
	bne	.Lstrcmp_done_equal
Packit 6c4009
Packit 6c4009
	/* We can only get here if the MSB of data1 contains 0, so
Packit 6c4009
	   fast-path the exit.  */
Packit 6c4009
	ldrb	result, [src2]
Packit 6c4009
	ldrd	r4, r5, [sp], #16
Packit 6c4009
	cfi_remember_state
Packit 6c4009
	cfi_def_cfa_offset (0)
Packit 6c4009
	cfi_restore (r4)
Packit 6c4009
	cfi_restore (r5)
Packit 6c4009
	/* R6/7 Not used in this sequence.  */
Packit 6c4009
	cfi_restore (r6)
Packit 6c4009
	cfi_restore (r7)
Packit 6c4009
	neg	result, result
Packit 6c4009
	bx	lr
Packit 6c4009
Packit 6c4009
6:
Packit 6c4009
	cfi_restore_state
Packit 6c4009
	S2LO	data1, data1, #24
Packit 6c4009
	and	data2, data2, #LSB
Packit 6c4009
	b	.Lstrcmp_tail
Packit 6c4009
Packit 6c4009
	.p2align 5,,12	/* Ensure at least 3 instructions in cache line.  */
Packit 6c4009
.Loverlap2:
Packit 6c4009
	and	tmp1, data1, const_m1, S2LO #16
Packit 6c4009
	uadd8	syndrome, data1, const_m1
Packit 6c4009
	eors	syndrome, tmp1, data2, S2LO #16
Packit 6c4009
	sel	syndrome, syndrome, const_m1
Packit 6c4009
	bne	4f
Packit 6c4009
	cbnz	syndrome, 5f
Packit 6c4009
	ldr	data2, [src2], #4
Packit 6c4009
	eor	tmp1, tmp1, data1
Packit 6c4009
	cmp	tmp1, data2, S2HI #16
Packit 6c4009
	bne	6f
Packit 6c4009
	ldr	data1, [src1], #4
Packit 6c4009
	b	.Loverlap2
Packit 6c4009
4:
Packit 6c4009
	S2LO	data2, data2, #16
Packit 6c4009
	b	.Lstrcmp_tail
Packit 6c4009
5:
Packit 6c4009
	ands	syndrome, syndrome, const_m1, S2LO #16
Packit 6c4009
	bne	.Lstrcmp_done_equal
Packit 6c4009
Packit 6c4009
	ldrh	data2, [src2]
Packit 6c4009
	S2LO	data1, data1, #16
Packit 6c4009
#ifdef __ARM_BIG_ENDIAN
Packit 6c4009
	lsl	data2, data2, #16
Packit 6c4009
#endif
Packit 6c4009
	b	.Lstrcmp_tail
Packit 6c4009
Packit 6c4009
6:
Packit 6c4009
	S2LO	data1, data1, #16
Packit 6c4009
	and	data2, data2, const_m1, S2LO #16
Packit 6c4009
	b	.Lstrcmp_tail
Packit 6c4009
Packit 6c4009
	.p2align 5,,12	/* Ensure at least 3 instructions in cache line.  */
Packit 6c4009
.Loverlap1:
Packit 6c4009
	and	tmp1, data1, #LSB
Packit 6c4009
	uadd8	syndrome, data1, const_m1
Packit 6c4009
	eors	syndrome, tmp1, data2, S2LO #24
Packit 6c4009
	sel	syndrome, syndrome, const_m1
Packit 6c4009
	bne	4f
Packit 6c4009
	cbnz	syndrome, 5f
Packit 6c4009
	ldr	data2, [src2], #4
Packit 6c4009
	eor	tmp1, tmp1, data1
Packit 6c4009
	cmp	tmp1, data2, S2HI #8
Packit 6c4009
	bne	6f
Packit 6c4009
	ldr	data1, [src1], #4
Packit 6c4009
	b	.Loverlap1
Packit 6c4009
4:
Packit 6c4009
	S2LO	data2, data2, #24
Packit 6c4009
	b	.Lstrcmp_tail
Packit 6c4009
5:
Packit 6c4009
	tst	syndrome, #LSB
Packit 6c4009
	bne	.Lstrcmp_done_equal
Packit 6c4009
	ldr	data2, [src2]
Packit 6c4009
6:
Packit 6c4009
	S2LO	data1, data1, #8
Packit 6c4009
	bic	data2, data2, #MSB
Packit 6c4009
	b	.Lstrcmp_tail
Packit 6c4009
Packit 6c4009
.Lstrcmp_done_equal:
Packit 6c4009
	mov	result, #0
Packit 6c4009
	ldrd	r4, r5, [sp], #16
Packit 6c4009
	cfi_remember_state
Packit 6c4009
	cfi_def_cfa_offset (0)
Packit 6c4009
	cfi_restore (r4)
Packit 6c4009
	cfi_restore (r5)
Packit 6c4009
	/* R6/7 not used in this sequence.  */
Packit 6c4009
	cfi_restore (r6)
Packit 6c4009
	cfi_restore (r7)
Packit 6c4009
	bx	lr
Packit 6c4009
Packit 6c4009
.Lstrcmp_tail:
Packit 6c4009
	cfi_restore_state
Packit 6c4009
#ifndef __ARM_BIG_ENDIAN
Packit 6c4009
	rev	data1, data1
Packit 6c4009
	rev	data2, data2
Packit 6c4009
	/* Now everything looks big-endian...  */
Packit 6c4009
#endif
Packit 6c4009
	uadd8	tmp1, data1, const_m1
Packit 6c4009
	eor	tmp1, data1, data2
Packit 6c4009
	sel	syndrome, tmp1, const_m1
Packit 6c4009
	clz	tmp1, syndrome
Packit 6c4009
	lsl	data1, data1, tmp1
Packit 6c4009
	lsl	data2, data2, tmp1
Packit 6c4009
	lsr	result, data1, #24
Packit 6c4009
	ldrd	r4, r5, [sp], #16
Packit 6c4009
	cfi_def_cfa_offset (0)
Packit 6c4009
	cfi_restore (r4)
Packit 6c4009
	cfi_restore (r5)
Packit 6c4009
	/* R6/7 not used in this sequence.  */
Packit 6c4009
	cfi_restore (r6)
Packit 6c4009
	cfi_restore (r7)
Packit 6c4009
	sub	result, result, data2, lsr #24
Packit 6c4009
	bx	lr
Packit 6c4009
END (strcmp)
Packit 6c4009
libc_hidden_builtin_def (strcmp)