Blame sysdeps/mips/strcmp.S

Packit Service 82fcde
/* Copyright (C) 2014-2018 Free Software Foundation, Inc.
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
#ifdef ANDROID_CHANGES
Packit Service 82fcde
# include "machine/asm.h"
Packit Service 82fcde
# include "machine/regdef.h"
Packit Service 82fcde
#elif _LIBC
Packit Service 82fcde
# include <sysdep.h>
Packit Service 82fcde
# include <regdef.h>
Packit Service 82fcde
# include <sys/asm.h>
Packit Service 82fcde
#elif defined _COMPILING_NEWLIB
Packit Service 82fcde
# include "machine/asm.h"
Packit Service 82fcde
# include "machine/regdef.h"
Packit Service 82fcde
#else
Packit Service 82fcde
# include <regdef.h>
Packit Service 82fcde
# include <sys/asm.h>
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Technically strcmp should not read past the end of the strings being
Packit Service 82fcde
   compared.  We will read a full word that may contain excess bits beyond
Packit Service 82fcde
   the NULL string terminator but unless ENABLE_READAHEAD is set, we will not
Packit Service 82fcde
   read the next word after the end of string.  Setting ENABLE_READAHEAD will
Packit Service 82fcde
   improve performance but is technically illegal based on the definition of
Packit Service 82fcde
   strcmp.  */
Packit Service 82fcde
#ifdef ENABLE_READAHEAD
Packit Service 82fcde
# define DELAY_READ
Packit Service 82fcde
#else
Packit Service 82fcde
# define DELAY_READ nop
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Testing on a little endian machine showed using CLZ was a
Packit Service 82fcde
   performance loss, so we are not turning it on by default.  */
Packit Service 82fcde
#if defined(ENABLE_CLZ) && (__mips_isa_rev > 1)
Packit Service 82fcde
# define USE_CLZ
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Some asm.h files do not have the L macro definition.  */
Packit Service 82fcde
#ifndef L
Packit Service 82fcde
# if _MIPS_SIM == _ABIO32
Packit Service 82fcde
#  define L(label) $L ## label
Packit Service 82fcde
# else
Packit Service 82fcde
#  define L(label) .L ## label
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Some asm.h files do not have the PTR_ADDIU macro definition.  */
Packit Service 82fcde
#ifndef PTR_ADDIU
Packit Service 82fcde
# ifdef USE_DOUBLE
Packit Service 82fcde
#  define PTR_ADDIU       daddiu
Packit Service 82fcde
# else
Packit Service 82fcde
#  define PTR_ADDIU       addiu
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Allow the routine to be named something else if desired.  */
Packit Service 82fcde
#ifndef STRCMP_NAME
Packit Service 82fcde
# define STRCMP_NAME strcmp
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifdef ANDROID_CHANGES
Packit Service 82fcde
LEAF(STRCMP_NAME, 0)
Packit Service 82fcde
#else
Packit Service 82fcde
LEAF(STRCMP_NAME)
Packit Service 82fcde
#endif
Packit Service 82fcde
	.set	nomips16
Packit Service 82fcde
	.set	noreorder
Packit Service 82fcde
Packit Service 82fcde
	or	t0, a0, a1
Packit Service 82fcde
	andi	t0,0x3
Packit Service 82fcde
	bne	t0, zero, L(byteloop)
Packit Service 82fcde
Packit Service 82fcde
/* Both strings are 4 byte aligned at this point.  */
Packit Service 82fcde
Packit Service 82fcde
	lui	t8, 0x0101
Packit Service 82fcde
	ori	t8, t8, 0x0101
Packit Service 82fcde
	lui	t9, 0x7f7f
Packit Service 82fcde
	ori	t9, 0x7f7f
Packit Service 82fcde
Packit Service 82fcde
#define STRCMP32(OFFSET) \
Packit Service 82fcde
	lw	v0, OFFSET(a0); \
Packit Service 82fcde
	lw	v1, OFFSET(a1); \
Packit Service 82fcde
	subu	t0, v0, t8; \
Packit Service 82fcde
	bne	v0, v1, L(worddiff); \
Packit Service 82fcde
	nor	t1, v0, t9; \
