summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-12-19 13:51:38 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-12-19 13:51:38 +0000
commit6c106c856412c027ff78a9661386b3a42a52cf36 (patch)
tree7ad4c7fbe228eca31768ba355ebf0d933a406cfe
parent6232f9122d61ee11edca902d95e04144f9c5b3c1 (diff)
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
-rw-r--r--libc/string/i386/memchr.c21
-rw-r--r--libc/string/i386/strncat.c73
-rw-r--r--libc/string/i386/strncmp.c41
-rw-r--r--libc/string/i386/strnlen.c26
4 files changed, 106 insertions, 55 deletions
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 <string.h>
#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 <string.h>
-/* 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 <string.h>
-/* 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