#include #include #include extern "C" { void* memcpy(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; } void* memset(void* buf, int c, size_t n) { for (size_t i = 0; i < n; ++i) { *((char*)buf + i) = (char)c; } return buf; } size_t strlen(const char* str) { const char* i = str; for (; *i; ++i) ; return (i - str); } char* strcpy(char* dest, const char* src) { memcpy(dest, src, strlen(src) + 1); return dest; } char* strncpy(char* dest, const char* src, size_t max) // FIXME: Implement strncpy according to the specification. { size_t src_len = strlen(src) + 1; // NULL byte memcpy(dest, src, src_len > max ? max : src_len); return dest; } char* strcat(char* dest, const char* src) { size_t dest_len = strlen(dest); size_t i; for (i = 0; *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i); *(char*)(dest + dest_len + i) = '\0'; return dest; } char* strncat(char* dest, const char* src, size_t max) { size_t dest_len = strlen(dest); size_t i; for (i = 0; i < max && *(src + i); i++) *(char*)(dest + dest_len + i) = *(const char*)(src + i); *(char*)(dest + dest_len + i) = '\0'; return dest; } char* strchr(const char* str, int c) { while (*str && *str != (char)c) str++; if (*str) return const_cast(str); return NULL; } void* memclr(void* buf, size_t n) { // "i" is our counter of how many bytes we've cleared size_t i; // find out if "m_start" is aligned on a SSE_XMM_SIZE boundary if ((size_t)buf & (15)) { i = 0; // we need to clear byte-by-byte until "m_start" is aligned on an SSE_XMM_SIZE boundary // ... and lets make sure we don't copy 'too' many bytes (i < m_count) while (((size_t)buf + i) & (15) && i < n) { asm("stosb;" ::"D"((size_t)buf + i), "a"(0)); i++; } } else { // if "m_start" was aligned, set our count to 0 i = 0; } // clear 64-byte chunks of memory (4 16-byte operations) for (; i + 64 <= n; i += 64) { asm volatile(" pxor %%xmm0, %%xmm0; " // set XMM0 to 0 " movdqa %%xmm0, 0(%0); " // move 16 bytes from XMM0 to %0 + 0 " movdqa %%xmm0, 16(%0); " " movdqa %%xmm0, 32(%0); " " movdqa %%xmm0, 48(%0); " ::"r"((size_t)buf + i)); } // copy the remaining bytes (if any) asm(" rep stosb; " ::"a"((size_t)(0)), "D"(((size_t)buf) + i), "c"(n - i)); // "i" will contain the total amount of bytes that were actually transfered i += n - i; // we return "m_start" + the amount of bytes that were transfered return (void*)(((size_t)buf) + i); } #pragma GCC push_options #pragma GCC diagnostic ignored "-Wwrite-strings" char* strerror(int err) { switch (err) { case EPERM: return "Operation not permitted"; case EINVAL: return "Invalid argument"; case ENOMEM: return "Cannot allocate memory"; case ENOSYS: return "Function not implemented"; case ENOENT: return "No such file or directory"; case EBADF: return "Bad file descriptor"; case EMFILE: return "Too many open files"; case EISDIR: return "Is a directory"; case ENOEXEC: return "Exec format error"; case EFAULT: return "Bad address"; case 0: return "Success"; default: return (char*)(unsigned long int)err; } } #pragma GCC pop_options }