summaryrefslogtreecommitdiff
path: root/arch/x86/machine/string.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2014-05-24 15:13:06 +0200
committerRichard Braun <rbraun@sceen.net>2014-05-24 15:13:06 +0200
commit7f40de6a91acfaa1451764a15b56a3ddfd4569eb (patch)
treec8374189f5ae0fb13be550c3aea84ce098a008dd /arch/x86/machine/string.c
parent532f247e4ecc6a101ae2b5c0acb83fa02380d779 (diff)
x86/string: add optimized versions of strlen, strcpy and strcmp
Diffstat (limited to 'arch/x86/machine/string.c')
-rw-r--r--arch/x86/machine/string.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/arch/x86/machine/string.c b/arch/x86/machine/string.c
index 2ea8392..3f347d0 100644
--- a/arch/x86/machine/string.c
+++ b/arch/x86/machine/string.c
@@ -85,3 +85,54 @@ memcmp(const void *s1, const void *s2, size_t n)
return (int)c1 - (int)c2;
}
#endif /* ARCH_STRING_MEMCMP */
+
+#ifdef ARCH_STRING_STRLEN
+size_t
+strlen(const char *s)
+{
+ size_t n;
+
+ n = (size_t)-1;
+ asm volatile("cld; repne scasb" : "+D" (s), "+c" (n) : "a" (0));
+ return ~n - 1;
+}
+#endif /* ARCH_STRING_STRLEN */
+
+#ifdef ARCH_STRING_STRCPY
+char *
+strcpy(char *dest, const char *src)
+{
+ char *orig_dest;
+
+ orig_dest = dest;
+ asm volatile("cld\n"
+ "1:\n"
+ "lodsb\n"
+ "stosb\n"
+ "testb %%al, %%al\n"
+ "jnz 1b\n"
+ : "+D" (dest), "+S" (src) : : "al");
+ return orig_dest;
+}
+#endif /* ARCH_STRING_STRCPY */
+
+#ifdef ARCH_STRING_STRCMP
+int
+strcmp(const char *s1, const char *s2)
+{
+ unsigned char c1, c2;
+
+ asm volatile("cld\n"
+ "1:\n"
+ "lodsb\n"
+ "scasb\n"
+ "jne 1f\n"
+ "testb %%al, %%al\n"
+ "jnz 1b\n"
+ "1:\n"
+ : "+D" (s1), "+S" (s2) : : "al");
+ c1 = *(((const unsigned char *)s1) - 1);
+ c2 = *(((const unsigned char *)s2) - 1);
+ return (int)c1 - (int)c2;
+}
+#endif /* ARCH_STRING_STRCMP */