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..262b059a --- /dev/null +++ b/core/shared/platform/baremetal/platform_init.c @@ -0,0 +1,206 @@ +#include "platform_api_vmcore.h" + +// 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..5804efd0 --- /dev/null +++ b/core/shared/platform/baremetal/platform_internal.h @@ -0,0 +1,509 @@ +#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 pthread_rwlock_t korp_rwlock; +typedef sem_t korp_sem; + +typedef struct { + volatile uint32_t readers; + volatile bool writer; +} korp_rwlock; + +// int +// os_rwlock_init(korp_rwlock *rwlock); +// int +// os_rwlock_destroy(korp_rwlock *rwlock); +// int +// os_rwlock_rdlock(korp_rwlock *rwlock); +// int +// os_rwlock_wrlock(korp_rwlock *rwlock); +// int +// os_rwlock_unlock(korp_rwlock *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; +} + +// Memory + +// https://git.musl-libc.org/cgit/musl/tree/src/string/memcpy.c + +__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; +} + +// https://git.musl-libc.org/cgit/musl/tree/src/string/memmove.c + +__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; +} + +// https://git.musl-libc.org/cgit/musl/tree/src/string/memset.c + +__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; +} + +// Strings + +// https://github.com/zerovm/glibc/blob/master/string/strcmp.c + +__attribute__((weak)) int +strcmp(const char *s1, const char *s2) +{ + while (*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char *)s1 - *(const unsigned char *)s2; +} + +// Math + +// https://github.com/glitchub/arith64/blob/master/arith64.c + +#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. +arith64_s64 +__absvdi2(arith64_s64 a) +{ + return arith64_abs(a); +} + +// Return the result of shifting a left by b bits. +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. +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. +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); +} + +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. +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); +} + +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). +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. +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. +int +__ffsdi2(arith64_u64 a) +{ + return a ? __ctzdi2(a) + 1 : 0; +} + +// Return the result of logically shifting a right by b bits. +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. +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. +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. +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. +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. +arith64_u64 +__umoddi3(arith64_u64 a, arith64_u64 b) +{ + arith64_u64 r; + __divmoddi4(a, b, &r); + return r; +} + +// Stack protection (?) + +uint32_t +__stack_chk_fail_local() +{ + return 0; +} + +#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})