Blame sysdeps/alpha/strcmp.S

Packit Service 82fcde
/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   Contributed by Richard Henderson (rth@tamu.edu)
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library.  If not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* Bytewise compare two null-terminated strings.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
Packit Service 82fcde
	.set noat
Packit Service 82fcde
	.set noreorder
Packit Service 82fcde
Packit Service 82fcde
	.text
Packit Service 82fcde
Packit Service 82fcde
ENTRY(strcmp)
Packit Service 82fcde
#ifdef PROF
Packit Service 82fcde
	ldgp	gp, 0(pv)
Packit Service 82fcde
	lda	AT, _mcount
Packit Service 82fcde
	jmp	AT, (AT), _mcount
Packit Service 82fcde
	.prologue 1
Packit Service 82fcde
#else
Packit Service 82fcde
	.prologue 0
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
	ldq_u	t0, 0(a0)	# e0    : give cache time to catch up
Packit Service 82fcde
	xor	a0, a1, t2	# .. e1 : are s1 and s2 co-aligned?
Packit Service 82fcde
	ldq_u	t1, 0(a1)	# e0    :
Packit Service 82fcde
	and	t2, 7, t2	# .. e1 :
Packit Service 82fcde
	lda	t3, -1		# e0    :
Packit Service 82fcde
	bne	t2, $unaligned	# .. e1 :
Packit Service 82fcde
Packit Service 82fcde
	/* On entry to this basic block:
Packit Service 82fcde
	   t0 == the first destination word for masking back in
Packit Service 82fcde
	   t1 == the first source word.
Packit Service 82fcde
	   t3 == -1.  */
Packit Service 82fcde
Packit Service 82fcde
$aligned:
Packit Service 82fcde
	mskqh	t3, a0, t3	# e0    :
Packit Service 82fcde
	nop			# .. e1 :
Packit Service 82fcde
	ornot	t1, t3, t1	# e0    :
Packit Service 82fcde
	ornot	t0, t3, t0	# .. e1 :
Packit Service 82fcde
	cmpbge	zero, t1, t7	# e0    : bits set iff null found
Packit Service 82fcde
	bne	t7, $eos	# e1 (zdb)
Packit Service 82fcde
Packit Service 82fcde
	/* Aligned compare main loop.
Packit Service 82fcde
	   On entry to this basic block:
Packit Service 82fcde
	   t0 == an s1 word.
Packit Service 82fcde
	   t1 == an s2 word not containing a null.  */
Packit Service 82fcde
Packit Service 82fcde
$a_loop:
Packit Service 82fcde
	xor	t0, t1, t2	# e0	:
Packit Service 82fcde
	bne	t2, $wordcmp	# .. e1 (zdb)
Packit Service 82fcde
	ldq_u	t1, 8(a1)	# e0    :
Packit Service 82fcde
	ldq_u	t0, 8(a0)	# .. e1 :
Packit Service 82fcde
	addq	a1, 8, a1	# e0    :
Packit Service 82fcde
	addq	a0, 8, a0	# .. e1 :
Packit Service 82fcde
	cmpbge	zero, t1, t7	# e0    :
Packit Service 82fcde
	beq	t7, $a_loop	# .. e1 (zdb)
Packit Service 82fcde
	br	$eos		# e1    :
Packit Service 82fcde
Packit Service 82fcde
	/* The two strings are not co-aligned.  Align s1 and cope.  */
Packit Service 82fcde
Packit Service 82fcde
$unaligned:
Packit Service 82fcde
	and	a0, 7, t4	# e0    : find s1 misalignment
Packit Service 82fcde
	and	a1, 7, t5	# .. e1 : find s2 misalignment
Packit Service 82fcde
	subq	a1, t4, a1	# e0    :
Packit Service 82fcde
Packit Service 82fcde
	/* If s2 misalignment is larger than s2 misalignment, we need
Packit Service 82fcde
	   extra startup checks to avoid SEGV.  */
Packit Service 82fcde
Packit Service 82fcde
	cmplt	t4, t5, t8	# .. e1 :
