diff options
author | Michael Brown <mcb30@ipxe.org> | 2012-11-04 22:43:59 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2012-11-12 16:58:49 +0000 |
commit | fc30b13b25d66c711778fee50ce2d5609ad361ee (patch) | |
tree | fb5c741523d1d79cc122f7bb864a5a02edef7605 | |
parent | 7cbac6859327296fba1c873d1f589fa90c1b9d91 (diff) | |
download | ipxe-fc30b13b25d66c711778fee50ce2d5609ad361ee.tar.gz |
[libc] Reduce overall code size by externalising memmove()
Typical saving is 15-20 bytes in each file using memmove().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/arch/x86/core/x86_string.c | 50 | ||||
-rw-r--r-- | src/arch/x86/include/bits/string.h | 48 |
2 files changed, 74 insertions, 24 deletions
diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 698dbe2e..59e0eaae 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -35,7 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @v len Length * @ret dest Destination address */ -void * __memcpy ( void *dest, const void *src, size_t len ) { +void * __attribute__ (( noinline )) __memcpy ( void *dest, const void *src, + size_t len ) { void *edi = dest; const void *esi = src; int discard_ecx; @@ -56,3 +57,50 @@ void * __memcpy ( void *dest, const void *src, size_t len ) { : "memory" ); return dest; } + +/** + * Copy memory area backwards + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * __attribute__ (( noinline )) __memcpy_reverse ( void *dest, + const void *src, + size_t len ) { + void *edi = ( dest + len - 1 ); + const void *esi = ( src + len - 1 ); + int discard_ecx; + + /* Assume memmove() is not performance-critical, and perform a + * bytewise copy for simplicity. + */ + __asm__ __volatile__ ( "std\n\t" + "rep movsb\n\t" + "cld\n\t" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), + "2" ( len ) + : "memory" ); + return dest; +} + + +/** + * Copy (possibly overlapping) memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * __memmove ( void *dest, const void *src, size_t len ) { + + if ( dest <= src ) { + return __memcpy ( dest, src, len ); + } else { + return __memcpy_reverse ( dest, src, len ); + } +} diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index d9ebe306..e5850ed9 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -26,6 +26,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); #define __HAVE_ARCH_MEMCPY extern void * __memcpy ( void *dest, const void *src, size_t len ); +extern void * __memcpy_reverse ( void *dest, const void *src, size_t len ); static inline __attribute__ (( always_inline )) void * __constant_memcpy ( void *dest, const void *src, size_t len ) { @@ -144,29 +145,30 @@ __constant_memcpy ( void *dest, const void *src, size_t len ) { __memcpy ( (dest), (src), (len) ) ) #define __HAVE_ARCH_MEMMOVE -static inline void * memmove(void * dest,const void * src, size_t n) -{ -int d0, d1, d2; -if (dest<src) -__asm__ __volatile__( - "cld\n\t" - "rep\n\t" - "movsb" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (n),"1" (src),"2" (dest) - : "memory"); -else -__asm__ __volatile__( - "std\n\t" - "rep\n\t" - "movsb\n\t" - "cld" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (n), - "1" (n-1+(const char *)src), - "2" (n-1+(char *)dest) - :"memory"); -return dest; + +extern void * __memmove ( void *dest, const void *src, size_t len ); + +/** + * Copy (possibly overlapping) memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +static inline __attribute__ (( always_inline )) void * +memmove ( void *dest, const void *src, size_t len ) { + ssize_t offset = ( dest - src ); + + if ( __builtin_constant_p ( offset ) ) { + if ( offset <= 0 ) { + return memcpy ( dest, src, len ); + } else { + return __memcpy_reverse ( dest, src, len ); + } + } else { + return __memmove ( dest, src, len ); + } } #define __HAVE_ARCH_MEMSET |