Blame sysdeps/x86_64/strspn.S

Packit 6c4009
/* strspn (str, ss) -- Return the length of the initial segment of STR
Packit 6c4009
			which contains only characters from SS.
Packit 6c4009
   For AMD x86-64.
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
   Adopted for x86-64 by Andreas Jaeger <aj@suse.de>.
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
Packit 6c4009
	.text
Packit 6c4009
ENTRY (strspn)
Packit 6c4009
Packit 6c4009
	movq %rdi, %rdx		/* Save SRC.  */
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.  */
Packit 6c4009
	movq %rdi, %r8			/* Save value.  */
Packit 6c4009
	subq $256, %rsp			/* Make space for 256 bytes.  */
Packit 6c4009
	cfi_adjust_cfa_offset(256)
Packit 6c4009
	movl $32,  %ecx			/* 32*8 bytes = 256 bytes.  */
Packit 6c4009
	movq %rsp, %rdi
Packit 6c4009
	xorl %eax, %eax			/* We store 0s.  */
Packit 6c4009
	cld
Packit 6c4009
	rep
Packit 6c4009
	stosq
Packit 6c4009
Packit 6c4009
	movq %rsi, %rax			/* Setup stopset.  */
Packit 6c4009
Packit 6c4009
/* For understanding the following code remember that %rcx == 0 now.
Packit 6c4009
   Although all the following instruction only modify %cl we always
Packit 6c4009
   have a correct zero-extended 64-bit value in %rcx.  */
Packit 6c4009
Packit 6c4009
	.p2align 4
Packit 6c4009
L(2):	movb (%rax), %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, (%rsp,%rcx)	/* set corresponding byte in stopset table */
Packit 6c4009
Packit 6c4009
	movb 1(%rax), %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, (%rsp,%rcx)	/* set corresponding byte in stopset table */
Packit 6c4009
Packit 6c4009
	movb 2(%rax), %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, (%rsp,%rcx)	/* set corresponding byte in stopset table */
Packit 6c4009
Packit 6c4009
	movb 3(%rax), %cl	/* get byte from stopset */
Packit 6c4009
	addq $4, %rax		/* increment stopset pointer */
Packit 6c4009
	movb %cl, (%rsp,%rcx)	/* 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):	leaq -4(%rdx), %rax	/* 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
	.p2align 4
Packit 6c4009
L(3):	addq $4, %rax		/* adjust pointer for full loop round */
Packit 6c4009
Packit 6c4009
	movb (%rax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit 6c4009
	jz L(4)			/* no => return */
Packit 6c4009
Packit 6c4009
	movb 1(%rax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit 6c4009
	jz L(5)			/* no => return */
Packit 6c4009
Packit 6c4009
	movb 2(%rax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit 6c4009
	jz L(6)			/* no => return */
Packit 6c4009
Packit 6c4009
	movb 3(%rax), %cl	/* get byte from string */
Packit 6c4009
	testb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit 6c4009
	jnz L(3)		/* yes => start loop again */
Packit 6c4009
Packit 6c4009
	incq %rax		/* adjust pointer */
Packit 6c4009
L(6):	incq %rax
Packit 6c4009
L(5):	incq %rax
Packit 6c4009
Packit 6c4009
L(4):	addq $256, %rsp		/* remove stopset */
Packit 6c4009
	cfi_adjust_cfa_offset(-256)
Packit 6c4009
	subq %rdx, %rax		/* 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)