diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b28fa89..6031b7c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,7 +150,7 @@ endif () include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) set (THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) +# find_package(Threads REQUIRED) add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) set_target_properties (vmlib PROPERTIES OUTPUT_NAME iwasm) diff --git a/core/shared/platform/baremetal/platform_init.c b/core/shared/platform/baremetal/platform_init.c new file mode 100644 index 00000000..331eea4e --- /dev/null +++ b/core/shared/platform/baremetal/platform_init.c @@ -0,0 +1,1225 @@ +#include "platform_api_vmcore.h" + +// Many implementations taken from musl: https://git.musl-libc.org + +// typedef int (*cmpfun)(const void *, const void *, void *); +typedef int (*cmpfun)(const void *, const void *); + +void +qsort(void *base, size_t nel, size_t width, cmpfun cmp) +{ +} + +static const int32_t upper_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 91, 92, 93, 94, 95, 96, + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 123, 124, 125, 126, + 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const int32_t *const upper_ptable = upper_table + 128; + +const int32_t ** +__ctype_toupper_loc(void) +{ + return (void *)&upper_ptable; +} + +static const int32_t lower_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 91, 92, 93, 94, 95, 96, + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 123, 124, 125, 126, + 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const int32_t *const lower_ptable = lower_table + 128; + +const int32_t ** +__ctype_tolower_loc(void) +{ + return (void *)&lower_ptable; +} + +#if __BYTE_ORDER == __BIG_ENDIAN +#define X(x) x +#else +#define X(x) (((x) / 256 | (x) * 256) % 65536) +#endif + +static const unsigned short table[] = { + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), + X(0x200), X(0x200), X(0x200), X(0x200), X(0x320), X(0x220), X(0x220), + X(0x220), X(0x220), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), + X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), + X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x160), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), + X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x8d5), X(0x8d5), X(0x8d5), + X(0x8d5), X(0x8d5), X(0x8d5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), + X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), + X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), + X(0x8c5), X(0x8c5), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), + X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), + X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), + X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x4c0), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x200), 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +static const unsigned short *const ptable = table + 128; + +const unsigned short ** +__ctype_b_loc(void) +{ + return (void *)&ptable; +} + +__attribute__((weak)) int +os_dumps_proc_mem_info(char *out, unsigned int size) +{ + return -1; +} + +__attribute__((weak)) void +__stack_chk_fail() +{ +} + +__attribute__((weak)) uint32_t +__stack_chk_fail_local() +{ + return 0; +} + +int +os_cond_init(korp_cond *cond) +{ + return 0; +} + +int +os_cond_destroy(korp_cond *cond) +{ + return 0; +} + +/**************************************************** + * string + ****************************************************/ + +static char * +twobyte_strstr(const unsigned char *h, const unsigned char *n) +{ + uint16_t nw = n[0] << 8 | n[1], hw = h[0] << 8 | h[1]; + for (h++; *h && hw != nw; hw = hw << 8 | *++h) + ; + return *h ? (char *)h - 1 : 0; +} + +static char * +threebyte_strstr(const unsigned char *h, const unsigned char *n) +{ + uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8; + uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8; + for (h += 2; *h && hw != nw; hw = (hw | *++h) << 8) + ; + return *h ? (char *)h - 2 : 0; +} + +static char * +fourbyte_strstr(const unsigned char *h, const unsigned char *n) +{ + uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; + uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3]; + for (h += 3; *h && hw != nw; hw = hw << 8 | *++h) + ; + return *h ? (char *)h - 3 : 0; +} + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define BITOP(a, b, op) \ + ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 \ + << ((size_t)(b) % (8 * sizeof *(a)))) + +static char * +twoway_strstr(const unsigned char *h, const unsigned char *n) +{ + const unsigned char *z; + size_t l, ip, jp, k, p, ms, p0, mem, mem0; + size_t byteset[32 / sizeof(size_t)] = { 0 }; + size_t shift[256]; + + /* Computing length of needle and fill shift table */ + for (l = 0; n[l] && h[l]; l++) + BITOP(byteset, n[l], |=), shift[n[l]] = l + 1; + if (n[l]) + return 0; /* hit the end of h */ + + /* Compute maximal suffix */ + ip = -1; + jp = 0; + k = p = 1; + while (jp + k < l) { + if (n[ip + k] == n[jp + k]) { + if (k == p) { + jp += p; + k = 1; + } + else + k++; + } + else if (n[ip + k] > n[jp + k]) { + jp += k; + k = 1; + p = jp - ip; + } + else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; + jp = 0; + k = p = 1; + while (jp + k < l) { + if (n[ip + k] == n[jp + k]) { + if (k == p) { + jp += p; + k = 1; + } + else + k++; + } + else if (n[ip + k] < n[jp + k]) { + jp += k; + k = 1; + p = jp - ip; + } + else { + ip = jp++; + k = p = 1; + } + } + if (ip + 1 > ms + 1) + ms = ip; + else + p = p0; + + /* Periodic needle? */ + if (memcmp(n, n + p, ms + 1)) { + mem0 = 0; + p = MAX(ms, l - ms - 1) + 1; + } + else + mem0 = l - p; + mem = 0; + + /* Initialize incremental end-of-haystack pointer */ + z = h; + + /* Search loop */ + for (;;) { + /* Update incremental end-of-haystack pointer */ + if (z - h < l) { + /* Fast estimate for MAX(l,63) */ + size_t grow = l | 63; + const unsigned char *z2 = memchr(z, 0, grow); + if (z2) { + z = z2; + if (z - h < l) + return 0; + } + else + z += grow; + } + + /* Check last byte first; advance by shift on mismatch */ + if (BITOP(byteset, h[l - 1], &)) { + k = l - shift[h[l - 1]]; + if (k) { + if (k < mem) + k = mem; + h += k; + mem = 0; + continue; + } + } + else { + h += l; + mem = 0; + continue; + } + + /* Compare right half */ + for (k = MAX(ms + 1, mem); n[k] && n[k] == h[k]; k++) + ; + if (n[k]) { + h += k - ms; + mem = 0; + continue; + } + /* Compare left half */ + for (k = ms + 1; k > mem && n[k - 1] == h[k - 1]; k--) + ; + if (k <= mem) + return (char *)h; + h += p; + mem = mem0; + } +} + +__attribute__((weak)) char * +strstr(const char *h, const char *n) +{ + /* Return immediately on empty needle */ + if (!n[0]) + return (char *)h; + + /* Use faster algorithms for short needles */ + h = strchr(h, *n); + if (!h || !n[1]) + return (char *)h; + if (!h[1]) + return 0; + if (!n[2]) + return twobyte_strstr((void *)h, (void *)n); + if (!h[2]) + return 0; + if (!n[3]) + return threebyte_strstr((void *)h, (void *)n); + if (!h[3]) + return 0; + if (!n[4]) + return fourbyte_strstr((void *)h, (void *)n); + + return twoway_strstr((void *)h, (void *)n); +} + +__attribute__((weak)) void * +memcpy(void *restrict dest, const void *restrict src, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + + for (; n; n--) + *d++ = *s++; + return dest; +} + +__attribute__((weak)) void * +memmove(void *dest, const void *src, size_t n) +{ + char *d = dest; + const char *s = src; + + if (d == s) + return d; + if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n) + return memcpy(d, s, n); + + if (d < s) { + for (; n; n--) + *d++ = *s++; + } + else { + while (n) + n--, d[n] = s[n]; + } + + return dest; +} + +__attribute__((weak)) void * +memset(void *dest, int c, size_t n) +{ + unsigned char *s = dest; + size_t k; + + /* Fill head and tail with minimal branching. Each + * conditional ensures that all the subsequently used + * offsets are well-defined and in the dest region. */ + + if (!n) + return dest; + s[0] = c; + s[n - 1] = c; + if (n <= 2) + return dest; + s[1] = c; + s[2] = c; + s[n - 2] = c; + s[n - 3] = c; + if (n <= 6) + return dest; + s[3] = c; + s[n - 4] = c; + if (n <= 8) + return dest; + + /* Advance pointer to align it at a 4-byte boundary, + * and truncate n to a multiple of 4. The previous code + * already took care of any head/tail that get cut off + * by the alignment. */ + + k = -(uintptr_t)s & 3; + s += k; + n -= k; + n &= -4; + + for (; n; n--, s++) + *s = c; + + return dest; +} + +__attribute__((weak)) int +memcmp(const void *vl, const void *vr, size_t n) +{ + const unsigned char *l = vl, *r = vr; + for (; n && *l == *r; n--, l++, r++) + ; + return n ? *l - *r : 0; +} + +__attribute__((weak)) void * +memchr(const void *src, int c, size_t n) +{ + const unsigned char *s = src; + c = (unsigned char)c; + for (; n && *s != c; s++, n--) + ; + return n ? (void *)s : 0; +} + +__attribute__((weak)) unsigned long +strtoul(const char *restrict s, char **restrict p, int base) +{ + return 0; +} + +__attribute__((weak)) long +strtol(const char *restrict s, char **restrict p, int base) +{ + return 0; +} + +__attribute__((weak)) int +strncmp(const char *_l, const char *_r, size_t n) +{ + const unsigned char *l = (void *)_l, *r = (void *)_r; + if (!n--) + return 0; + for (; *l && *r && n && *l == *r; l++, r++, n--) + ; + return *l - *r; +} + +__attribute__((weak)) int +strcmp(const char *l, const char *r) +{ + for (; *l == *r && *l; l++, r++) + ; + return *(unsigned char *)l - *(unsigned char *)r; +} + +__attribute__((weak)) size_t +strlen(const char *s) +{ + const char *a = s; + for (; *s; s++) + ; + return s - a; +} + +__attribute__((weak)) char * +__stpncpy(char *restrict d, const char *restrict s, size_t n) +{ + for (; n && (*d = *s); n--, s++, d++) + ; + memset(d, 0, n); + return d; +} + +__attribute__((weak)) char * +strncpy(char *restrict d, const char *restrict s, size_t n) +{ + __stpncpy(d, s, n); + return d; +} + +__attribute__((weak)) char * +__strchrnul(const char *s, int c) +{ + c = (unsigned char)c; + if (!c) + return (char *)s + strlen(s); + + for (; *s && *(unsigned char *)s != c; s++) + ; + return (char *)s; +} + +__attribute__((weak)) char * +strchr(const char *s, int c) +{ + char *r = __strchrnul(s, c); + return *(unsigned char *)r == (unsigned char)c ? r : 0; +} + +#define BITOP(a, b, op) \ + ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 \ + << ((size_t)(b) % (8 * sizeof *(a)))) + +__attribute__((weak)) size_t +strspn(const char *s, const char *c) +{ + const char *a = s; + size_t byteset[32 / sizeof(size_t)] = { 0 }; + + if (!c[0]) + return 0; + if (!c[1]) { + for (; *s == *c; s++) + ; + return s - a; + } + + for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) + ; + for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++) + ; + return s - a; +} + +__attribute__((weak)) size_t +strcspn(const char *s, const char *c) +{ + const char *a = s; + size_t byteset[32 / sizeof(size_t)]; + + if (!c[0] || !c[1]) + return __strchrnul(s, *c) - a; + + memset(byteset, 0, sizeof byteset); + for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) + ; + for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++) + ; + return s - a; +} + +__attribute__((weak)) int +my_tolower(int c) +{ + if ((unsigned)c - 'A' < 26) + // if (isupper(c)) + return c | 32; + return c; +} + +__attribute__((weak)) int +strncasecmp(const char *_l, const char *_r, size_t n) +{ + const unsigned char *l = (void *)_l, *r = (void *)_r; + if (!n--) + return 0; + for (; *l && *r && n && (*l == *r || my_tolower(*l) == my_tolower(*r)); + l++, r++, n--) + ; + return my_tolower(*l) - my_tolower(*r); +} + +/**************************************************** + * stdio + ****************************************************/ + +__attribute__((weak)) int +snprintf(char *restrict s, size_t n, const char *restrict fmt, ...) +{ + return 0; +} + +__attribute__((weak)) int +__snprintf_chk(char *s, size_t n, int m, size_t o, const char *fmt, ...) +{ + return 0; +} + +__attribute__((weak)) int +vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) +{ + return 0; +} + +__attribute__((weak)) int +__vsnprintf_chk(char *s, size_t n, int m, size_t o, const char *fmt, +#if __x86_64__ + __gnuc_va_list whatever) +#else + char *whatever) +#endif +{ + return 0; +} + +/**************************************************** + * mman + ****************************************************/ + +void * +os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) +{ + return NULL; +} + +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size) +{ + return NULL; +} + +void +os_munmap(void *addr, size_t size) +{ +} + +int +os_mprotect(void *addr, size_t size, int prot) +{ + return 0; +} + +/**************************************************** + * lgcc/math + ****************************************************/ + +double +sqrt(double x) +{ + return 0.0; +} + +float +sqrtf(float x) +{ + return 0.0; +} + +/* +#define arith64_u64 unsigned long long int +#define arith64_s64 signed long long int +#define arith64_u32 unsigned int +#define arith64_s32 int + +typedef union { + arith64_u64 u64; + arith64_s64 s64; + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + arith64_u32 hi; + arith64_u32 lo; +#else + arith64_u32 lo; + arith64_u32 hi; +#endif + } u32; + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + arith64_s32 hi; + arith64_s32 lo; +#else + arith64_s32 lo; + arith64_s32 hi; +#endif + } s32; +} arith64_word; + +// extract hi and lo 32-bit words from 64-bit value +#define arith64_hi(n) (arith64_word){ .u64 = n }.u32.hi +#define arith64_lo(n) (arith64_word){ .u64 = n }.u32.lo + +// Negate a if b is negative, via invert and increment. +#define arith64_neg(a, b) \ + (((a) ^ ((((arith64_s64)(b)) >= 0) - 1)) + (((arith64_s64)(b)) < 0)) +#define arith64_abs(a) arith64_neg(a, a) + +// Return the absolute value of a. +// Note LLINT_MIN cannot be negated. +__attribute__((weak)) arith64_s64 +__absvdi2(arith64_s64 a) +{ + return arith64_abs(a); +} + +// Return the result of shifting a left by b bits. +__attribute__((weak)) arith64_s64 +__ashldi3(arith64_s64 a, int b) +{ + arith64_word w = { .s64 = a }; + + b &= 63; + + if (b >= 32) { + w.u32.hi = w.u32.lo << (b - 32); + w.u32.lo = 0; + } + else if (b) { + w.u32.hi = (w.u32.lo >> (32 - b)) | (w.u32.hi << b); + w.u32.lo <<= b; + } + return w.s64; +} + +// Return the result of arithmetically shifting a right by b bits. +__attribute__((weak)) arith64_s64 +__ashrdi3(arith64_s64 a, int b) +{ + arith64_word w = { .s64 = a }; + + b &= 63; + + if (b >= 32) { + w.s32.lo = w.s32.hi >> (b - 32); + w.s32.hi >>= 31; // 0xFFFFFFFF or 0 + } + else if (b) { + w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b); + w.s32.hi >>= b; + } + return w.s64; +} + +// These functions return the number of leading 0-bits in a, starting at the +// most significant bit position. If a is zero, the result is undefined. +__attribute__((weak)) int +__clzsi2(arith64_u32 a) +{ + int b, n = 0; + b = !(a & 0xffff0000) << 4; + n += b; + a <<= b; + b = !(a & 0xff000000) << 3; + n += b; + a <<= b; + b = !(a & 0xf0000000) << 2; + n += b; + a <<= b; + b = !(a & 0xc0000000) << 1; + n += b; + a <<= b; + return n + !(a & 0x80000000); +} + +__attribute__((weak)) int +__clzdi2(arith64_u64 a) +{ + int b, n = 0; + b = !(a & 0xffffffff00000000ULL) << 5; + n += b; + a <<= b; + b = !(a & 0xffff000000000000ULL) << 4; + n += b; + a <<= b; + b = !(a & 0xff00000000000000ULL) << 3; + n += b; + a <<= b; + b = !(a & 0xf000000000000000ULL) << 2; + n += b; + a <<= b; + b = !(a & 0xc000000000000000ULL) << 1; + n += b; + a <<= b; + return n + !(a & 0x8000000000000000ULL); +} + +// These functions return the number of trailing 0-bits in a, starting at the +// least significant bit position. If a is zero, the result is undefined. +__attribute__((weak)) int +__ctzsi2(arith64_u32 a) +{ + int b, n = 0; + b = !(a & 0x0000ffff) << 4; + n += b; + a >>= b; + b = !(a & 0x000000ff) << 3; + n += b; + a >>= b; + b = !(a & 0x0000000f) << 2; + n += b; + a >>= b; + b = !(a & 0x00000003) << 1; + n += b; + a >>= b; + return n + !(a & 0x00000001); +} + +__attribute__((weak)) int +__ctzdi2(arith64_u64 a) +{ + int b, n = 0; + b = !(a & 0x00000000ffffffffULL) << 5; + n += b; + a >>= b; + b = !(a & 0x000000000000ffffULL) << 4; + n += b; + a >>= b; + b = !(a & 0x00000000000000ffULL) << 3; + n += b; + a >>= b; + b = !(a & 0x000000000000000fULL) << 2; + n += b; + a >>= b; + b = !(a & 0x0000000000000003ULL) << 1; + n += b; + a >>= b; + return n + !(a & 0x0000000000000001ULL); +} + +// Calculate both the quotient and remainder of the unsigned division of a by +// b. The return value is the quotient, and the remainder is placed in variable +// pointed to by c (if it's not NULL). +__attribute__((weak)) arith64_u64 +__divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c) +{ + if (b > a) // divisor > numerator? + { + if (c) + *c = a; // remainder = numerator + return 0; // quotient = 0 + } + if (!arith64_hi(b)) // divisor is 32-bit + { + if (b == 0) // divide by 0 + { + volatile char x = 0; + x = 1 / x; // force an exception + } + if (b == 1) // divide by 1 + { + if (c) + *c = 0; // remainder = 0 + return a; // quotient = numerator + } + if (!arith64_hi(a)) // numerator is also 32-bit + { + if (c) // use generic 32-bit operators + *c = arith64_lo(a) % arith64_lo(b); + return arith64_lo(a) / arith64_lo(b); + } + } + + // let's do long division + char bits = __clzdi2(b) - __clzdi2(a) + + 1; // number of bits to iterate (a and b are non-zero) + arith64_u64 rem = a >> bits; // init remainder + a <<= 64 - bits; // shift numerator to the high bit + arith64_u64 wrap = 0; // start with wrap = 0 + while (bits-- > 0) // for each bit + { + rem = (rem << 1) | (a >> 63); // shift numerator MSB to remainder LSB + a = (a << 1) | (wrap & 1); // shift out the numerator, shift in wrap + wrap = ((arith64_s64)(b - rem - 1) + >> 63); // wrap = (b > rem) ? 0 : 0xffffffffffffffff (via sign + // extension) + rem -= b & wrap; // if (wrap) rem -= b + } + if (c) + *c = rem; // maybe set remainder + return (a << 1) | (wrap & 1); // return the quotient +} + +// Return the quotient of the signed division of a by b. +__attribute__((weak)) arith64_s64 +__divdi3(arith64_s64 a, arith64_s64 b) +{ + arith64_u64 q = __divmoddi4(arith64_abs(a), arith64_abs(b), (void *)0); + return arith64_neg(q, a ^ b); // negate q if a and b signs are different +} + +// Return the index of the least significant 1-bit in a, or the value zero if a +// is zero. The least significant bit is index one. +__attribute__((weak)) int +__ffsdi2(arith64_u64 a) +{ + return a ? __ctzdi2(a) + 1 : 0; +} + +// Return the result of logically shifting a right by b bits. +__attribute__((weak)) arith64_u64 +__lshrdi3(arith64_u64 a, int b) +{ + arith64_word w = { .u64 = a }; + + b &= 63; + + if (b >= 32) { + w.u32.lo = w.u32.hi >> (b - 32); + w.u32.hi = 0; + } + else if (b) { + w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b); + w.u32.hi >>= b; + } + return w.u64; +} + +// Return the remainder of the signed division of a by b. +__attribute__((weak)) arith64_s64 +__moddi3(arith64_s64 a, arith64_s64 b) +{ + arith64_u64 r; + __divmoddi4(arith64_abs(a), arith64_abs(b), &r); + return arith64_neg(r, a); // negate remainder if numerator is negative +} + +// Return the number of bits set in a. +__attribute__((weak)) int +__popcountsi2(arith64_u32 a) +{ + // collect sums into two low bytes + a = a - ((a >> 1) & 0x55555555); + a = ((a >> 2) & 0x33333333) + (a & 0x33333333); + a = (a + (a >> 4)) & 0x0F0F0F0F; + a = (a + (a >> 16)); + // add the bytes, return bottom 6 bits + return (a + (a >> 8)) & 63; +} + +// Return the number of bits set in a. +__attribute__((weak)) int +__popcountdi2(arith64_u64 a) +{ + // collect sums into two low bytes + a = a - ((a >> 1) & 0x5555555555555555ULL); + a = ((a >> 2) & 0x3333333333333333ULL) + (a & 0x3333333333333333ULL); + a = (a + (a >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + a = (a + (a >> 32)); + a = (a + (a >> 16)); + // add the bytes, return bottom 7 bits + return (a + (a >> 8)) & 127; +} + +// Return the quotient of the unsigned division of a by b. +__attribute__((weak)) arith64_u64 +__udivdi3(arith64_u64 a, arith64_u64 b) +{ + return __divmoddi4(a, b, (void *)0); +} + +// Return the remainder of the unsigned division of a by b. +__attribute__((weak)) arith64_u64 +__umoddi3(arith64_u64 a, arith64_u64 b) +{ + arith64_u64 r; + __divmoddi4(a, b, &r); + return r; +} + +__attribute__((weak)) arith64_u64 +__udivmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c) +{ + // +https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#index-_005f_005fudivmoddi4 + *c = __umoddi3(a, b); + return __udivdi3(a, b); +} +*/ + +/**************************************************** + * rwlock + ****************************************************/ + +/* +int +os_rwlock_init(korp_rwlock *rwlock) +{ + if (!rwlock) + return -1; + rwlock->readers = 0; + rwlock->writer = false; + return 0; +} + +int +os_rwlock_destroy(korp_rwlock *rwlock) +{ + if (!rwlock) + return -1; + return 0; +} + +int +os_rwlock_rdlock(korp_rwlock *rwlock) +{ + if (!rwlock) + return -1; + + // Wait until no writer + while (__atomic_load_n(&rwlock->writer, __ATOMIC_ACQUIRE)) + ; + + // Increment readers count + __atomic_fetch_add(&rwlock->readers, 1, __ATOMIC_ACQUIRE); + return 0; +} + +int +os_rwlock_wrlock(korp_rwlock *rwlock) +{ + if (!rwlock) + return -1; + + // Wait until no readers and no writer + while (__atomic_load_n(&rwlock->readers, __ATOMIC_ACQUIRE) > 0 + || __atomic_test_and_set(&rwlock->writer, __ATOMIC_ACQUIRE)) + ; + + return 0; +} + +int +os_rwlock_unlock(korp_rwlock *rwlock) +{ + if (!rwlock) + return -1; + + if (__atomic_load_n(&rwlock->writer, __ATOMIC_ACQUIRE)) { + // Writer releasing + __atomic_clear(&rwlock->writer, __ATOMIC_RELEASE); + } + else { + // Reader releasing + __atomic_fetch_sub(&rwlock->readers, 1, __ATOMIC_RELEASE); + } + return 0; +} +*/ + +/**************************************************** + * Section 1 * + * Interfaces required by the runtime * + ****************************************************/ + +/** + * Initialize the platform internal resources if needed, + * this function is called by wasm_runtime_init() and + * wasm_runtime_full_init() + * + * @return 0 if success + */ + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{ +} + +/** + ******** memory allocator APIs ********** + */ + +void * +os_malloc(unsigned size) +{ + return NULL; +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return NULL; +} + +void +os_free(void *ptr) +{ +} + +/** + * Note: the above APIs can simply return NULL if wasm runtime + * isn't initialized with Alloc_With_System_Allocator. + * Refer to wasm_runtime_full_init(). + */ + +int +os_printf(const char *format, ...) +{ + return 0; +} + +int +os_vprintf(const char *format, va_list ap) +{ + return 0; +} + +/** + * Get microseconds after boot. + */ +uint64 +os_time_get_boot_us(void) +{ + return 0; +} + +/** + * Get thread-specific CPU-time clock in microseconds + */ +uint64 +os_time_thread_cputime_us(void) +{ + return 0; +} + +/** + * Get current thread id. + * Implementation optional: Used by runtime for logging only. + */ +korp_tid +os_self_thread(void) +{ + return 0; +} + +/** + * Get current thread's stack boundary address, used for runtime + * to check the native stack overflow. Return NULL if it is not + * easy to implement, but may have potential issue. + */ +uint8 * +os_thread_get_stack_boundary(void) +{ + return NULL; +} + +/** + * Set whether the MAP_JIT region write protection is enabled for this thread. + * Pass true to make the region executable, false to make it writable. + */ +void +os_thread_jit_write_protect_np(bool enabled) +{ +} + +/** + ************** mutext APIs *********** + * vmcore: Not required until pthread is supported by runtime + * app-mgr: Must be implemented + */ + +int +os_mutex_init(korp_mutex *mutex) +{ + return 0; +} + +int +os_mutex_destroy(korp_mutex *mutex) +{ + return 0; +} + +int +os_mutex_lock(korp_mutex *mutex) +{ + return 0; +} + +int +os_mutex_unlock(korp_mutex *mutex) +{ + return 0; +} diff --git a/core/shared/platform/baremetal/platform_internal.h b/core/shared/platform/baremetal/platform_internal.h new file mode 100644 index 00000000..8a4ae791 --- /dev/null +++ b/core/shared/platform/baremetal/platform_internal.h @@ -0,0 +1,78 @@ +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +// #include +// #include +#include +#include +#include +#include +#include +#include +#include +// #include +#include +// #include +#include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_BAREMETAL +#define BH_PLATFORM_BAREMETAL +#endif + +#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024) +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; +typedef sem_t korp_sem; + +// typedef pthread_rwlock_t korp_rwlock; +typedef struct { + volatile uint32_t readers; + volatile bool writer; +} korp_rwlock; + +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; + +static inline os_file_handle +os_get_invalid_handle(void) +{ + return -1; +} + +static inline int +os_getpagesize() +{ + // TODO: What pagesize? + return 4096; +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ diff --git a/core/shared/platform/baremetal/shared_platform.cmake b/core/shared/platform/baremetal/shared_platform.cmake new file mode 100644 index 00000000..a123d693 --- /dev/null +++ b/core/shared/platform/baremetal/shared_platform.cmake @@ -0,0 +1,12 @@ +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_BAREMETAL) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) +set (PLATFORM_SHARED_SOURCE ${source_all}) + +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/baremetal/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})