Packit Service 82fcde
	beq	t8, $u_head	# e1    :
Packit Service 82fcde
Packit Service 82fcde
	mskqh	t3, t5, t3	# e0    :
Packit Service 82fcde
	ornot	t1, t3, t3	# e0    :
Packit Service 82fcde
	cmpbge	zero, t3, t7	# e1    : is there a zero?
Packit Service 82fcde
	beq	t7, $u_head	# e1    :
Packit Service 82fcde
Packit Service 82fcde
	/* We've found a zero in the first partial word of s2.  Align
Packit Service 82fcde
	   our current s1 and s2 words and compare what we've got.  */
Packit Service 82fcde
Packit Service 82fcde
	extql	t1, t5, t1	# e0    :
Packit Service 82fcde
	extql	t0, a0, t0	# e0    :
Packit Service 82fcde
	cmpbge	zero, t1, t7	# .. e1 : find that zero again
Packit Service 82fcde
	br	$eos		# e1    : and finish up
Packit Service 82fcde
Packit Service 82fcde
	.align 3
Packit Service 82fcde
$u_head:
Packit Service 82fcde
	/* We know just enough now to be able to assemble the first
Packit Service 82fcde
	   full word of s2.  We can still find a zero at the end of it.
Packit Service 82fcde
Packit Service 82fcde
	   On entry to this basic block:
Packit Service 82fcde
	   t0 == first word of s1
Packit Service 82fcde
	   t1 == first partial word of s2.  */
Packit Service 82fcde
Packit Service 82fcde
	ldq_u	t2, 8(a1)	# e0    : load second partial s2 word
Packit Service 82fcde
	lda	t3, -1		# .. e1 : create leading garbage mask
Packit Service 82fcde
	extql	t1, a1, t1	# e0    : create first s2 word
Packit Service 82fcde
	mskqh	t3, a0, t3	# e0    :
Packit Service 82fcde
	extqh	t2, a1, t4	# e0    :
Packit Service 82fcde
	ornot	t0, t3, t0	# .. e1 : kill s1 garbage
Packit Service 82fcde
	or	t1, t4, t1	# e0    : s2 word now complete
Packit Service 82fcde
	cmpbge	zero, t0, t7	# .. e1 : find zero in first s1 word
Packit Service 82fcde
	ornot	t1, t3, t1	# e0    : kill s2 garbage
Packit Service 82fcde
	lda	t3, -1		# .. e1 :
Packit Service 82fcde
	mskql	t3, a1, t3	# e0    : mask for s2[1] bits we have seen
Packit Service 82fcde
	bne	t7, $eos	# .. e1 :
Packit Service 82fcde
	xor	t0, t1, t4	# e0    : compare aligned words
Packit Service 82fcde
	bne	t4, $wordcmp	# .. e1 (zdb)
Packit Service 82fcde
	or	t2, t3, t3	# e0    :
Packit Service 82fcde
	cmpbge	zero, t3, t7	# e1    :
Packit Service 82fcde
	bne	t7, $u_final	# e1    :
Packit Service 82fcde
Packit Service 82fcde
	/* Unaligned copy main loop.  In order to avoid reading too much,
Packit Service 82fcde
	   the loop is structured to detect zeros in aligned words from s2.
Packit Service 82fcde
	   This has, unfortunately, effectively pulled half of a loop
Packit Service 82fcde
	   iteration out into the head and half into the tail, but it does
Packit Service 82fcde
	   prevent nastiness from accumulating in the very thing we want
Packit Service 82fcde
	   to run as fast as possible.
Packit Service 82fcde
Packit Service 82fcde
	   On entry to this basic block:
Packit Service 82fcde
	   t2 == the unshifted low-bits from the next s2 word.  */
Packit Service 82fcde
Packit Service 82fcde
	.align 3
Packit Service 82fcde
$u_loop:
Packit Service 82fcde
	extql	t2, a1, t3	# e0    :
