diff options
Diffstat (limited to 'riscv/riscv-probe/libfemto/std')
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; +} |
