Blame sysdeps/i386/strspn.S

Packit 6c4009
/* strcspn (str, ss) -- Return the length of the initial segment of STR
Packit 6c4009
			which contains only characters from SS.
Packit 6c4009
   For Intel 80x86, x>=3.
Packit 6c4009
   Copyright (C) 1994-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
Packit 6c4009
   Bug fixes by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
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 "asm-syntax.h"
Packit 6c4009
Packit 6c4009
#define PARMS	4		/* no space for saved regs */
Packit 6c4009
#define STR	PARMS
Packit 6c4009
#define SKIP	STR+4
Packit 6c4009
Packit 6c4009
	.text
Packit 6c4009
ENTRY (strspn)
Packit 6c4009
Packit 6c4009
	movl STR(%esp), %edx
Packit 6c4009
	movl SKIP(%esp), %eax
Packit 6c4009
Packit 6c4009
	/* First we create a table with flags for all possible characters.
Packit 6c4009
	   For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
Packit 6c4009
	   supported by the C string functions we have 256 characters.
Packit 6c4009
	   Before inserting marks for the stop characters we clear the whole
Packit 6c4009
	   table.  The unrolled form is much faster than a loop.  */
Packit 6c4009
	xorl %ecx, %ecx		/* %ecx = 0 !!! */
Packit 6c4009
Packit 6c4009
	pushl %ecx		/* make a 256 bytes long block filled with 0 */
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl %ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl $0		/* These immediate values make the label 2 */
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl $0		/* to be aligned on a 16 byte boundary to */
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl $0		/* get a better performance of the loop.  */
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl $0
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl $0
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl $0
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
Packit 6c4009
/* For understanding the following code remember that %ecx == 0 now.
Packit 6c4009
   Although all the following instruction only modify %cl we always
Packit 6c4009
   have a correct zero-extended 32-bit value in %ecx.  */
Packit 6c4009
Packit 6c4009
/* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl".  We want
Packit 6c4009
   longer instructions so that the next loop aligns without adding nops.  */
Packit 6c4009
Packit 6c4009
L(2):	movb (%eax), %cl	/* get byte from stopset */
Packit 6c4009
	testb %cl, %cl		/* is NUL char? */
Packit 6c4009
	jz L(1)			/* yes => start compare loop */
Packit 6c4009
	movb %cl, (%esp,%ecx)	/* set corresponding byte in stopset table */
Packit 6c4009
Packit 6c4009
	movb 1(%eax), %cl	/* get byte from stopset */
Packit 6c4009
	testb $0xff, %cl	/* is NUL char? */
Packit 6c4009
	jz L(1)			/* yes => start compare loop */
Packit 6c4009
	movb %cl, (%esp,%ecx)	/* set corresponding byte in stopset table */
Packit 6c4009
Packit 6c4009
	movb 2(%eax), %cl	/* get byte from stopset */
Packit 6c4009
	testb $0xff, %cl	/* is NUL char? */
Packit 6c4009
	jz L(1)			/* yes => start compare loop */
Packit 6c4009
	movb %cl, (%esp,%ecx)	/* set corresponding byte in stopset table */
Packit 6c4009
Packit 6c4009
	movb 3(%eax), %cl	/* get byte from stopset */
Packit 6c4009
	addl $4, %eax		/* increment stopset pointer */
Packit 6c4009
	movb %cl, (%esp,%ecx)	/* set corresponding byte in stopset table */
Packit 6c4009
	testb $0xff, %cl	/* is NUL char? */
Packit 6c4009
	jnz L(2)		/* no => process next dword from stopset */
Packit 6c4009
Packit 6c4009
L(1):	leal -4(%edx), %eax	/* prepare loop */
Packit 6c4009
Packit 6c4009
	/* We use a neat trick for the following loop.  Normally we would
Packit 6c4009
	   have to test for two termination conditions
Packit 6c4009
	   1. a character in the stopset was found
Packit 6c4009
	   and
Packit 6c4009
	   2. the end of the string was found
Packit 6c4009
	   But as a sign that the character is in the stopset we store its
Packit 6c4009
	   value in the table.  But the value of NUL is NUL so the loop
Packit 6c4009
	   terminates for NUL in every case.  */
Packit 6c4009
Packit 6c4009
L(3):	addl $4, %eax		/* adjust pointer for full loop round */
Packit 6c4009
Packit 6c4009
	movb (%eax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%esp,%ecx)	/* is it contained in skipset? */
Packit 6c4009
	jz L(4)			/* no => return */
Packit 6c4009
Packit 6c4009
	movb 1(%eax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%esp,%ecx)	/* is it contained in skipset? */
Packit 6c4009
	jz L(5)			/* no => return */
Packit 6c4009
Packit 6c4009
	movb 2(%eax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%esp,%ecx)	/* is it contained in skipset? */
Packit 6c4009
	jz L(6)			/* no => return */
Packit 6c4009
Packit 6c4009
	movb 3(%eax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%esp,%ecx)	/* is it contained in skipset? */
Packit 6c4009
	jnz L(3)		/* yes => start loop again */
Packit 6c4009
Packit 6c4009
	incl %eax		/* adjust pointer */
Packit 6c4009
L(6):	incl %eax
Packit 6c4009
L(5):	incl %eax
Packit 6c4009
Packit 6c4009
L(4):	addl $256, %esp		/* remove stopset */
Packit 6c4009
	cfi_adjust_cfa_offset (-256)
Packit 6c4009
	subl %edx, %eax		/* we have to return the number of valid
Packit 6c4009
				   characters, so compute distance to first
Packit 6c4009
				   non-valid character */
Packit 6c4009
	ret
Packit 6c4009
END (strspn)
Packit 6c4009
libc_hidden_builtin_def (strspn)