Packit Service 82fcde
	ldq_u	t2, 16(a1)	# .. e1 : load next s2 high bits
Packit Service 82fcde
	ldq_u	t0, 8(a0)	# e0    : load next s1 word
Packit Service 82fcde
	addq	a1, 8, a1	# .. e1 :
Packit Service 82fcde
	addq	a0, 8, a0	# e0    :
Packit Service 82fcde
	nop			# .. e1 :
Packit Service 82fcde
	extqh	t2, a1, t1	# e0    :
Packit Service 82fcde
	cmpbge	zero, t0, t7	# .. e1 : find zero in current s1 word
Packit Service 82fcde
	or	t1, t3, t1	# e0    :
Packit Service 82fcde
	bne	t7, $eos	# .. e1 :
Packit Service 82fcde
	xor	t0, t1, t4	# e0    : compare the words
Packit Service 82fcde
	bne	t4, $wordcmp	# .. e1 (zdb)
Packit Service 82fcde
	cmpbge	zero, t2, t4	# e0    : find zero in next low bits
Packit Service 82fcde
	beq	t4, $u_loop	# .. e1 (zdb)
Packit Service 82fcde
Packit Service 82fcde
	/* We've found a zero in the low bits of the last s2 word.  Get
Packit Service 82fcde
	   the next s1 word and align them.  */
Packit Service 82fcde
$u_final:
Packit Service 82fcde
	ldq_u	t0, 8(a0)	# e1    :
Packit Service 82fcde
	extql	t2, a1, t1	# .. e0 :
Packit Service 82fcde
	cmpbge	zero, t1, t7	# e0    :
Packit Service 82fcde
Packit Service 82fcde
	/* We've found a zero somewhere in a word we just read.
Packit Service 82fcde
	   On entry to this basic block:
Packit Service 82fcde
	   t0 == s1 word
Packit Service 82fcde
	   t1 == s2 word
Packit Service 82fcde
	   t7 == cmpbge mask containing the zero.  */
Packit Service 82fcde
Packit Service 82fcde
	.align 3
Packit Service 82fcde
$eos:
Packit Service 82fcde
	negq	t7, t6		# e0    : create bytemask of valid data
Packit Service 82fcde
	and	t6, t7, t8	# e1    :
Packit Service 82fcde
	subq	t8, 1, t6	# e0    :
Packit Service 82fcde
	or	t6, t8, t7	# e1    :
Packit Service 82fcde
	zapnot	t0, t7, t0	# e0    : kill the garbage
Packit Service 82fcde
	zapnot	t1, t7, t1	# .. e1 :
Packit Service 82fcde
	xor	t0, t1, v0	# e0    : and compare
Packit Service 82fcde
	beq	v0, $done	# .. e1 :
Packit Service 82fcde
Packit Service 82fcde
	/* Here we have two differing co-aligned words in t0 & t1.
Packit Service 82fcde
	   Bytewise compare them and return (t0 > t1 ? 1 : -1).  */
Packit Service 82fcde
$wordcmp:
Packit Service 82fcde
	cmpbge	t0, t1, t2	# e0    : comparison yields bit mask of ge
Packit Service 82fcde
	cmpbge	t1, t0, t3	# .. e1 :
Packit Service 82fcde
	xor	t2, t3, t0	# e0    : bits set iff t0/t1 bytes differ
Packit Service 82fcde
	negq	t0, t1		# e1    : clear all but least bit
Packit Service 82fcde
	and	t0, t1, t0	# e0    :
Packit Service 82fcde
	lda	v0, -1		# .. e1 :
Packit Service 82fcde
	and	t0, t2, t1	# e0    : was bit set in t0 > t1?
Packit Service 82fcde
	cmovne	t1, 1, v0	# .. e1 (zdb)
Packit Service 82fcde
Packit Service 82fcde
$done:
Packit Service 82fcde
	ret			# e1    :
Packit Service 82fcde
Packit Service 82fcde
	END(strcmp)
Packit Service 82fcde
libc_hidden_builtin_def (strcmp)