sllibc/string.c

400 lines
8.0 KiB
C
Raw Normal View History

2025-06-04 01:22:53 +10:00
// Copyright (c) 2025, Zak Fenton
// Zak Fenton's libc is licensed under the Mulan PSL v2. You can use this
// software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN “AS IS” BASIS, WITHOUT warranties of
// any kind, either express or implied, including but not limited to
// non-infringement, merchantability or fit for a particular purpose.
// See the Mulan PSL v2 for more details.
// For auditing purposes, this is NEW CODE
#ifdef KERNEL_MODE
#define size_t long
#define NULL ((void*)0ULL)
#else
#include <string.h>
#include "internal.h"
#endif
//ifdef _ZCC
#ifdef NOT_USED_YET
/* Works like memset except assumes n is a multiple of 8 and src>=dst+8.
* Doesn't return a useful value.
*/
void __naked memset_quick64(void* dst, uint64 v, uint64 n) __asm {
add a3, a0, a2
.setloop:
sd a1, 0(a0)
addi a0, a0, 8
bne a0, a3, .setloop
ret
}
void __naked memset_quick(void* dst, uint64 v, uint64 n) __asm {
add a3, a0, a2
.setloopa:
sb a1, 0(a0)
addi a0, a0, 1
bne a0, a3, .setloopa
ret
}
void* __naked memset_opt(void* dst, uint64 v, uint64 n) __asm {
add a3, a0, a2
add a4, a0, zero
beq a2, zero, .endopt
addi a6, zero, 16
blt a2, a6, .setloopoptshort
addi a6, zero, 128
blt a6, a2, .setloopoptlong
.setloopopt:
sb a1, 0(a4)
addi a4, a4, 1
andi a5, a4, 7
beq a5, zero, .setloopopt64
.setloopstartopt:
bne a4, a3, .setloopopt
.endopt:
ret
.setloopoptshort:
sb a1, 0(a4)
addi a4, a4, 1
bne a4, a3, .setloopoptshort
ret
.setloopopt64adjust:
addi a3, a3, -1
sb a1, 0(a3)
.setloopopt64:
bne a1, zero, .setloopstartopt
andi a6, a3, 7
bne a6, zero, .setloopopt64adjust
//addi a6, zero, 8
.setloopopt64b:
//sub a5, a3, a4
//blt a5, a6, .setloopstartopt
sd a1, 0(a4)
addi a4, a4, 8
blt a4, a3, .setloopopt64b
//j .setloopstartopt
ret
.setloopoptlong:
bne a1, zero, .setloopstartopt
andi a6, a2, 127
bne a6, zero, .setloopstartopt
.setloopoptlongb:
sd zero, 0(a4)
sd zero, 8(a4)
sd zero, 16(a4)
sd zero, 24(a4)
sd zero, 32(a4)
sd zero, 40(a4)
sd zero, 48(a4)
sd zero, 56(a4)
sd zero, 64(a4)
sd zero, 72(a4)
sd zero, 80(a4)
sd zero, 88(a4)
sd zero, 96(a4)
sd zero, 104(a4)
sd zero, 112(a4)
sd zero, 120(a4)
addi a4, a4, 128
bne a4, a3, .setloopoptlongb
ret
}
void* __naked memcpy_opt(void* dst, void* src, uint64 n) __asm {
add a3, a0, a2
add a4, a0, zero
beq a2, zero, .endcpy
addi a6, zero, 16
blt a2, a6, .cpyloopoptshort
addi a6, zero, 128
blt a6, a2, .cpyloopoptlong
.cpyloopopt:
lb a6, 0(a1)
sb a6, 0(a4)
addi a4, a4, 1
addi a1, a1, 1
andi a5, a4, 7
beq a5, zero, .cpyloopopt64
.cpyloopstartopt:
bne a4, a3, .cpyloopopt
.endcpy:
ret
.cpyloopoptshort:
lb a6, 0(a1)
sb a6, 0(a4)
addi a4, a4, 1
addi a1, a1, 1
bne a4, a3, .cpyloopoptshort
ret
.cpyloopopt64adjust:
addi a3, a3, -1
sub a5, a3, a4
add a5, a5, a1
lb a6, 0(a5)
sb a6, 0(a3)
.cpyloopopt64:
andi a6, a3, 7
bne a6, zero, .cpyloopopt64adjust
//addi a6, zero, 8
.cpyloopopt64b:
//sub a5, a3, a4
//blt a5, a6, .setloopstartopt
ld a6, 0(a1)
sd a6, 0(a4)
addi a4, a4, 8
addi a1, a1, 8
blt a4, a3, .cpyloopopt64b
//j .setloopstartopt
ret
.cpyloopoptlong:
andi a6, a2, 127
bne a6, zero, .cpyloopstartopt
.cpyloopoptlongb:
ld a6, 0(a1)
sd a6, 0(a4)
ld a6, 8(a1)
sd a6, 8(a4)
ld a6, 16(a1)
sd a6, 16(a4)
ld a6, 24(a1)
sd a6, 24(a4)
ld a6, 32(a1)
sd a6, 32(a4)
ld a6, 40(a1)
sd a6, 40(a4)
ld a6, 48(a1)
sd a6, 48(a4)
ld a6, 56(a1)
sd a6, 56(a4)
ld a6, 64(a1)
sd a6, 64(a4)
ld a6, 72(a1)
sd a6, 72(a4)
ld a6, 80(a1)
sd a6, 80(a4)
ld a6, 88(a1)
sd a6, 88(a4)
ld a6, 96(a1)
sd a6, 96(a4)
ld a6, 104(a1)
sd a6, 104(a4)
ld a6, 112(a1)
sd a6, 112(a4)
ld a6, 120(a1)
sd a6, 120(a4)
addi a4, a4, 128
addi a1, a1, 128
bne a4, a3, .cpyloopoptlongb
ret
}
// Works like memcpy except assumes n is a multiple of 8 and src>=dst+8.
// Doesn't return a useful value.
void __naked memcpy_quick64(void* dst, void* src, uint64 n) __asm {
add a3, a0, a2
.cpyloop:
ld a4, 0(a1)
addi a1, a1, 8
sd a4, 0(a0)
addi a0, a0, 8
bne a0, a3, .cpyloop
ret
}
// Expands a byte to a word.
uint64 __naked expandbyte_quick64(int b) __asm {
andi a1, a0, 255
slli a0, a0, 8
or a0, a0, a1
slli a0, a0, 8
or a0, a0, a1
slli a0, a0, 8
or a0, a0, a1
slli a0, a0, 8
or a0, a0, a1
slli a0, a0, 8
or a0, a0, a1
slli a0, a0, 8
or a0, a0, a1
slli a0, a0, 8
or a0, a0, a1
ret
}
#endif
// Copied from my preexisting number parser in numbered.c
unsigned long long _libc_scandec(const char** strvar) {
unsigned long long val = 0;
const char* s = *strvar;
char c;
while ((c = *s) >= '0' && c <= '9') {
unsigned long long oldval = val;
val = val * 10 + c - '0';
if (val / 10 != oldval) {
return 0;
}
s++;
}
*strvar = s;
return val;
}
long long atoll(const char* str) {
if (*str == '-') {
str++;
long long x = (long long) _libc_scandec(&str);
return -x;
} else if (*str == '+') {
str++;
return (long long) _libc_scandec(&str);
} else {
return (long long) _libc_scandec(&str);
}
}
long atol(const char* str) {
return (long) atoll(str);
}
int atoi(const char* str) {
return (int) atoll(str);
}
size_t strlen(const char* foo) {
if (foo == NULL) {
return 0;
} else {
size_t i = 0;
while (foo[i] != 0) i++;
return i;
}
}
void* memcpy(void* dst, const void* src, size_t nbytes) {
char* cdst = (char*) dst;
const char* csrc = (char*) src;
size_t i = 0;
for (i = 0; i < nbytes; i++) {
cdst[i] = csrc[i];
}
return dst;
}
void* memset(void* mem, int byt, size_t nbytes) {
char* tmp = mem;
for (size_t i = 0; i < nbytes; i++) {
tmp[i] = (char) byt;
}
return mem;
}
int strcmp(const char* a, const char* b) {
while (*a == *b) {
if (*a == 0) {
return 0; // Got to the end, strings are equal
}
a++;
b++;
}
return *a - *b;
}
char* strcat(char* dst, const char* src) {
char* end = dst;
while (*end) { // Find the terminating zero of the dst string
end++;
}
while (*src) { // Overwrite the end of dst from src until it's terminating zero
*end++ = *src++;
}
*end = 0; // Add terminating zero back to dst
return dst; // Return the start of the dst string
}
char* strcpy(char *dst, const char* src) {
char *d = dst;
while (*src) {
*d++ = *src++;
}
*d = 0;
return dst;
}
char* strncpy(char* dst, const char* src, size_t n) {
size_t i = 0;
char *d = dst;
while (*src) {
*d++ = *src++;
i++;
}
while (i < n) { // TODO: Is this right??
dst[i] = 0;
i++;
}
return dst;
}
#ifndef KERNEL_MODE
char* strdup(const char* src) {
char* result = malloc(strlen(src) + 1);
if (result) {
strcpy(result, src);
}
return result;
}
char* strndup(const char* str, size_t n) {
size_t resultlen = strlen(str);
if (resultlen > n) {
resultlen = n;
}
char* result = malloc(resultlen + 1);
if (result) {
for (size_t i = 0; i < resultlen; i++) {
result[i] = str[i];
}
str[resultlen] = 0;
}
return result;
}
#endif
const char* strpbrk(const char* str, const char* search) {
char c;
while ((c = *str)) {
const char* s = search;
while (*s++) {
if (c == *s) {
return str;
}
}
str++;
}
return NULL;
}
char *strchr(const char* str, int chr) {
int c;
while ((c = *str)) {
if (c == chr) {
return (char*) str;
}
str++;
}
return NULL;
}
char *strrchr(const char* str, int chr) {
int c;
char* result = NULL;
while ((c = *str)) {
if (c == chr) {
result = (char*) str;
}
str++;
}
return result;
}