home *** CD-ROM | disk | FTP | other *** search
- /* strspn (str, ss) -- Return the length of the initial segement of STR
- which contains only characters from SS.
- For Intel 80x86, x>=3.
- Copyright (C) 1994 Free Software Foundation, Inc.
- Contributed by Ulrich Drepper <drepper@ira.uka.de>
-
- 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., 675 Mass Ave,
- Cambridge, MA 02139, USA. */
-
- #include <string.h>
-
- #include "asm-ops.h"
-
- size_t
- strspn(const char *str, const char *skipset)
- {
- register size_t __res;
- __asm__(
- /*
- * 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\n\t" /* Put 0 in a register because the */
- "movl %%ecx,-4(%%esp)\n\t" /* resulting code for all the moves */
- "movl %%ecx,-8(%%esp)\n\t" /* is a lot shorter. */
- "movl %%ecx,-12(%%esp)\n\t"
- "movl %%ecx,-16(%%esp)\n\t"
- "movl %%ecx,-20(%%esp)\n\t"
- "movl %%ecx,-24(%%esp)\n\t"
- "movl %%ecx,-28(%%esp)\n\t"
- "movl %%ecx,-32(%%esp)\n\t"
- "movl %%ecx,-36(%%esp)\n\t"
- "movl %%ecx,-40(%%esp)\n\t"
- "movl %%ecx,-44(%%esp)\n\t"
- "movl %%ecx,-48(%%esp)\n\t"
- "movl %%ecx,-52(%%esp)\n\t"
- "movl %%ecx,-56(%%esp)\n\t"
- "movl %%ecx,-60(%%esp)\n\t"
- "movl %%ecx,-64(%%esp)\n\t"
- "movl %%ecx,-68(%%esp)\n\t"
- "movl %%ecx,-72(%%esp)\n\t"
- "movl %%ecx,-76(%%esp)\n\t"
- "movl %%ecx,-80(%%esp)\n\t"
- "movl %%ecx,-84(%%esp)\n\t"
- "movl %%ecx,-88(%%esp)\n\t"
- "movl %%ecx,-92(%%esp)\n\t"
- "movl %%ecx,-96(%%esp)\n\t"
- "movl %%ecx,-100(%%esp)\n\t"
- "movl %%ecx,-104(%%esp)\n\t"
- "movl %%ecx,-108(%%esp)\n\t"
- "movl %%ecx,-112(%%esp)\n\t"
- "movl %%ecx,-116(%%esp)\n\t"
- "movl %%ecx,-120(%%esp)\n\t"
- "movl %%ecx,-124(%%esp)\n\t"
- "movl %%ecx,-128(%%esp)\n\t"
- "movl %%ecx,-132(%%esp)\n\t"
- "movl %%ecx,-136(%%esp)\n\t"
- "movl %%ecx,-140(%%esp)\n\t"
- "movl %%ecx,-144(%%esp)\n\t"
- "movl %%ecx,-148(%%esp)\n\t"
- "movl %%ecx,-152(%%esp)\n\t"
- "movl %%ecx,-156(%%esp)\n\t"
- "movl %%ecx,-160(%%esp)\n\t"
- "movl %%ecx,-164(%%esp)\n\t"
- "movl %%ecx,-168(%%esp)\n\t"
- "movl %%ecx,-172(%%esp)\n\t"
- "movl %%ecx,-176(%%esp)\n\t"
- "movl %%ecx,-180(%%esp)\n\t"
- "movl %%ecx,-184(%%esp)\n\t"
- "movl %%ecx,-188(%%esp)\n\t"
- "movl %%ecx,-192(%%esp)\n\t"
- "movl %%ecx,-196(%%esp)\n\t"
- "movl %%ecx,-200(%%esp)\n\t"
- "movl %%ecx,-204(%%esp)\n\t"
- "movl %%ecx,-208(%%esp)\n\t"
- "movl %%ecx,-212(%%esp)\n\t"
- "movl %%ecx,-216(%%esp)\n\t"
- "movl %%ecx,-220(%%esp)\n\t"
- "movl %%ecx,-224(%%esp)\n\t"
- "movl %%ecx,-228(%%esp)\n\t"
- "movl %%ecx,-232(%%esp)\n\t"
- "movl %%ecx,-236(%%esp)\n\t"
- "movl %%ecx,-240(%%esp)\n\t"
- "movl %%ecx,-244(%%esp)\n\t"
- "movl %%ecx,-248(%%esp)\n\t"
- "movl %%ecx,-252(%%esp)\n\t"
- "movl %%ecx,-256(%%esp)\n\t"
-
- "movl $-4,%%eax\n\t" /* This is a trick. For i486 alignment
- * here would be a big NOP hole. We
- * can use this hole for setting some
- * registers for the following code.
- * Eax is not used in this asm stat.
- * but in the following (see below).
- */
- ALIGN "\n"
-
- LL(2) "\tmovb (%0),%%cl\n\t" /* get char from stopset */
- "movb %%cl,-256(%%esp,%%ecx)\n\t" /* mark as stop character in table */
- "testl %%ecx,%%ecx\n\t" /* was NULL char */
- "jz " LF(1) "\n\t" /* yes, than stop */
-
- "movb 1(%0),%%cl\n\t"
- "movb %%cl,-256(%%esp,%%ecx)\n\t"
- "test %%ecx,%%ecx\n\t"
- "jz " LF(1) "\n\t"
-
- "movb 2(%0),%%cl\n\t"
- "movb %%cl,-256(%%esp,%%ecx)\n\t"
- "test %%ecx,%%ecx\n\t"
- "jz " LF(1) "\n\t"
-
- "movb 3(%0),%%cl\n\t"
- "addl $4,%0\n\t" /* add loop increment */
- "movb %%cl,-256(%%esp,%%ecx)\n\t"
- "test %%ecx,%%ecx\n\t"
- "jnz " LB(2) "\n"
-
- /* At this point all characters not in the skipset are not marked
- * in the table. Especially the NULL character is not marked
- * altough The last move before the end of the loop wrote a NULL
- * in the table. But this NULL is the stop character.
- */
-
- /* We use two asm statements because we don't want to do the
- * argument in the asm code. In the first part we need the stopset
- * and in the second the string. By this splitting we don't need
- * another register.
- */
-
- /* If you cannot guess what this is for look through the resulting
- * code. The dumb version has an .align at the beginning of the
- * following asm statement. This is quite long. If we could
- * make the jump to the label '1' behind the NOPs we would save
- * the time in 75% of the cases. Exactly this is done here.
- * If anything in the prepending code changes the number of NOPs
- * may have to change, too.
- */
-
- #if (!defined(__i486__) && !defined(__i586__)) || \
- defined(I_DONT_KNOW_WHAT_THIS_MEANS)
- LL(1)
- : :"d" (skipset):"ax");
-
- __asm__(ALIGN "\n"
- #else
- "\tnop; nop\n"
- LL(1)
- : :"d" (skipset):"ax");
-
- __asm__(
- #endif
- /* At this point of the execution %eax contains the value -4
- * (see above).
- */
-
- /* We use the base+index adressing mode because by this mean we only
- * have to increment one counter in the loop which can also serve
- * as the string length counter which is the result.
- */
-
- LL(3) "\taddl $4,%0\n\t" /* add loop increment */
-
- "movb (%1,%0),%%cl\n\t" /* get current string character */
- "testb $0xff,-256(%%esp,%%ecx)\n\t" /* is char set in table ? */
- "jz " LF(4) "\n\t" /* no, than exit */
-
- "movb 1(%1,%0),%%cl\n\t"
- "testb $0xff,-256(%%esp,%%ecx)\n\t"
- "jz " LF(5) "\n\t"
-
- "movb 2(%1,%0),%%cl\n\t"
- "testb $0xff,-256(%%esp,%%ecx)\n\t"
- "jz " LF(6) "\n\t"
-
- "movb 3(%1,%0),%%cl\n\t"
- "testb $0xff,-256(%%esp,%%ecx)\n\t"
- "jnz " LB(3) "\n\t"
-
- "incl %0\n" /* correct result length counter */
- LL(6) "\tincl %0\n"
- LL(5) "\tincl %0\n"
- LL(4)
- :"=a" (__res):"d" (str):"cx");
- return __res;
- }
-