Squash commits for public release

This commit is contained in:
2025-02-12 09:54:05 -05:00
commit 7118adc514
1108 changed files with 80873 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
// Target ARMv7
.global memset
// r0 - dest
// r1 - ch
// r2 - len
memset:
mov r3, r0
cmp r2, #0
beq memset_exit
tst r3, #3 // Will set N
beq memset_4bytes_aligned_entry
memset_byte:
subs r2, r2, #1
strb r1, [r3], #1
cmp r2, #0
beq memset_exit
tst r3, #3
bne memset_byte
memset_4bytes_aligned_entry:
cmp r2, #4
blt memset_byte_2
and r1, #0xFF
orr r1, r1, r1, lsl#8
orr r1, r1, r1, lsl#16
tst r3, #15
beq memset_16bytes_aligned_entry
memset_4bytes_aligned_loop:
subs r2, r2, #4
str r1, [r3], #4
cmp r2, #0
beq memset_exit
cmp r2, #4
blt memset_byte_2
tst r3, #15 // Test if we can put 16bytes block.
bne memset_4bytes_aligned_loop // If not repeat 4 byte block again.
memset_16bytes_aligned_entry:
push {r5, r6, r7}
cmp r2, #16
blt memset_16bytes_aligned_exit
memset_16bytes_aligned_preloop:
// Load ch into all bytes of 32bit r1 register
mov r5, r1
mov r6, r1
mov r7, r1
memset_16bytes_aligned_loop:
subs r2, r2, #16
stmia r3!,{r1,r5,r6,r7}
cmp r2, #16
bge memset_16bytes_aligned_loop
memset_16bytes_aligned_exit:
pop {r5, r6, r7}
cmp r2, #0
beq memset_exit
memset_4bytes_aligned_entry_2:
cmp r2, #4
blt memset_byte_2
memset_4bytes_aligned_loop_2:
subs r2, r2, #4
str r1, [r3], #4
cmp r2, #0
beq memset_exit
cmp r2, #4
bge memset_4bytes_aligned_loop_2
memset_byte_2:
subs r2, r2, #1
strb r1, [r3], #1
bne memset_byte_2
memset_exit:
bx lr

277
libs/libc/string/string.c Normal file
View File

