#include #include namespace { // Needed since we cannot declare a templated enum. template struct word_helper { using underlying [[gnu::aligned(1)]] = T; enum class [[gnu::may_alias]] word_enum : underlying { }; }; template using word = typename word_helper::word_enum; template [[gnu::always_inline]] inline word alias_load(const unsigned char *&p) { word value = *reinterpret_cast *>(p); p += sizeof(T); return value; } template [[gnu::always_inline]] inline void alias_store(unsigned char *&p, word value) { *reinterpret_cast *>(p) = value; p += sizeof(T); } #ifdef __LP64__ void *forward_copy(void *__restrict dest, const void *__restrict src, size_t n) { auto curDest = reinterpret_cast(dest); auto curSrc = reinterpret_cast(src); while(n >= 8 * 8) { auto w1 = alias_load(curSrc); auto w2 = alias_load(curSrc); auto w3 = alias_load(curSrc); auto w4 = alias_load(curSrc); auto w5 = alias_load(curSrc); auto w6 = alias_load(curSrc); auto w7 = alias_load(curSrc); auto w8 = alias_load(curSrc); alias_store(curDest, w1); alias_store(curDest, w2); alias_store(curDest, w3); alias_store(curDest, w4); alias_store(curDest, w5); alias_store(curDest, w6); alias_store(curDest, w7); alias_store(curDest, w8); n -= 8 * 8; } if(n >= 4 * 8) { auto w1 = alias_load(curSrc); auto w2 = alias_load(curSrc); auto w3 = alias_load(curSrc); auto w4 = alias_load(curSrc); alias_store(curDest, w1); alias_store(curDest, w2); alias_store(curDest, w3); alias_store(curDest, w4); n -= 4 * 8; } if(n >= 2 * 8) { auto w1 = alias_load(curSrc); auto w2 = alias_load(curSrc); alias_store(curDest, w1); alias_store(curDest, w2); n -= 2 * 8; } if(n >= 8) { auto w = alias_load(curSrc); alias_store(curDest, w); n -= 8; } if(n >= 4) { auto w = alias_load(curSrc); alias_store(curDest, w); n -= 4; } if(n >= 2) { auto w = alias_load(curSrc); alias_store(curDest, w); n -= 2; } if(n) *curDest = *curSrc; return dest; } #else // !__LP64__ void *forward_copy(void *dest, const void *src, size_t n) { for(size_t i = 0; i < n; i++) ((char *)dest)[i] = ((const char *)src)[i]; return dest; } #endif // __LP64__ / !__LP64__ } // -------------------------------------------------------------------------------------- // memcpy() implementation. // -------------------------------------------------------------------------------------- void *memcpy(void *__restrict dest, const void *__restrict src, size_t n) { return forward_copy(dest, src, n); } // -------------------------------------------------------------------------------------- // memset() implementation. // -------------------------------------------------------------------------------------- #ifdef __LP64__ void *memset(void *dest, int val, size_t n) { auto curDest = reinterpret_cast(dest); unsigned char byte = val; // Get rid of misalignment. while(n && (reinterpret_cast(curDest) & 7)) { *curDest++ = byte; --n; } auto pattern64 = static_cast>( static_cast(byte) | (static_cast(byte) << 8) | (static_cast(byte) << 16) | (static_cast(byte) << 24) | (static_cast(byte) << 32) | (static_cast(byte) << 40) | (static_cast(byte) << 48) | (static_cast(byte) << 56)); auto pattern32 = static_cast>( static_cast(byte) | (static_cast(byte) << 8) | (static_cast(byte) << 16) | (static_cast(byte) << 24)); auto pattern16 = static_cast>( static_cast(byte) | (static_cast(byte) << 8)); while(n >= 8 * 8) { alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); n -= 8 * 8; } if(n >= 4 * 8) { alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); alias_store(curDest, pattern64); n -= 4 * 8; } if(n >= 2 * 8) { alias_store(curDest, pattern64); alias_store(curDest, pattern64); n -= 2 * 8; } if(n >= 8) { alias_store(curDest, pattern64); n -= 8; } if(n >= 4) { alias_store(curDest, pattern32); n -= 4; } if(n >= 2) { alias_store(curDest, pattern16); n -= 2; } if(n) *curDest = byte; return dest; } #else // !__LP64__ void *memset(void *dest, int byte, size_t count) { for(size_t i = 0; i < count; i++) ((char *)dest)[i] = (char)byte; return dest; } #endif // __LP64__ / !__LP64__ // -------------------------------------------------------------------------------------- // "Non-optimized" functions. // -------------------------------------------------------------------------------------- void *memmove(void *dest, const void *src, size_t size) { char *dest_bytes = (char *)dest; char *src_bytes = (char *)src; if(dest_bytes < src_bytes) { return forward_copy(dest, src, size); }else if(dest_bytes > src_bytes) { for(size_t i = 0; i < size; i++) dest_bytes[size - i - 1] = src_bytes[size - i - 1]; } return dest; } size_t strlen(const char *s) { size_t len = 0; for(size_t i = 0; s[i]; i++) len++; return len; }