mirror of
https://github.com/ipxe/ipxe
synced 2025-12-27 10:02:42 +03:00
[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:
@@ -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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user