Packit Service 82fcde
	and	t0, t0, t1; \
Packit Service 82fcde
	bne	t0, zero, L(returnzero)
Packit Service 82fcde
Packit Service 82fcde
L(wordloop):
Packit Service 82fcde
	STRCMP32(0)
Packit Service 82fcde
	DELAY_READ
Packit Service 82fcde
	STRCMP32(4)
Packit Service 82fcde
	DELAY_READ
Packit Service 82fcde
	STRCMP32(8)
Packit Service 82fcde
	DELAY_READ
Packit Service 82fcde
	STRCMP32(12)
Packit Service 82fcde
	DELAY_READ
Packit Service 82fcde
	STRCMP32(16)
Packit Service 82fcde
	DELAY_READ
Packit Service 82fcde
	STRCMP32(20)
Packit Service 82fcde
	DELAY_READ
Packit Service 82fcde
	STRCMP32(24)
Packit Service 82fcde
	DELAY_READ
Packit Service 82fcde
	STRCMP32(28)
Packit Service 82fcde
	PTR_ADDIU a0, a0, 32
Packit Service 82fcde
	b	L(wordloop)
Packit Service 82fcde
	PTR_ADDIU a1, a1, 32
Packit Service 82fcde
Packit Service 82fcde
L(returnzero):
Packit Service 82fcde
	j	ra
Packit Service 82fcde
	move	v0, zero
Packit Service 82fcde
Packit Service 82fcde
L(worddiff):
Packit Service 82fcde
#ifdef USE_CLZ
Packit Service 82fcde
	subu	t0, v0, t8
Packit Service 82fcde
	nor	t1, v0, t9
Packit Service 82fcde
	and	t1, t0, t1
Packit Service 82fcde
	xor	t0, v0, v1
Packit Service 82fcde
	or	t0, t0, t1
Packit Service 82fcde
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Packit Service 82fcde
	wsbh	t0, t0
Packit Service 82fcde
	rotr	t0, t0, 16
Packit Service 82fcde
# endif
Packit Service 82fcde
	clz	t1, t0
Packit Service 82fcde
	and	t1, 0xf8
Packit Service 82fcde
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
Packit Service 82fcde
	neg	t1
Packit Service 82fcde
	addu	t1, 24
Packit Service 82fcde
# endif
Packit Service 82fcde
	rotrv	v0, v0, t1
Packit Service 82fcde
	rotrv	v1, v1, t1
Packit Service 82fcde
	and	v0, v0, 0xff
Packit Service 82fcde
	and	v1, v1, 0xff
Packit Service 82fcde
	j	ra
Packit Service 82fcde
	subu	v0, v0, v1
Packit Service 82fcde
#else /* USE_CLZ */
Packit Service 82fcde
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Packit Service 82fcde
	andi	t0, v0, 0xff
Packit Service 82fcde
	beq	t0, zero, L(wexit01)
Packit Service 82fcde
	andi	t1, v1, 0xff
Packit Service 82fcde
	bne	t0, t1, L(wexit01)
Packit Service 82fcde
Packit Service 82fcde
	srl	t8, v0, 8
Packit Service 82fcde
	srl	t9, v1, 8
Packit Service 82fcde
	andi	t8, t8, 0xff
Packit Service 82fcde
	beq	t8, zero, L(wexit89)
Packit Service 82fcde
	andi	t9, t9, 0xff
Packit Service 82fcde
	bne	t8, t9, L(wexit89)
Packit Service 82fcde
Packit Service 82fcde
	srl	t0, v0, 16
Packit Service 82fcde
	srl	t1, v1, 16
Packit Service 82fcde
	andi	t0, t0, 0xff
Packit Service 82fcde
	beq	t0, zero, L(wexit01)
Packit Service 82fcde
	andi	t1, t1, 0xff
Packit Service 82fcde
	bne	t0, t1, L(wexit01)
Packit Service 82fcde
Packit Service 82fcde
	srl	t8, v0, 24
Packit Service 82fcde
	srl	t9, v1, 24
Packit Service 82fcde
# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
Packit Service 82fcde
	srl	t0, v0, 24
Packit Service 82fcde
	beq	t0, zero, L(wexit01)
Packit Service 82fcde
	srl	t1, v1, 24
