summaryrefslogtreecommitdiff
path: root/riscv/riscv-probe/libfemto/std
diff options
context:
space:
mode:
authorCarlos Maiolino <[email protected]>2025-07-10 22:18:39 +0200
committerCarlos Maiolino <[email protected]>2025-07-10 22:18:39 +0200
commit8c6fc0c15415b32080a848bbde640e104098cf13 (patch)
tree04a21bd28f9dc82c8e216390d6208ed93b9bcd11 /riscv/riscv-probe/libfemto/std
Initial drop
Add some riscv code Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'riscv/riscv-probe/libfemto/std')
-rw-r--r--riscv/riscv-probe/libfemto/std/abort.c8
-rw-r--r--riscv/riscv-probe/libfemto/std/clz.c22
-rw-r--r--riscv/riscv-probe/libfemto/std/ctz.c22
-rw-r--r--riscv/riscv-probe/libfemto/std/exit.c12
-rw-r--r--riscv/riscv-probe/libfemto/std/getchar.c9
-rw-r--r--riscv/riscv-probe/libfemto/std/malloc.c146
-rw-r--r--riscv/riscv-probe/libfemto/std/memchr.c11
-rw-r--r--riscv/riscv-probe/libfemto/std/memcmp.c15
-rw-r--r--riscv/riscv-probe/libfemto/std/memcpy.c12
-rw-r--r--riscv/riscv-probe/libfemto/std/memset.c12
-rw-r--r--riscv/riscv-probe/libfemto/std/printf.c15
-rw-r--r--riscv/riscv-probe/libfemto/std/putchar.c9
-rw-r--r--riscv/riscv-probe/libfemto/std/puts.c9
-rw-r--r--riscv/riscv-probe/libfemto/std/snprintf.c14
-rw-r--r--riscv/riscv-probe/libfemto/std/strchr.c11
-rw-r--r--riscv/riscv-probe/libfemto/std/strcmp.c9
-rw-r--r--riscv/riscv-probe/libfemto/std/strlen.c12
-rw-r--r--riscv/riscv-probe/libfemto/std/strncmp.c9
-rw-r--r--riscv/riscv-probe/libfemto/std/strncpy.c15
-rw-r--r--riscv/riscv-probe/libfemto/std/vprintf.c14
-rw-r--r--riscv/riscv-probe/libfemto/std/vsnprintf.c109
21 files changed, 495 insertions, 0 deletions
diff --git a/riscv/riscv-probe/libfemto/std/abort.c b/riscv/riscv-probe/libfemto/std/abort.c
new file mode 100644
index 0000000..d4a7f06
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/abort.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+void abort(void)
+{
+ puts("abort");
+ exit(-1);
+}
diff --git a/riscv/riscv-probe/libfemto/std/clz.c b/riscv/riscv-probe/libfemto/std/clz.c
new file mode 100644
index 0000000..bc94795
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/clz.c
@@ -0,0 +1,22 @@
+// See LICENSE for license details.
+
+#include <stdint.h>
+
+#define GLUE_HELPER(x, y) x##y
+#define GLUE(x, y) GLUE_HELPER(x, y)
+
+#define DEFINE_CLZ(T,bits) \
+int GLUE(clz,bits)(T val) \
+{ \
+ int n = 0; \
+ for (n = 0; n < bits; n++) { \
+ if (val < 0) break; \
+ val <<= 1; \
+ } \
+ return n; \
+}
+
+DEFINE_CLZ(int8_t,8)
+DEFINE_CLZ(int16_t,16)
+DEFINE_CLZ(int32_t,32)
+DEFINE_CLZ(int64_t,64)
diff --git a/riscv/riscv-probe/libfemto/std/ctz.c b/riscv/riscv-probe/libfemto/std/ctz.c
new file mode 100644
index 0000000..098687c
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/ctz.c
@@ -0,0 +1,22 @@
+// See LICENSE for license details.
+
+#include <stdint.h>
+
+#define GLUE_HELPER(x, y) x##y
+#define GLUE(x, y) GLUE_HELPER(x, y)
+
+#define DEFINE_CTZ(T,bits) \
+int GLUE(ctz,bits)(T val) \
+{ \
+ int n = 0; \
+ for (n = 0; n < bits; n++) { \
+ if (val & 1) break; \
+ val >>= 1; \
+ } \
+ return n; \
+}
+
+DEFINE_CTZ(int8_t,8)
+DEFINE_CTZ(int16_t,16)
+DEFINE_CTZ(int32_t,32)
+DEFINE_CTZ(int64_t,64)
diff --git a/riscv/riscv-probe/libfemto/std/exit.c b/riscv/riscv-probe/libfemto/std/exit.c
new file mode 100644
index 0000000..2489ef5
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/exit.c
@@ -0,0 +1,12 @@
+// See LICENSE for license details.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <device.h>
+
+void exit(int status)
+{
+ poweroff_dev->poweroff(status);
+ asm volatile("1: j 1b");
+ __builtin_unreachable();
+}
diff --git a/riscv/riscv-probe/libfemto/std/getchar.c b/riscv/riscv-probe/libfemto/std/getchar.c
new file mode 100644
index 0000000..35babff
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/getchar.c
@@ -0,0 +1,9 @@
+// See LICENSE for license details.
+
+#include <stdio.h>
+#include <device.h>
+
+int getchar()
+{
+ return console_dev->getchar();
+}
diff --git a/riscv/riscv-probe/libfemto/std/malloc.c b/riscv/riscv-probe/libfemto/std/malloc.c
new file mode 100644
index 0000000..3df26f3
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/malloc.c
@@ -0,0 +1,146 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 Embedded Artistry
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "list.h"
+
+/* align to nearest power of two */
+#define ALIGN_SIZE(sz, align) (((sz) + ((align)-1)) & ~((align)-1))
+
+/* free list node*/
+typedef struct alloc_node
+{
+ struct list_head node;
+ size_t size;
+ char* block;
+} alloc_node_t;
+
+/* allocation metadata size */
+#define ALLOC_HEADER_SZ __builtin_offsetof(alloc_node_t, block)
+
+/* minimum allocation size of 32 bytes */
+#define MIN_ALLOC_SZ ALLOC_HEADER_SZ + 32
+
+/* free list */
+static LIST_HEAD(free_list);
+
+static void coalesce_free_list(void)
+{
+ alloc_node_t *b, *lb = NULL, *t;
+
+ list_for_each_entry_safe(b, t, &free_list, node)
+ {
+ if (lb)
+ {
+ /* coalesce adjacent blocks */
+ if ((((uintptr_t)&lb->block) + lb->size) == (uintptr_t)b)
+ {
+ lb->size += sizeof(*b) + b->size;
+ list_del(&b->node);
+ continue;
+ }
+ }
+ lb = b;
+ }
+}
+
+void* malloc(size_t size)
+{
+ void* ptr = NULL;
+ alloc_node_t* blk = NULL;
+
+ if (size > 0)
+ {
+ /* Align the pointer */
+ size = ALIGN_SIZE(size, sizeof(void*));
+
+ /* try to find a big enough block */
+ list_for_each_entry(blk, &free_list, node)
+ {
+ if (blk->size >= size)
+ {
+ ptr = &blk->block;
+ break;
+ }
+ }
+
+ if (ptr)
+ {
+ /* split block if possible */
+ if ((blk->size - size) >= MIN_ALLOC_SZ)
+ {
+ alloc_node_t* new_blk;
+ new_blk = (alloc_node_t*)((uintptr_t)(&blk->block) + size);
+ new_blk->size = blk->size - size - ALLOC_HEADER_SZ;
+ blk->size = size;
+ list_add(&new_blk->node, &blk->node);
+ }
+
+ list_del(&blk->node);
+ }
+
+ }
+
+ return ptr;
+}
+
+void free(void* ptr)
+{
+ alloc_node_t *blk, *free_blk;
+
+ if (ptr)
+ {
+ blk = container_of(ptr, alloc_node_t, block);
+
+ /* add block to free list in ascending order by pointer */
+ list_for_each_entry(free_blk, &free_list, node)
+ {
+ if (free_blk > blk)
+ {
+ list_add_tail(&blk->node, &free_blk->node);
+ goto blockadded;
+ }
+ }
+ list_add_tail(&blk->node, &free_list);
+
+ blockadded:
+ coalesce_free_list();
+ }
+}
+
+void _malloc_addblock(void* addr, size_t size)
+{
+ alloc_node_t* blk;
+
+ /* pointer align the block */
+ blk = (alloc_node_t*)ALIGN_SIZE((uintptr_t)addr, sizeof(void*));
+
+ /* calculate usable size */
+ blk->size = (uintptr_t)addr + size - (uintptr_t)blk - ALLOC_HEADER_SZ;
+
+ /* add the block to the free list */
+ list_add(&blk->node, &free_list);
+}
diff --git a/riscv/riscv-probe/libfemto/std/memchr.c b/riscv/riscv-probe/libfemto/std/memchr.c
new file mode 100644
index 0000000..b8287ff
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/memchr.c
@@ -0,0 +1,11 @@
+#include <string.h>
+
+void *memchr(const void *s, int c, size_t n)
+{
+ unsigned char *p = (unsigned char *)s;
+ while (n-- > 0) {
+ if (*p == c) return p;
+ p++;
+ }
+ return NULL;
+}
diff --git a/riscv/riscv-probe/libfemto/std/memcmp.c b/riscv/riscv-probe/libfemto/std/memcmp.c
new file mode 100644
index 0000000..73932c9
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/memcmp.c
@@ -0,0 +1,15 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+
+int memcmp(const void *s1, const void *s2, size_t n)
+{
+ while (n-- > 0) {
+ char c1 = *(const char*)s1++;
+ char c2 = *(const char*)s2++;
+ if (c1 != c2) {
+ return c1 - c2;
+ }
+ }
+ return 0;
+}
diff --git a/riscv/riscv-probe/libfemto/std/memcpy.c b/riscv/riscv-probe/libfemto/std/memcpy.c
new file mode 100644
index 0000000..69209e7
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/memcpy.c
@@ -0,0 +1,12 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ char *p = dest;
+ while (n-- > 0) {
+ *(char*)dest++ = *(char*)src++;
+ }
+ return p;
+}
diff --git a/riscv/riscv-probe/libfemto/std/memset.c b/riscv/riscv-probe/libfemto/std/memset.c
new file mode 100644
index 0000000..82b1545
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/memset.c
@@ -0,0 +1,12 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+
+void *memset(void *dest, int c, size_t n)
+{
+ char *p = dest;
+ while (n-- > 0) {
+ *(char*)dest++ = c;
+ }
+ return p;
+}
diff --git a/riscv/riscv-probe/libfemto/std/printf.c b/riscv/riscv-probe/libfemto/std/printf.c
new file mode 100644
index 0000000..5d81212
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/printf.c
@@ -0,0 +1,15 @@
+// See LICENSE for license details.
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+int printf(const char* s, ...)
+{
+ int res = 0;
+ va_list vl;
+ va_start(vl, s);
+ res = vprintf(s, vl);
+ va_end(vl);
+ return res;
+}
diff --git a/riscv/riscv-probe/libfemto/std/putchar.c b/riscv/riscv-probe/libfemto/std/putchar.c
new file mode 100644
index 0000000..3066a65
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/putchar.c
@@ -0,0 +1,9 @@
+// See LICENSE for license details.
+
+#include <stdio.h>
+#include <device.h>
+
+int putchar(int ch)
+{
+ return console_dev->putchar(ch);
+}
diff --git a/riscv/riscv-probe/libfemto/std/puts.c b/riscv/riscv-probe/libfemto/std/puts.c
new file mode 100644
index 0000000..2dd07f7
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/puts.c
@@ -0,0 +1,9 @@
+// See LICENSE for license details.
+
+#include <stdio.h>
+
+int puts(const char *s)
+{
+ while (*s) putchar(*s++);
+ putchar('\n');
+}
diff --git a/riscv/riscv-probe/libfemto/std/snprintf.c b/riscv/riscv-probe/libfemto/std/snprintf.c
new file mode 100644
index 0000000..0228195
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/snprintf.c
@@ -0,0 +1,14 @@
+// See LICENSE for license details.
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+int snprintf(char* out, size_t n, const char* s, ...)
+{
+ va_list vl;
+ va_start(vl, s);
+ int res = vsnprintf(out, n, s, vl);
+ va_end(vl);
+ return res;
+}
diff --git a/riscv/riscv-probe/libfemto/std/strchr.c b/riscv/riscv-probe/libfemto/std/strchr.c
new file mode 100644
index 0000000..7eef221
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/strchr.c
@@ -0,0 +1,11 @@
+#include <string.h>
+
+char *strchr(const char *s, int c)
+{
+ char *p = (char *)s;
+ while (*p) {
+ if (*p == c) return p;
+ p++;
+ }
+ return NULL;
+}
diff --git a/riscv/riscv-probe/libfemto/std/strcmp.c b/riscv/riscv-probe/libfemto/std/strcmp.c
new file mode 100644
index 0000000..73d9d8a
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/strcmp.c
@@ -0,0 +1,9 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+
+int strcmp(const char *s1, const char *s2)
+{
+ while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; }
+ return *s1 - *s2;
+}
diff --git a/riscv/riscv-probe/libfemto/std/strlen.c b/riscv/riscv-probe/libfemto/std/strlen.c
new file mode 100644
index 0000000..74de6c4
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/strlen.c
@@ -0,0 +1,12 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+
+size_t strlen(const char* s)
+{
+ const char *p = s;
+ for (;; s++) {
+ if (!*s) break;
+ }
+ return s - p;
+}
diff --git a/riscv/riscv-probe/libfemto/std/strncmp.c b/riscv/riscv-probe/libfemto/std/strncmp.c
new file mode 100644
index 0000000..e1b476c
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/strncmp.c
@@ -0,0 +1,9 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+ while (n-- > 0 && *s1 && *s2 && *s1 == *s2) { s1++; s2++; }
+ return *s1 - *s2;
+}
diff --git a/riscv/riscv-probe/libfemto/std/strncpy.c b/riscv/riscv-probe/libfemto/std/strncpy.c
new file mode 100644
index 0000000..ccb8fc3
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/strncpy.c
@@ -0,0 +1,15 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+
+char *strncpy(char *dst, const char *src, size_t n)
+{
+ size_t i;
+ for (i = 0; i < n && src[i]; i++) {
+ dst[i] = src[i];
+ }
+ for (; i < n; i++) {
+ dst[i] = 0;
+ }
+ return dst;
+}
diff --git a/riscv/riscv-probe/libfemto/std/vprintf.c b/riscv/riscv-probe/libfemto/std/vprintf.c
new file mode 100644
index 0000000..36c99a3
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/vprintf.c
@@ -0,0 +1,14 @@
+// See LICENSE for license details.
+
+#include <stdio.h>
+#include <alloca.h>
+
+int vprintf(const char* s, va_list vl)
+{
+ char *out;
+ int res = vsnprintf(NULL, -1, s, vl);
+ out = alloca(res + 1);
+ vsnprintf(out, res + 1, s, vl);
+ while (*out) putchar(*out++);
+ return res;
+}
diff --git a/riscv/riscv-probe/libfemto/std/vsnprintf.c b/riscv/riscv-probe/libfemto/std/vsnprintf.c
new file mode 100644
index 0000000..32dcf3f
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/std/vsnprintf.c
@@ -0,0 +1,109 @@
+// See LICENSE for license details.
+
+#include <stddef.h>
+#include <stdarg.h>
+
+int vsnprintf(char * out, size_t n, const char* s, va_list vl)
+{
+ int format = 0;
+ int longarg = 0;
+ size_t pos = 0;
+ for( ; *s; s++) {
+ if (format) {
+ switch(*s) {
+ case 'l': {
+ longarg = 1;
+ break;
+ }
+ case 'p': {
+ longarg = 1;
+ if (out && pos < n) {
+ out[pos] = '0';
+ }
+ pos++;
+ if (out && pos < n) {
+ out[pos] = 'x';
+ }
+ pos++;
+ }
+ case 'x': {
+ long num = longarg ? va_arg(vl, long) : va_arg(vl, int);
+ int hexdigits = 2*(longarg ? sizeof(long) : sizeof(int))-1;
+ for(int i = hexdigits; i >= 0; i--) {
+ int d = (num >> (4*i)) & 0xF;
+ if (out && pos < n) {
+ out[pos] = (d < 10 ? '0'+d : 'a'+d-10);
+ }
+ pos++;
+ }
+ longarg = 0;
+ format = 0;
+ break;
+ }
+ case 'd': {
+ long num = longarg ? va_arg(vl, long) : va_arg(vl, int);
+ if (num < 0) {
+ num = -num;
+ if (out && pos < n) {
+ out[pos] = '-';
+ }
+ pos++;
+ }
+ long digits = 1;
+ for (long nn = num; nn /= 10; digits++)
+ ;
+ for (int i = digits-1; i >= 0; i--) {
+ if (out && pos + i < n) {
+ out[pos + i] = '0' + (num % 10);
+ }
+ num /= 10;
+ }
+ pos += digits;
+ longarg = 0;
+ format = 0;
+ break;
+ }
+ case 's': {
+ const char* s2 = va_arg(vl, const char*);
+ while (*s2) {
+ if (out && pos < n) {
+ out[pos] = *s2;
+ }
+ pos++;
+ s2++;
+ }
+ longarg = 0;
+ format = 0;
+ break;
+ }
+ case 'c': {
+ if (out && pos < n) {
+ out[pos] = (char)va_arg(vl,int);
+ }
+ pos++;
+ longarg = 0;
+ format = 0;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if(*s == '%') {
+ format = 1;
+ }
+ else {
+ if (out && pos < n) {
+ out[pos] = *s;
+ }
+ pos++;
+ }
+ }
+ if (out && pos < n) {
+ out[pos] = 0;
+ }
+ else if (out && n) {
+ out[n-1] = 0;
+ }
+ return pos;
+}