// 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 #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; }