Packit Service 82fcde
	bne	t0, t1, L(wexit01)
Packit Service 82fcde
Packit Service 82fcde
	srl	t8, v0, 16
Packit Service 82fcde
	srl	t9, v1, 16
Packit Service 82fcde
	andi	t8, t8, 0xff
Packit Service 82fcde
	beq	t8, zero, L(wexit89)
Packit Service 82fcde
	andi	t9, t9, 0xff
Packit Service 82fcde
	bne	t8, t9, L(wexit89)
Packit Service 82fcde
Packit Service 82fcde
	srl	t0, v0, 8
Packit Service 82fcde
	srl	t1, v1, 8
Packit Service 82fcde
	andi	t0, t0, 0xff
Packit Service 82fcde
	beq	t0, zero, L(wexit01)
Packit Service 82fcde
	andi	t1, t1, 0xff
Packit Service 82fcde
	bne	t0, t1, L(wexit01)
Packit Service 82fcde
Packit Service 82fcde
	andi	t8, v0, 0xff
Packit Service 82fcde
	andi	t9, v1, 0xff
Packit Service 82fcde
# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
Packit Service 82fcde
Packit Service 82fcde
L(wexit89):
Packit Service 82fcde
	j	ra
Packit Service 82fcde
	subu	v0, t8, t9
Packit Service 82fcde
L(wexit01):
Packit Service 82fcde
	j	ra
Packit Service 82fcde
	subu	v0, t0, t1
Packit Service 82fcde
#endif /* USE_CLZ */
Packit Service 82fcde
Packit Service 82fcde
/* It might seem better to do the 'beq' instruction between the two 'lbu'
Packit Service 82fcde
   instructions so that the nop is not needed but testing showed that this
Packit Service 82fcde
   code is actually faster (based on glibc strcmp test).  */
Packit Service 82fcde
#define BYTECMP01(OFFSET) \
Packit Service 82fcde
	lbu	v0, OFFSET(a0); \
Packit Service 82fcde
	lbu	v1, OFFSET(a1); \
Packit Service 82fcde
	beq	v0, zero, L(bexit01); \
Packit Service 82fcde
	nop; \
Packit Service 82fcde
	bne	v0, v1, L(bexit01)
Packit Service 82fcde
Packit Service 82fcde
#define BYTECMP89(OFFSET) \
Packit Service 82fcde
	lbu	t8, OFFSET(a0); \
Packit Service 82fcde
	lbu	t9, OFFSET(a1); \
Packit Service 82fcde
	beq	t8, zero, L(bexit89); \
Packit Service 82fcde
	nop;	\
Packit Service 82fcde
	bne	t8, t9, L(bexit89)
Packit Service 82fcde
Packit Service 82fcde
L(byteloop):
Packit Service 82fcde
	BYTECMP01(0)
Packit Service 82fcde
	BYTECMP89(1)
Packit Service 82fcde
	BYTECMP01(2)
Packit Service 82fcde
	BYTECMP89(3)
Packit Service 82fcde
	BYTECMP01(4)
Packit Service 82fcde
	BYTECMP89(5)
Packit Service 82fcde
	BYTECMP01(6)
Packit Service 82fcde
	BYTECMP89(7)
Packit Service 82fcde
	PTR_ADDIU a0, a0, 8
Packit Service 82fcde
	b	L(byteloop)
Packit Service 82fcde
	PTR_ADDIU a1, a1, 8
Packit Service 82fcde
Packit Service 82fcde
L(bexit01):
Packit Service 82fcde
	j	ra
Packit Service 82fcde
	subu	v0, v0, v1
Packit Service 82fcde
L(bexit89):
Packit Service 82fcde
	j	ra
Packit Service 82fcde
	subu	v0, t8, t9
Packit Service 82fcde
Packit Service 82fcde
	.set	at
Packit Service 82fcde
	.set	reorder
Packit Service 82fcde
Packit Service 82fcde
END(STRCMP_NAME)
Packit Service 82fcde
#ifndef ANDROID_CHANGES
Packit Service 82fcde
# ifdef _LIBC
Packit Service 82fcde
libc_hidden_builtin_def (STRCMP_NAME)
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif