138 lines
3.9 KiB
C++
138 lines
3.9 KiB
C++
#include <errno.h>
|
|
#include <luna.h>
|
|
#include <string.h>
|
|
|
|
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<char*>(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
|
|
} |