[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>
This commit is contained in:
Michael Brown
2012-11-04 22:43:59 +00:00
parent 7cbac68593
commit fc30b13b25
2 changed files with 74 additions and 24 deletions

View File

@@ -35,7 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
* @v len Length * @v len Length
* @ret dest Destination address * @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; void *edi = dest;
const void *esi = src; const void *esi = src;
int discard_ecx; int discard_ecx;
@@ -56,3 +57,50 @@ void * __memcpy ( void *dest, const void *src, size_t len ) {
: "memory" ); : "memory" );
return dest; 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 );
}
}

View File

@@ -26,6 +26,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN );
#define __HAVE_ARCH_MEMCPY #define __HAVE_ARCH_MEMCPY
extern void * __memcpy ( void *dest, const void *src, size_t len ); 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 * static inline __attribute__ (( always_inline )) void *
__constant_memcpy ( void *dest, const void *src, size_t len ) { __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) ) ) __memcpy ( (dest), (src), (len) ) )
#define __HAVE_ARCH_MEMMOVE #define __HAVE_ARCH_MEMMOVE
static inline void * memmove(void * dest,const void * src, size_t n)
{ extern void * __memmove ( void *dest, const void *src, size_t len );
int d0, d1, d2;
if (dest<src) /**
__asm__ __volatile__( * Copy (possibly overlapping) memory area
"cld\n\t" *
"rep\n\t" * @v dest Destination address
"movsb" * @v src Source address
: "=&c" (d0), "=&S" (d1), "=&D" (d2) * @v len Length
:"0" (n),"1" (src),"2" (dest) * @ret dest Destination address
: "memory"); */
else static inline __attribute__ (( always_inline )) void *
__asm__ __volatile__( memmove ( void *dest, const void *src, size_t len ) {
"std\n\t" ssize_t offset = ( dest - src );
"rep\n\t"
"movsb\n\t" if ( __builtin_constant_p ( offset ) ) {
"cld" if ( offset <= 0 ) {
: "=&c" (d0), "=&S" (d1), "=&D" (d2) return memcpy ( dest, src, len );
:"0" (n), } else {
"1" (n-1+(const char *)src), return __memcpy_reverse ( dest, src, len );
"2" (n-1+(char *)dest) }
:"memory"); } else {
return dest; return __memmove ( dest, src, len );
}
} }
#define __HAVE_ARCH_MEMSET #define __HAVE_ARCH_MEMSET