From 6c106c856412c027ff78a9661386b3a42a52cf36 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 19 Dec 2008 13:51:38 +0000 Subject: strncat: shorter version for i386, add small embedded test memchr: add small embedded test strnlen: make small embedded test easier to use strncmp: reformat assembly to make it readable, no code changes (verified with objdump) text data bss dec hex filename - 46 0 0 46 2e libc/string/i386/strncat.os + 39 0 0 39 27 libc/string/i386/strncat.os --- libc/string/i386/memchr.c | 21 +++++++++++++ libc/string/i386/strncat.c | 73 +++++++++++++++++++++++++++++++--------------- libc/string/i386/strncmp.c | 41 +++++++++++++------------- libc/string/i386/strnlen.c | 26 ++++++++++------- 4 files changed, 106 insertions(+), 55 deletions(-) (limited to 'libc/string') diff --git a/libc/string/i386/memchr.c b/libc/string/i386/memchr.c index bff0538d7..772251cee 100644 --- a/libc/string/i386/memchr.c +++ b/libc/string/i386/memchr.c @@ -33,6 +33,7 @@ #include #undef memchr +//#define memchr TESTING void *memchr(const void *s, int c, size_t count) { void *edi; @@ -51,4 +52,24 @@ void *memchr(const void *s, int c, size_t count) ); return edi; } +#ifndef memchr libc_hidden_def(memchr) +#else +/* Uncomment TESTING, gcc -D__USE_GNU -m32 -Os memchr.c -o memchr + * and run ./memchr + */ +int main() +{ + static const char str[] = "abc.def"; + printf((char*)memchr(str, '.',-2) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.',-1) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 0) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 1) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 2) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 3) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 4) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 5) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str+3, '.', 0) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str+3, '.', 5) - str == 3 ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/libc/string/i386/strncat.c b/libc/string/i386/strncat.c index 3872679d5..640b0d213 100644 --- a/libc/string/i386/strncat.c +++ b/libc/string/i386/strncat.c @@ -32,30 +32,55 @@ #include -/* Experimentally off - libc_hidden_proto(strncat) */ -char *strncat(char * dest, - const char * src, size_t count) +#undef strncat +//#define strncat TESTING +char *strncat(char * dest, const char * src, size_t count) { - int d0, d1, d2, d3; - __asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "decl %1\n\t" - "movl %8,%3\n" - "incl %3\n" - "1:\tdecl %3\n\t" - "jz 2f\n" - "lodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "jmp 3f\n" - "2:\txorl %2,%2\n\t" - "stosb\n" - "3:" - : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) - : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) - : "memory"); - return dest; + int esi, edi, eax, ecx, edx; + __asm__ __volatile__( + " xorl %%eax, %%eax\n" + " incl %%edx\n" + " pushl %%edi\n" /* save dest */ + " repne; scasb\n" + " decl %%edi\n" /* edi => NUL in dest */ + /* count-- */ + "1: decl %%edx\n" + /* if count reached 0, store NUL and bail out */ + " movl %%edx, %%eax\n" + " jz 2f\n" + /* else copy a char */ + " lodsb\n" + "2: stosb\n" + " testb %%al, %%al\n" + " jnz 1b\n" + /* end of loop */ + " popl %%eax\n" /* restore dest into eax */ + : "=&S" (esi), "=&D" (edi), "=&a" (eax), "=&c" (ecx), "=&d" (edx) + : "0" (src), "1" (dest), "3" (0xffffffff), "4" (count) + : "memory" + ); + return (char *)eax; } +#ifndef strncat libc_hidden_def(strncat) +#else +/* Uncomment TESTING, gcc -m32 -Os strncat.c -o strncat + * and run ./strncat + */ +int main() +{ + char buf[99]; + + strcpy(buf, "abc"); buf[4] = '*'; strncat(buf, "def", 0); + printf(strcmp(buf, "abc") == 0 && buf[4] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", 50); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", -1); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def123", 3); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/libc/string/i386/strncmp.c b/libc/string/i386/strncmp.c index a14bb503b..bfb20c307 100644 --- a/libc/string/i386/strncmp.c +++ b/libc/string/i386/strncmp.c @@ -32,27 +32,28 @@ #include -/* Experimentally off - libc_hidden_proto(strncmp) */ +#undef strncmp int strncmp(const char *cs, const char *ct, size_t count) { - register int __res; - int d0, d1, d2; - __asm__ __volatile__( - "incl %3\n" - "1:\tdecl %3\n\t" - "jz 2f\n" - "lodsb\n\t" - "scasb\n\t" - "jne 3f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "2:\txorl %%eax,%%eax\n\t" - "jmp 4f\n" - "3:\tsbbl %%eax,%%eax\n\t" - "orb $1,%%al\n" - "4:" - :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) - :"1" (cs),"2" (ct),"3" (count)); - return __res; + int eax; + int esi, edi, ecx; + __asm__ __volatile__( + " incl %%ecx\n" + "1: decl %%ecx\n" + " jz 2f\n" + " lodsb\n" + " scasb\n" + " jne 3f\n" + " testb %%al, %%al\n" + " jnz 1b\n" + "2: xorl %%eax, %%eax\n" + " jmp 4f\n" + "3: sbbl %%eax, %%eax\n" + " orb $1, %%al\n" + "4:\n" + : "=a" (eax), "=&S" (esi), "=&D" (edi), "=&c" (ecx) + : "1" (cs), "2" (ct), "3" (count) + ); + return eax; } libc_hidden_weak(strncmp) diff --git a/libc/string/i386/strnlen.c b/libc/string/i386/strnlen.c index 066a11ef7..d9bce6485 100644 --- a/libc/string/i386/strnlen.c +++ b/libc/string/i386/strnlen.c @@ -34,6 +34,8 @@ #ifdef __USE_GNU +#undef strnlen +//#define strnlen TESTING size_t strnlen(const char *s, size_t count) { int edx; @@ -51,20 +53,22 @@ size_t strnlen(const char *s, size_t count) ); return eax; } +#ifndef strnlen libc_hidden_def(strnlen) - -#if 0 +#else +/* Uncomment TESTING, gcc -D__USE_GNU -m32 -Os strnlen.c -o strnlen + * and run ./strnlen + */ int main() { - printf(strnlen2("abc\0def", -2) == 3 ? "ok\n" : "BAD!\n"); - printf(strnlen2("abc\0def", -1) == 3 ? "ok\n" : "BAD!\n"); - printf(strnlen2("abc\0def", 0) == 0 ? "ok\n" : "BAD!\n"); - printf(strnlen2("abc\0def", 1) == 1 ? "ok\n" : "BAD!\n"); - printf(strnlen2("abc\0def", 2) == 2 ? "ok\n" : "BAD!\n"); - printf(strnlen2("abc\0def", 3) == 3 ? "ok\n" : "BAD!\n"); - printf(strnlen2("abc\0def", 4) == 3 ? "ok\n" : "BAD!\n"); - printf(strnlen2("abc\0def", 5) == 3 ? "ok\n" : "BAD!\n"); - return 0; + printf(strnlen("abc\0def", -2) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", -1) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 0) == 0 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 1) == 1 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 2) == 2 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 3) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 4) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 5) == 3 ? "ok\n" : "BAD!\n"); } #endif -- cgit v1.2.3