#ifndef BITS_STRING_H #define BITS_STRING_H FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * * String functions * */ extern void arm64_bzero ( void *dest, size_t len ); extern void arm64_memset ( void *dest, size_t len, int character ); extern void arm64_memcpy ( void *dest, const void *src, size_t len ); extern void arm64_memmove_forwards ( void *dest, const void *src, size_t len ); extern void arm64_memmove_backwards ( void *dest, const void *src, size_t len ); extern void arm64_memmove ( void *dest, const void *src, size_t len ); /** * Fill memory region * * @v dest Destination region * @v character Fill character * @v len Length * @ret dest Destination region */ static inline __attribute__ (( always_inline )) void * memset ( void *dest, int character, size_t len ) { /* Allow gcc to generate inline "stX xzr" instructions for * small, constant lengths. */ if ( __builtin_constant_p ( character ) && ( character == 0 ) && __builtin_constant_p ( len ) && ( len <= 64 ) ) { __builtin_memset ( dest, 0, len ); return dest; } /* For zeroing larger or non-constant lengths, use the * optimised variable-length zeroing code. */ if ( __builtin_constant_p ( character ) && ( character == 0 ) ) { arm64_bzero ( dest, len ); return dest; } /* Not necessarily zeroing: use basic variable-length code */ arm64_memset ( dest, len, character ); return dest; } /** * Copy memory region * * @v dest Destination region * @v src Source region * @v len Length * @ret dest Destination region */ static inline __attribute__ (( always_inline )) void * memcpy ( void *dest, const void *src, size_t len ) { /* Allow gcc to generate inline "ldX"/"stX" instructions for * small, constant lengths. */ if ( __builtin_constant_p ( len ) && ( len <= 64 ) ) { __builtin_memcpy ( dest, src, len ); return dest; } /* Otherwise, use variable-length code */ arm64_memcpy ( dest, src, len ); return dest; } /** * Copy (possibly overlapping) memory region * * @v dest Destination region * @v src Source region * @v len Length * @ret dest Destination region */ static inline __attribute__ (( always_inline )) void * memmove ( void *dest, const void *src, size_t len ) { ssize_t offset = ( dest - src ); /* If required direction of copy is known at build time, then * use the appropriate forwards/backwards copy directly. */ if ( __builtin_constant_p ( offset ) ) { if ( offset <= 0 ) { arm64_memmove_forwards ( dest, src, len ); return dest; } else { arm64_memmove_backwards ( dest, src, len ); return dest; } } /* Otherwise, use ambidirectional copy */ arm64_memmove ( dest, src, len ); return dest; } #endif /* BITS_STRING_H */