diff options
Diffstat (limited to 'fw')
-rw-r--r-- | fw/Makefile | 7 | ||||
-rw-r--r-- | fw/musl_include_shims/bits/alltypes.h | 23 | ||||
-rw-r--r-- | fw/musl_include_shims/endian.h | 80 | ||||
-rw-r--r-- | fw/musl_include_shims/features.h | 40 | ||||
-rw-r--r-- | fw/musl_include_shims/fp_arch.h | 6 | ||||
-rw-r--r-- | fw/musl_include_shims/libm.h | 270 |
6 files changed, 425 insertions, 1 deletions
diff --git a/fw/Makefile b/fw/Makefile index d4c4678..0a83aa2 100644 --- a/fw/Makefile +++ b/fw/Makefile @@ -6,6 +6,7 @@ CMSIS_DEVICE_DIR ?= upstream/st-cmsis-f0 CMSIS_CORE_DIR ?= upstream/cmsis-core HAL_DIR ?= upstream/st-hal-f0 ST_USBD_DIR ?= upstream/st-usb-device +MUSL_DIR ?= upstream/musl ######################################################################################################################## # Sources @@ -20,6 +21,9 @@ C_SOURCES := src/main.c \ src/usbd_hid.c \ src/system_stm32f0xx.c +C_SOURCES += $(MUSL_DIR)/src/string/memset.c \ + $(MUSL_DIR)/src/string/memcpy.c + C_SOURCES += $(HAL_DIR)/Src/stm32f0xx_ll_usb.c \ $(HAL_DIR)/Src/stm32f0xx_hal_adc.c \ $(HAL_DIR)/Src/stm32f0xx_hal_adc_ex.c \ @@ -73,7 +77,8 @@ CFLAGS += -I$(BUILDDIR) \ -I$(CMSIS_CORE_DIR) \ -I$(HAL_DIR)/Inc \ -I$(ST_USBD_DIR)/Core/Inc \ - -I$(ST_USBD_DIR)/Class/HID/Inc + -I$(ST_USBD_DIR)/Class/HID/Inc \ + -Imusl_include_shims # for musl CFLAGS += -Dhidden= diff --git a/fw/musl_include_shims/bits/alltypes.h b/fw/musl_include_shims/bits/alltypes.h new file mode 100644 index 0000000..581ca85 --- /dev/null +++ b/fw/musl_include_shims/bits/alltypes.h @@ -0,0 +1,23 @@ + +/* shim file for musl */ + +#ifndef __MUSL_SHIM_BITS_ALLTYPES_H__ +#define __MUSL_SHIM_BITS_ALLTYPES_H__ + +#define _REDIR_TIME64 1 +#define _Addr int +#define _Int64 long long +#define _Reg int + +#define __BYTE_ORDER 1234 + +#define __LONG_MAX 0x7fffffffL + +#ifndef __cplusplus +typedef unsigned wchar_t; +#endif + +typedef float float_t; +typedef double double_t; + +#endif /* __MUSL_SHIM_BITS_ALLTYPES_H__ */ diff --git a/fw/musl_include_shims/endian.h b/fw/musl_include_shims/endian.h new file mode 100644 index 0000000..172c432 --- /dev/null +++ b/fw/musl_include_shims/endian.h @@ -0,0 +1,80 @@ +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include <features.h> + +#define __NEED_uint16_t +#define __NEED_uint32_t +#define __NEED_uint64_t + +#include <bits/alltypes.h> + +#define __PDP_ENDIAN 3412 + +#define BIG_ENDIAN __BIG_ENDIAN +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +static __inline uint16_t __bswap16(uint16_t __x) +{ + return __x<<8 | __x>>8; +} + +static __inline uint32_t __bswap32(uint32_t __x) +{ + return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; +} + +static __inline uint64_t __bswap64(uint64_t __x) +{ + return __bswap32(__x)+0ULL<<32 | __bswap32(__x>>32); +} + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobe16(x) __bswap16(x) +#define be16toh(x) __bswap16(x) +#define htobe32(x) __bswap32(x) +#define be32toh(x) __bswap32(x) +#define htobe64(x) __bswap64(x) +#define be64toh(x) __bswap64(x) +#define htole16(x) (uint16_t)(x) +#define le16toh(x) (uint16_t)(x) +#define htole32(x) (uint32_t)(x) +#define le32toh(x) (uint32_t)(x) +#define htole64(x) (uint64_t)(x) +#define le64toh(x) (uint64_t)(x) +#else +#define htobe16(x) (uint16_t)(x) +#define be16toh(x) (uint16_t)(x) +#define htobe32(x) (uint32_t)(x) +#define be32toh(x) (uint32_t)(x) +#define htobe64(x) (uint64_t)(x) +#define be64toh(x) (uint64_t)(x) +#define htole16(x) __bswap16(x) +#define le16toh(x) __bswap16(x) +#define htole32(x) __bswap32(x) +#define le32toh(x) __bswap32(x) +#define htole64(x) __bswap64(x) +#define le64toh(x) __bswap64(x) +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define betoh16(x) __bswap16(x) +#define betoh32(x) __bswap32(x) +#define betoh64(x) __bswap64(x) +#define letoh16(x) (uint16_t)(x) +#define letoh32(x) (uint32_t)(x) +#define letoh64(x) (uint64_t)(x) +#else +#define betoh16(x) (uint16_t)(x) +#define betoh32(x) (uint32_t)(x) +#define betoh64(x) (uint64_t)(x) +#define letoh16(x) __bswap16(x) +#define letoh32(x) __bswap32(x) +#define letoh64(x) __bswap64(x) +#endif +#endif + +#endif diff --git a/fw/musl_include_shims/features.h b/fw/musl_include_shims/features.h new file mode 100644 index 0000000..85cfb72 --- /dev/null +++ b/fw/musl_include_shims/features.h @@ -0,0 +1,40 @@ +#ifndef _FEATURES_H +#define _FEATURES_H + +#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE 1 +#endif + +#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) +#define _BSD_SOURCE 1 +#endif + +#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ + && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ + && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) +#define _BSD_SOURCE 1 +#define _XOPEN_SOURCE 700 +#endif + +#if __STDC_VERSION__ >= 199901L +#define __restrict restrict +#elif !defined(__GNUC__) +#define __restrict +#endif + +#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) +#define __inline inline +#elif !defined(__GNUC__) +#define __inline +#endif + +#if __STDC_VERSION__ >= 201112L +#elif defined(__GNUC__) +#define _Noreturn __attribute__((__noreturn__)) +#else +#define _Noreturn +#endif + +#define __REDIR(x,y) __typeof__(x) x __asm__(#y) + +#endif diff --git a/fw/musl_include_shims/fp_arch.h b/fw/musl_include_shims/fp_arch.h new file mode 100644 index 0000000..f5bab6d --- /dev/null +++ b/fw/musl_include_shims/fp_arch.h @@ -0,0 +1,6 @@ +#ifndef __MUSL_SHIM_FP_ARCH_H__ +#define __MUSL_SHIM_FP_ARCH_H__ + +#define hidden + +#endif /* __MUSL_SHIM_FP_ARCH_H__ */ diff --git a/fw/musl_include_shims/libm.h b/fw/musl_include_shims/libm.h new file mode 100644 index 0000000..d48135d --- /dev/null +++ b/fw/musl_include_shims/libm.h @@ -0,0 +1,270 @@ +#ifndef _LIBM_H +#define _LIBM_H + +#include <stdint.h> +#include <float.h> +#include <math.h> +#include <endian.h> +#include "fp_arch.h" + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t m; + uint16_t se; + } i; +}; +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +/* This is the m68k variant of 80-bit long double, and this definition only works + * on archs where the alignment requirement of uint64_t is <= 4. */ +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t pad; + uint64_t m; + } i; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct { + uint64_t hi; + uint64_t lo; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +/* Support non-nearest rounding mode. */ +#define WANT_ROUNDING 1 +/* Support signaling NaNs. */ +#define WANT_SNAN 0 + +#if WANT_SNAN +#error SNaN is unsupported +#else +#define issignalingf_inline(x) 0 +#define issignaling_inline(x) 0 +#endif + +#ifndef TOINT_INTRINSICS +#define TOINT_INTRINSICS 0 +#endif + +#if TOINT_INTRINSICS +/* Round x to nearest int in all rounding modes, ties have to be rounded + consistently with converttoint so the results match. If the result + would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ +static double_t roundtoint(double_t); + +/* Convert x to nearest int in all rounding modes, ties have to be rounded + consistently with roundtoint. If the result is not representible in an + int32_t then the semantics is unspecified. */ +static int32_t converttoint(double_t); +#endif + +/* Helps static branch prediction so hot path can be better optimized. */ +#ifdef __GNUC__ +#define predict_true(x) __builtin_expect(!!(x), 1) +#define predict_false(x) __builtin_expect(x, 0) +#else +#define predict_true(x) (x) +#define predict_false(x) (x) +#endif + +/* Evaluate an expression as the specified type. With standard excess + precision handling a type cast or assignment is enough (with + -ffloat-store an assignment is required, in old compilers argument + passing and return statement may not drop excess precision). */ + +static inline float eval_as_float(float x) +{ + float y = x; + return y; +} + +static inline double eval_as_double(double x) +{ + double y = x; + return y; +} + +/* fp_barrier returns its input, but limits code transformations + as if it had a side-effect (e.g. observable io) and returned + an arbitrary value. */ + +#ifndef fp_barrierf +#define fp_barrierf fp_barrierf +static inline float fp_barrierf(float x) +{ + volatile float y = x; + return y; +} +#endif + +#ifndef fp_barrier +#define fp_barrier fp_barrier +static inline double fp_barrier(double x) +{ + volatile double y = x; + return y; +} +#endif + +#ifndef fp_barrierl +#define fp_barrierl fp_barrierl +static inline long double fp_barrierl(long double x) +{ + volatile long double y = x; + return y; +} +#endif + +/* fp_force_eval ensures that the input value is computed when that's + otherwise unused. To prevent the constant folding of the input + expression, an additional fp_barrier may be needed or a compilation + mode that does so (e.g. -frounding-math in gcc). Then it can be + used to evaluate an expression for its fenv side-effects only. */ + +#ifndef fp_force_evalf +#define fp_force_evalf fp_force_evalf +static inline void fp_force_evalf(float x) +{ + volatile float y; + y = x; +} +#endif + +#ifndef fp_force_eval +#define fp_force_eval fp_force_eval +static inline void fp_force_eval(double x) +{ + volatile double y; + y = x; +} +#endif + +#ifndef fp_force_evall +#define fp_force_evall fp_force_evall +static inline void fp_force_evall(long double x) +{ + volatile long double y; + y = x; +} +#endif + +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ +} while(0) + +#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i +#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f +#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i +#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f + +#define EXTRACT_WORDS(hi,lo,d) \ +do { \ + uint64_t __u = asuint64(d); \ + (hi) = __u >> 32; \ + (lo) = (uint32_t)__u; \ +} while (0) + +#define GET_HIGH_WORD(hi,d) \ +do { \ + (hi) = asuint64(d) >> 32; \ +} while (0) + +#define GET_LOW_WORD(lo,d) \ +do { \ + (lo) = (uint32_t)asuint64(d); \ +} while (0) + +#define INSERT_WORDS(d,hi,lo) \ +do { \ + (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ +} while (0) + +#define SET_HIGH_WORD(d,hi) \ + INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) + +#define SET_LOW_WORD(d,lo) \ + INSERT_WORDS(d, asuint64(d)>>32, lo) + +#define GET_FLOAT_WORD(w,d) \ +do { \ + (w) = asuint(d); \ +} while (0) + +#define SET_FLOAT_WORD(d,w) \ +do { \ + (d) = asfloat(w); \ +} while (0) + +hidden int __rem_pio2_large(double*,double*,int,int,int); + +hidden int __rem_pio2(double,double*); +hidden double __sin(double,double,int); +hidden double __cos(double,double); +hidden double __tan(double,double,int); +hidden double __expo2(double); + +hidden int __rem_pio2f(float,double*); +hidden float __sindf(double); +hidden float __cosdf(double); +hidden float __tandf(double,int); +hidden float __expo2f(float); + +hidden int __rem_pio2l(long double, long double *); +hidden long double __sinl(long double, long double, int); +hidden long double __cosl(long double, long double); +hidden long double __tanl(long double, long double, int); + +hidden long double __polevll(long double, const long double *, int); +hidden long double __p1evll(long double, const long double *, int); + +hidden double __lgamma_r(double, int *); +hidden float __lgammaf_r(float, int *); + +/* error handling functions */ +hidden float __math_xflowf(uint32_t, float); +hidden float __math_uflowf(uint32_t); +hidden float __math_oflowf(uint32_t); +hidden float __math_divzerof(uint32_t); +hidden float __math_invalidf(float); +hidden double __math_xflow(uint32_t, double); +hidden double __math_uflow(uint32_t); +hidden double __math_oflow(uint32_t); +hidden double __math_divzero(uint32_t); +hidden double __math_invalid(double); + +#endif |