1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
/* strcspn (str, ss) -- Return the length of the initial segment of STR
which contains no characters from SS.
For Intel 80x86, x>=3.
Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
Bug fixes by Alan Modra <Alan@SPRI.Levels.UniSA.Edu.Au>
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <sysdep.h>
#include "asm-syntax.h"
/*
INPUT PARAMETERS:
str (sp + 4)
stopset (sp + 8)
*/
.text
ENTRY (strcspn)
movl 4(%esp), %edx /* get string pointer */
movl 8(%esp), %eax /* get stopset pointer */
/* First we create a table with flags for all possible characters.
For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
supported by the C string functions we have 256 characters.
Before inserting marks for the stop characters we clear the whole
table. The unrolled form is much faster than a loop. */
xorl %ecx, %ecx /* %ecx = 0 !!! */
pushl %ecx /* make a 256 bytes long block filled with 0 */
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl %ecx
pushl $0 /* These immediate values make the label 2 */
pushl $0 /* to be aligned on a 16 byte boundary to */
pushl $0 /* get a better performance of the loop. */
pushl $0
pushl $0
pushl $0
/* For understanding the following code remember that %ecx == 0 now.
Although all the following instruction only modify %cl we always
have a correct zero-extended 32-bit value in %ecx. */
/* Don't change the "testb $0xff,%%cl" to "testb %%cl,%%cl". We want
longer instructions so that the next loop aligns without adding nops. */
L(2): movb (%eax), %cl /* get byte from stopset */
testb %cl, %cl /* is NUL char? */
jz L(1) /* yes => start compare loop */
movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
movb 1(%eax), %cl /* get byte from stopset */
testb $0xff, %cl /* is NUL char? */
jz L(1) /* yes => start compare loop */
movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
movb 2(%eax), %cl /* get byte from stopset */
testb $0xff, %cl /* is NUL char? */
jz L(1) /* yes => start compare loop */
movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
movb 3(%eax), %cl /* get byte from stopset */
addl $4, %eax /* increment stopset pointer */
movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
testb $0xff, %cl /* is NUL char? */
jnz L(2) /* no => process next dword from stopset */
L(1): leal -4(%edx), %eax /* prepare loop */
/* We use a neat trick for the following loop. Normally we would
have to test for two termination conditions
1. a character in the stopset was found
and
2. the end of the string was found
But as a sign that the character is in the stopset we store its
value in the table. But the value of NUL is NUL so the loop
terminates for NUL in every case. */
L(3): addl $4, %eax /* adjust pointer for full loop round */
movb (%eax), %cl /* get byte from string */
cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
je L(4) /* yes => return */
movb 1(%eax), %cl /* get byte from string */
cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
je L(5) /* yes => return */
movb 2(%eax), %cl /* get byte from string */
cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
je L(6) /* yes => return */
movb 3(%eax), %cl /* get byte from string */
cmpb %cl, (%esp,%ecx) /* is it contained in stopset? */
jne L(3) /* yes => return */
incl %eax /* adjust pointer */
L(6): incl %eax
L(5): incl %eax
L(4): subl %edx, %eax /* we have to return the number of valid
characters, so compute distance to first
non-valid character */
addl $256, %esp /* remove stopset */
ret
END (strcspn)
|