summaryrefslogtreecommitdiffstats
path: root/src/arch/x86/core
diff options
context:
space:
mode:
authorMichael Brown2012-11-05 00:53:59 +0100
committerMichael Brown2012-11-12 17:58:49 +0100
commit06766875ada566a95ff22aef2d6c7fadec4da4b8 (patch)
tree823062d8fe48fe723074882ae6668280d6e49086 /src/arch/x86/core
parent[libc] Remove unnecessary "cld" instruction from memset() (diff)
downloadipxe-06766875ada566a95ff22aef2d6c7fadec4da4b8.tar.gz
ipxe-06766875ada566a95ff22aef2d6c7fadec4da4b8.tar.xz
ipxe-06766875ada566a95ff22aef2d6c7fadec4da4b8.zip
[libc] Reduce overall code size by externalising strncmp()
Typical saving is 20-30 bytes in each file using strncmp(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/x86/core')
-rw-r--r--src/arch/x86/core/x86_string.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c
index 59e0eaae1..962a7d84d 100644
--- a/src/arch/x86/core/x86_string.c
+++ b/src/arch/x86/core/x86_string.c
@@ -104,3 +104,41 @@ void * __memmove ( void *dest, const void *src, size_t len ) {
return __memcpy_reverse ( dest, src, len );
}
}
+
+/**
+ * Compare strings (up to a specified length)
+ *
+ * @v str1 First string
+ * @v str2 Second string
+ * @v len Maximum length
+ * @ret diff Difference
+ */
+int strncmp ( const char *str1, const char *str2, size_t len ) {
+ const void *discard_S;
+ const void *discard_D;
+ size_t discard_c;
+ int diff;
+
+ __asm__ __volatile__ ( "\n1:\n\t"
+ "dec %2\n\t"
+ "js 2f\n\t"
+ "lodsb\n\t"
+ "scasb\n\t"
+ "jne 3f\n\t"
+ "testb %b3, %b3\n\t"
+ "jnz 1b\n\t"
+ /* Equal */
+ "\n2:\n\t"
+ "xor %3, %3\n\t"
+ "jmp 4f\n\t"
+ /* Not equal; CF indicates difference */
+ "\n3:\n\t"
+ "sbb %3, %3\n\t"
+ "orb $1, %b3\n\t"
+ "\n4:\n\t"
+ : "=&S" ( discard_S ), "=&D" ( discard_D ),
+ "=&c" ( discard_c ), "=&a" ( diff )
+ : "0" ( str1 ), "1" ( str2 ), "2" ( len ) );
+
+ return diff;
+}