Blame sysdeps/x86_64/strcspn.S

Packit Service 82fcde
/* strcspn (str, ss) -- Return the length of the initial segment of STR
Packit Service 82fcde
			which contains no characters from SS.
Packit Service 82fcde
   For AMD x86-64.
Packit Service 82fcde
   Copyright (C) 1994-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>.
Packit Service 82fcde
   Bug fixes by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>.
Packit Service 82fcde
   Adopted for x86-64 by Andreas Jaeger <aj@suse.de>.
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
#include <sysdep.h>
Packit Service 82fcde
#include "asm-syntax.h"
Packit Service 82fcde
Packit Service 82fcde
	.text
Packit Service 82fcde
ENTRY (strcspn)
Packit Service 82fcde
Packit Service 82fcde
	movq %rdi, %rdx		/* Save SRC.  */
Packit Service 82fcde
Packit Service 82fcde
	/* First we create a table with flags for all possible characters.
Packit Service 82fcde
	   For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
Packit Service 82fcde
	   supported by the C string functions we have 256 characters.
Packit Service 82fcde
	   Before inserting marks for the stop characters we clear the whole
Packit Service 82fcde
	   table.  */
Packit Service 82fcde
	movq %rdi, %r8			/* Save value.  */
Packit Service 82fcde
	subq $256, %rsp			/* Make space for 256 bytes.  */
Packit Service 82fcde
	cfi_adjust_cfa_offset(256)
Packit Service 82fcde
	movl $32,  %ecx			/* 32*8 bytes = 256 bytes.  */
Packit Service 82fcde
	movq %rsp, %rdi
Packit Service 82fcde
	xorl %eax, %eax			/* We store 0s.  */
Packit Service 82fcde
	cld
Packit Service 82fcde
	rep
Packit Service 82fcde
	stosq
Packit Service 82fcde
Packit Service 82fcde
	movq %rsi, %rax			/* Setup skipset.  */
Packit Service 82fcde
Packit Service 82fcde
/* For understanding the following code remember that %rcx == 0 now.
Packit Service 82fcde
   Although all the following instruction only modify %cl we always
Packit Service 82fcde
   have a correct zero-extended 64-bit value in %rcx.  */
Packit Service 82fcde
Packit Service 82fcde
	.p2align 4
Packit Service 82fcde
L(2):	movb (%rax), %cl	/* get byte from skipset */
Packit Service 82fcde
	testb %cl, %cl		/* is NUL char? */
Packit Service 82fcde
	jz L(1)			/* yes => start compare loop */
Packit Service 82fcde
	movb %cl, (%rsp,%rcx)	/* set corresponding byte in skipset table */
Packit Service 82fcde
Packit Service 82fcde
	movb 1(%rax), %cl	/* get byte from skipset */
Packit Service 82fcde
	testb $0xff, %cl	/* is NUL char? */
Packit Service 82fcde
	jz L(1)			/* yes => start compare loop */
Packit Service 82fcde
	movb %cl, (%rsp,%rcx)	/* set corresponding byte in skipset table */
Packit Service 82fcde
Packit Service 82fcde
	movb 2(%rax), %cl	/* get byte from skipset */
Packit Service 82fcde
	testb $0xff, %cl	/* is NUL char? */
Packit Service 82fcde
	jz L(1)			/* yes => start compare loop */
Packit Service 82fcde
	movb %cl, (%rsp,%rcx)	/* set corresponding byte in skipset table */
Packit Service 82fcde
Packit Service 82fcde
	movb 3(%rax), %cl	/* get byte from skipset */
Packit Service 82fcde
	addq $4, %rax		/* increment skipset pointer */
Packit Service 82fcde
	movb %cl, (%rsp,%rcx)	/* set corresponding byte in skipset table */
Packit Service 82fcde
	testb $0xff, %cl	/* is NUL char? */
Packit Service 82fcde
	jnz L(2)		/* no => process next dword from skipset */
Packit Service 82fcde
Packit Service 82fcde
L(1):	leaq -4(%rdx), %rax	/* prepare loop */
Packit Service 82fcde
Packit Service 82fcde
	/* We use a neat trick for the following loop.  Normally we would
Packit Service 82fcde
	   have to test for two termination conditions
Packit Service 82fcde
	   1. a character in the skipset was found
Packit Service 82fcde
	   and
Packit Service 82fcde
	   2. the end of the string was found
Packit Service 82fcde
	   But as a sign that the character is in the skipset we store its
Packit Service 82fcde
	   value in the table.  But the value of NUL is NUL so the loop
Packit Service 82fcde
	   terminates for NUL in every case.  */
Packit Service 82fcde
Packit Service 82fcde
	.p2align 4
Packit Service 82fcde
L(3):	addq $4, %rax		/* adjust pointer for full loop round */
Packit Service 82fcde
Packit Service 82fcde
	movb (%rax), %cl	/* get byte from string */
Packit Service 82fcde
	cmpb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit Service 82fcde
	je L(4)			/* yes => return */
Packit Service 82fcde
Packit Service 82fcde
	movb 1(%rax), %cl	/* get byte from string */
Packit Service 82fcde
	cmpb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit Service 82fcde
	je L(5)			/* yes => return */
Packit Service 82fcde
Packit Service 82fcde
	movb 2(%rax), %cl	/* get byte from string */
Packit Service 82fcde
	cmpb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit Service 82fcde
	jz L(6)			/* yes => return */
Packit Service 82fcde
Packit Service 82fcde
	movb 3(%rax), %cl	/* get byte from string */
Packit Service 82fcde
	cmpb %cl, (%rsp,%rcx)	/* is it contained in skipset? */
Packit Service 82fcde
	jne L(3)		/* no => start loop again */
Packit Service 82fcde
Packit Service 82fcde
	incq %rax		/* adjust pointer */
Packit Service 82fcde
L(6):	incq %rax
Packit Service 82fcde
L(5):	incq %rax
Packit Service 82fcde
Packit Service 82fcde
L(4):	addq $256, %rsp		/* remove skipset */
Packit Service 82fcde
	cfi_adjust_cfa_offset(-256)
Packit Service 82fcde
#ifdef USE_AS_STRPBRK
Packit Service 82fcde
	xorl %edx,%edx
Packit Service 82fcde
	orb %cl, %cl		/* was last character NUL? */
Packit Service 82fcde
	cmovzq %rdx, %rax	/* Yes:	return NULL */
Packit Service 82fcde
#else
Packit Service 82fcde
	subq %rdx, %rax		/* we have to return the number of valid
Packit Service 82fcde
				   characters, so compute distance to first
Packit Service 82fcde
				   non-valid character */
Packit Service 82fcde
#endif
Packit Service 82fcde
	ret
Packit Service 82fcde
END (strcspn)
Packit Service 82fcde
libc_hidden_builtin_def (strcspn)