@@ -0,0 +1,277 @@
#include <stdbool.h>
#include <string.h>
#ifndef __arm__
void* memset(void* dest, int fill, size_t nbytes)
{
for (int i = 0; i < nbytes; ++i)
((uint8_t*)dest)[i] = fill;
return dest;
}
#endif //__arm__
void* memmove(void* dest, const void* src, size_t nbytes)
{
if (src > dest) {
memcpy(dest, src, nbytes);
return dest;
}
for (int i = nbytes - 1; i >= 0; --i)
((uint8_t*)dest)[i] = ((uint8_t*)src)[i];
return dest;
}
/* This optimized version of memcpy uses 32 bit chunks to copy over data on
the 32 bit architecture this library is built for. If this function gets
used on a 64 bit arch, be sure to use 8 byte chunks so each chunk fits
in a single register. The important part is this should be compiled with
atleast -O1 or -Os, because -O0 just makes this function too big for what
it does.
GCC does a better job at optimizing this if the pointers are restricted,
making the copying part have less instructions. Clang on the other hand
does not really change anything if the pointers are restricted or not. */
void* memcpy(void* __restrict dest, const void* __restrict src, size_t nbytes)
{
size_t chunks, rest, i;
rest = nbytes % 4;
chunks = (nbytes - rest) >> 2;
if (!chunks)
goto skip_chunks;
for (i = 0; i < chunks; i++)
((uint32_t*)dest)[i] = ((uint32_t*)src)[i];
skip_chunks:
/* Multiplying chunks by 4 will give us the offset of the 'rest' bytes,
which were not copied over along with the 4 byte chunks. */
chunks <<= 2;
for (i = 0; i < rest; i++)
((uint8_t*)dest)[chunks + i] = ((uint8_t*)src)[chunks + i];
return dest;
}
void* memccpy(void* dest, const void* src, int stop, size_t nbytes)
{
for (int i = 0; i < nbytes; i++) {
*((uint8_t*)dest + i) = *((uint8_t*)src + i);
if (*((uint8_t*)src + i) == stop)
return ((uint8_t*)dest + i + 1);
}
return NULL;
}
int memcmp(const void* src1, const void* src2, size_t nbytes)
{
const uint8_t* first = src1;
const uint8_t* second = src2;
for (int i = 0; i < nbytes; i++) {
/* Return the difference if the byte does not match. */
if (first[i] != second[i])
return (int)first[i] - (int)second[i];
}
return 0;
}
void* memchr(const void* ptr, int c, size_t size)
{
char ch = c;
const char* cptr = (const char*)ptr;
for (size_t i = 0; i < size; i++) {
if (cptr[i] == ch) {
return (char*)(cptr + i);
}
}
return NULL;
}
int strcmp(const char* a, const char* b)
{
while (*a == *b && *a != '\0' && *b != '\0') {
a++;
b++;
}
if (*a < *b) {
return -1;
}
if (*a > *b) {
return 1;
}
return 0;
}
int strncmp(const char* a, const char* b, size_t num)
{
while (*a == *b && *a != 0 && *b != 0 && num) {
a++;
b++;
num--;
}
if (!num) {
return 0;
}
if (*a < *b) {
return -1;
}
if (*a > *b) {
return 1;
}
return 0;
}
size_t strlen(const char* str)
{
size_t i = 0;
while (str[i])
++i;
return i;
}
char* strcpy(char* dest, const char* src)
{
size_t i;
for (i = 0; src[i] != 0; i++)
dest[i] = src[i];
dest[i] = '\0';
return dest;
}
char* strncpy(char* dest, const char* src, size_t nbytes)
{
size_t i;
for (i = 0; i < nbytes && src[i] != 0; i++)
dest[i] = src[i];
/* Fill the rest with null bytes */
for (; i < nbytes; i++)
dest[i] = 0;
return dest;
}
char* strchr(const char* s, int c)
{
for (;; s++) {
if (*s == c) {
return (char*)s;
}
if (!(*s)) {
return NULL;
}
}
}
char* strtok_r(char* str, const char* delim, char** saveptr)
{
if (!str) {
if (!saveptr) {
return NULL;
}
str = *saveptr;
}
size_t start = 0;
size_t end = 0;
size_t n = strlen(str);
size_t m = strlen(delim);
bool ok = false;
for (size_t i = 0; i < n; i++) {
ok = false;
for (size_t j = 0; j < m; j++) {
if (str[i] == delim[j]) {
if (end - start == 0) {
start++;
break;
}
ok = true;
}
}
if (ok) {
break;
}
end++;
}
if (str[start] == '\0') {
return NULL;
}
if (end == 0) {
*saveptr = NULL;
return &str[start];
}
if (str[end] == '\0') {
*saveptr = &str[end];
} else {
*saveptr = &str[end + 1];
}
str[end] = '\0';
return &str[start];
}
char* strtok(char* str, const char* delim)
{
static char* saveptr;
return strtok_r(str, delim, &saveptr);
}
char* strstr(const char* haystack, const char* needle)
{
size_t n = strlen(needle);
while (*haystack) {
if (!memcmp(haystack, needle, n)) {
return (char*)haystack;
}
haystack++;
}
return NULL;
}
char* strcat(char* dest, const char* src)
{
size_t dest_len = strlen(dest);
size_t i = 0;
while (src[i] != '\0') {
dest[dest_len + i] = src[i];
i++;
}
dest[dest_len + i] = '\0';
return dest;
}
char* strrchr(const char* str, int ch)
{
char c;
char* last = NULL;
while ((c = *str)) {
if (c == ch) {
last = (char*)(str);
}
str++;
}
return last;
}