From 9735c425be4313c7dd450841669046a1248bd52e Mon Sep 17 00:00:00 2001 From: Lucas Pluvinage Date: Tue, 25 Jun 2019 15:23:28 +0200 Subject: [PATCH] add esp32 target --- .gitignore | 1 + config.in/Makefile.ESP32.xtensa | 107 ++++++++++++++++ config.in/m.xtensa.h | 12 ++ nolibc/Makefile | 2 +- nolibc/dtoa.c | 8 +- nolibc/include/endian.h | 2 +- nolibc/include/limits.h | 3 + nolibc/include/math.h | 1 - nolibc/sysdeps_esp32.c | 210 ++++++++++++++++++++++++++++++++ nolibc/vfprintf.c | 9 +- 10 files changed, 348 insertions(+), 7 deletions(-) create mode 100644 config.in/Makefile.ESP32.xtensa create mode 100644 config.in/m.xtensa.h delete mode 100644 nolibc/include/math.h create mode 100644 nolibc/sysdeps_esp32.c diff --git a/.gitignore b/.gitignore index b7a08b9f..de2b8d51 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ flags/cflags flags/cflags.tmp flags/libs flags/libs.tmp +*.o diff --git a/config.in/Makefile.ESP32.xtensa b/config.in/Makefile.ESP32.xtensa new file mode 100644 index 00000000..a32b0563 --- /dev/null +++ b/config.in/Makefile.ESP32.xtensa @@ -0,0 +1,107 @@ +# generated by ./configure -lto -flambda -target xtensa-esp32-elf -target-bindir . +CONFIGURE_ARGS=-lto -flambda -target xtensa-esp32-elf -target-bindir . +PREFIX=/usr/local +BINDIR=$(PREFIX)/bin +LIBDIR=$(PREFIX)/lib/ocaml +STUBLIBDIR=$(LIBDIR)/stublibs +MANDIR=$(PREFIX)/man +MANEXT=1 +TARGET_BINDIR=. +RANLIB=xtensa-esp32-elf-ranlib +RANLIBCMD=xtensa-esp32-elf-ranlib +ARCMD=xtensa-esp32-elf-ar +HASHBANGSCRIPTS=true +UNIX_OR_WIN32=unix +UNIXLIB=unix +GRAPHLIB=graph +PTHREAD_LINK= +PTHREAD_CAML_LINK= +X11_INCLUDES=not found +X11_LINK=not found +LIBBFD_LINK= +LIBBFD_INCLUDE= +CC=xtensa-esp32-elf-gcc +CPP=xtensa-esp32-elf-cpp +CFLAGS=-nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--start-group -lgcc -lstdc++ -lgcov -Wl,--end-group -Wl,-EL -Os -fno-strict-aliasing -fwrapv -mlongcalls -Wall +CPPFLAGS=-Os -D_FILE_OFFSET_BITS=64 -DCAML_NAME_SPACE +OCAMLC_CFLAGS=-nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--start-group -lgcc -lstdc++ -lgcov -Wl,--end-group -Wl,-EL -Os -fno-strict-aliasing -fwrapv -mlongcalls +OCAMLC_CPPFLAGS=-Os -D_FILE_OFFSET_BITS=64 +LDFLAGS=-nostdlib -lgcc -lm +BYTECCLIBS= -lm +RPATH= +EXE= +EMPTY= +OUTPUTEXE=-o $(EMPTY) +SUPPORTS_SHARED_LIBRARIES=false +SHAREDCCCOMPOPTS= +MKSHAREDLIBRPATH= +NATDYNLINKOPTS= +SYSLIB=-l$(1) +#ml let syslib x = "-l"^x;; + +### How to build a static library +MKLIB=rm -f $(1) && xtensa-esp32-elf-ar rc $(1) $(2) && xtensa-esp32-elf-ranlib $(1) +#ml let mklib out files opts = (* "" *) +#ml Printf.sprintf "xtensa-esp32-elf-ar rc %s %s %s && xtensa-esp32-elf-ranlib %s" +#ml out opts files out;; +ARCH=xtensa +MODEL=default +SYSTEM=elf +OCAMLOPT_CFLAGS=-nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--start-group -lgcc -lstdc++ -lgcov -Wl,--end-group -Wl,-EL -Os -fno-strict-aliasing -fwrapv -mlongcalls +OCAMLOPT_CPPFLAGS=-Os -D_FILE_OFFSET_BITS=64 +NATIVECCPROFOPTS= +NATIVECCLIBS= -lm +ASM=xtensa-esp32-elf-as --text-section-literals --longcalls +ASPP=xtensa-esp32-elf-cc -c +ASPPPROFFLAGS=-DPROFILING +PROFILING=false +DYNLINKOPTS= +OTHERLIBRARIES=str +CC_PROFILE=-pg +SYSTHREAD_SUPPORT=false +PACKLD=xtensa-esp32-elf-ld -r -u caml_main -o\ $(EMPTY) +IFLEXDIR= +O=o +A=a +SO=so +EXT_OBJ=.o +OUTPUTOBJ=-o $(EMPTY) +EXT_ASM=.s +EXT_LIB=.a +EXT_DLL=.so +EXTRALIBS= +CCOMPTYPE=cc +TOOLCHAIN=cc +NATDYNLINK=false +CMXS=cmxa +MKEXE=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) +MKEXEDEBUGFLAG=-g +MKDLL=shared-libs-not-available +MKMAINDLL=shared-libs-not-available +RUNTIMED=true +RUNTIMEI=false +WITH_DEBUGGER= +WITH_OCAMLDOC= +ASM_CFI_SUPPORTED=false +WITH_FRAME_POINTERS=false +WITH_SPACETIME=false +ENABLE_CALL_COUNTS=true +WITH_PROFINFO=false +LIBUNWIND_AVAILABLE=false +LIBUNWIND_INCLUDE_FLAGS= +LIBUNWIND_LINK_FLAGS= +PROFINFO_WIDTH=0 +WITH_CPLUGINS=false +WITH_FPIC=false +TARGET=xtensa-esp32-elf +HOST=x86_64-unknown-linux-gnu +FLAMBDA=true +WITH_FLAMBDA_INVARIANTS=false +FORCE_SAFE_STRING=false +DEFAULT_SAFE_STRING=true +WINDOWS_UNICODE=0 +AFL_INSTRUMENT=false +MAX_TESTSUITE_DIR_RETRIES=0 +FLAT_FLOAT_ARRAY=true +LTO=true +AWK=awk diff --git a/config.in/m.xtensa.h b/config.in/m.xtensa.h new file mode 100644 index 00000000..6dcdf64b --- /dev/null +++ b/config.in/m.xtensa.h @@ -0,0 +1,12 @@ +#undef ARCH_SIXTYFOUR +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define SIZEOF_PTR 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_LONGLONG 8 +#define INT64_LITERAL(s) s ## LL +#define ARCH_ALIGN_DOUBLE +#define ARCH_ALIGN_INT64 +#define PROFINFO_WIDTH 0 +#define FLAT_FLOAT_ARRAY +#define OCAML_OS_TYPE "freestanding" \ No newline at end of file diff --git a/nolibc/Makefile b/nolibc/Makefile index 45460aa0..eb667068 100644 --- a/nolibc/Makefile +++ b/nolibc/Makefile @@ -6,7 +6,7 @@ ifeq ($(SYSDEP_OBJS),) endif CC=cc -CFLAGS=-O2 -std=c99 -Wall -Wno-parentheses -Werror +CFLAGS=-O2 -Wall -Wno-parentheses -Werror CFLAGS+=$(FREESTANDING_CFLAGS) OBJS=ctype.o \ diff --git a/nolibc/dtoa.c b/nolibc/dtoa.c index bc9efebc..f6a0c6de 100644 --- a/nolibc/dtoa.c +++ b/nolibc/dtoa.c @@ -21,7 +21,7 @@ * ocaml-freestanding. */ -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || defined(__xtensa__) #define IEEE_8087 #define Long int #else @@ -360,7 +360,11 @@ static double private_mem[PRIVATE_mem], *pmem_next = private_mem; #endif /* Bad_float_h */ #ifndef __MATH_H__ -#include "math.h" +#if defined(__x86_64__) || defined(__aarch64__) +#include "openlibm.h" +#else +#include +#endif #endif #ifdef __cplusplus diff --git a/nolibc/include/endian.h b/nolibc/include/endian.h index 17e9371f..5a85881c 100644 --- a/nolibc/include/endian.h +++ b/nolibc/include/endian.h @@ -3,7 +3,7 @@ #define __LITTLE_ENDIAN 1234 #define __BIG_ENDIAN 4321 -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || defined(__xtensa__) #define __BYTE_ORDER __LITTLE_ENDIAN #else #error Unsupported architecture diff --git a/nolibc/include/limits.h b/nolibc/include/limits.h index c4f2b2a6..47576174 100644 --- a/nolibc/include/limits.h +++ b/nolibc/include/limits.h @@ -10,6 +10,9 @@ #if defined(__x86_64__) || defined(__aarch64__) #define LONG_MAX 0x7fffffffffffffffL #define LLONG_MAX 0x7fffffffffffffffLL +#elif defined(__xtensa__) +#define LONG_MAX INT_MAX +#define LLONG_MAX 0x7fffffffffffffffLL #else #error Unsupported architecture #endif diff --git a/nolibc/include/math.h b/nolibc/include/math.h deleted file mode 100644 index a228a4fa..00000000 --- a/nolibc/include/math.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/nolibc/sysdeps_esp32.c b/nolibc/sysdeps_esp32.c new file mode 100644 index 00000000..b30a5a6b --- /dev/null +++ b/nolibc/sysdeps_esp32.c @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Output a char to uart, which uart to output(which is in uart module in ROM) is not in scope of the function. + * Can not print float point data format, or longlong data format + * + * @param char c : char to output. + * + * @return None + */ +void ets_write_char_uart(char c); + + +/** + * @brief Printf the strings to uart or other devices, similar with printf, simple than printf. + * Can not print float point data format, or longlong data format. + * So we maybe only use this in ROM. + * + * @param const char *fmt : See printf. + * + * @param ... : See printf. + * + * @return int : the length printed to the output device. + */ +int ets_printf(const char *fmt, ...); + + +void esp32_print(const char* s, size_t l) { + for (int i=0;iwrite(stream, string, strlen(string)); +} + +/* + * Global errno lives in this module. + */ +// newlib's libm uses __errno; +int errno; +int* __errno() { + return &errno; +}; + + +/* + * Standard output and error "streams". + */ +static size_t console_write(FILE *f __attribute__((unused)), const char *s, + size_t l) +{ + esp32_print(s, l); + return l; +} + +static FILE console = { .write = console_write }; +FILE *stderr = &console; +FILE *stdout = &console; + +ssize_t write(int fd, const void *buf, size_t count) +{ + if (fd == 1 || fd == 2) { + esp32_print(buf, count); + return count; + } + errno = ENOSYS; + return -1; +} + + +int esp_cpu_in_ocd_debug_mode() /* from IDF cpu_util.c */ +{ + int dcr; + int reg=0x10200C; //DSRSET register + asm("rer %0,%1":"=r"(dcr):"r"(reg)); + return (dcr&0x1); +} + + +void exit(int status) +{ + while(1); +} + +void abort(void) /* from IDF bootloader_init.c */ +{ + ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3); + + if (esp_cpu_in_ocd_debug_mode()) { + __asm__ ("break 0,0"); + } + while (1); +} + +/* + * System time. + * FIXME: no rtc in spike/qemu + * returns a fake value + */ + +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + esp32_print("gettimeofday() not supported on risc-v\n", 39); + if (tv != NULL) { + memset(tv, 0, sizeof(*tv)); + } + if (tz != NULL) { + memset(tz, 0, sizeof(*tz)); + } + return 0; +} + +clock_t times(struct tms *buf) +{ + memset(buf, 0, sizeof(*buf)); + return (clock_t)0; +} + +static uintptr_t sbrk_start; +static uintptr_t sbrk_end; +static uintptr_t sbrk_cur; + +/* + * This is to be called by the bootcode before handing of + * control via caml_startup(char**) + * + * XXX: There is intentionally no public prototype for this function. There + * should really be a caml_freestanding_startup(), but I'm lazy and don't have + * a proper place to put it in the build system right now. + */ +void _nolibc_init(uintptr_t heap_start, uintptr_t heap_size) +{ + sbrk_start = sbrk_cur = heap_start; + sbrk_end = heap_start + heap_size; +} + +/* + * Called by dlmalloc to allocate or free memory. + */ +void *sbrk(intptr_t increment) +{ + uintptr_t prev, brk; + prev = brk = sbrk_cur; + + /* + * dlmalloc guarantees increment values less than half of size_t, so this + * is safe from overflow. + */ + brk += increment; + if (brk >= sbrk_end || brk < sbrk_start) + return (void *)-1; + + sbrk_cur = brk; + return (void *)prev; +} + +/* + * dlmalloc configuration: + */ + +/* + * DEBUG not defined and assertions compiled out corresponds to the default + * recommended configuration (see documentation below). If you need to debug + * dlmalloc on Solo5 then define DEBUG to `1' here. + */ +#if defined(DEBUG) && (DEBUG) +#define ABORT_ON_ASSERT_FAILURE 0 +#else +#undef assert +#define assert(x) +#define NO_MALLINFO 1 +#endif + +#undef WIN32 +#define HAVE_MMAP 0 +#define HAVE_MREMAP 0 +#define MMAP_CLEARS 0 +#define NO_MALLOC_STATS 1 +#define LACKS_FCNTL_H +#define LACKS_SYS_PARAM_H +#define LACKS_SYS_MMAN_H +#define LACKS_STRINGS_H +#define LACKS_SYS_TYPES_H +#define LACKS_SCHED_H +#define LACKS_TIME_H +#define MALLOC_FAILURE_ACTION +#define USE_LOCKS 0 + +/* disable null-pointer-arithmetic warning on clang */ +#if defined(__clang__) && __clang_major__ >= 6 +#pragma clang diagnostic ignored "-Wnull-pointer-arithmetic" +#endif + +/* inline the dlmalloc implementation into this module */ +#include "dlmalloc.i" + +/* + * When adding new functions to this module, add them BEFORE the "dlmalloc + * configuration" comment above, not here. + */ diff --git a/nolibc/vfprintf.c b/nolibc/vfprintf.c index 7aff7412..32cdd412 100644 --- a/nolibc/vfprintf.c +++ b/nolibc/vfprintf.c @@ -4,10 +4,15 @@ #include #include #include -#include #include #include +#if defined(__x86_64__) || defined(__aarch64__) +#include "openlibm.h" +#else +#include +#endif + /* Some useful macros */ #define MAX(a,b) ((a)>(b) ? (a) : (b)) @@ -362,7 +367,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t) if (z>d+1) z=d+1; } for (; z>a && !z[-1]; z--); - + if ((t|32)=='g') { if (!p) p++; if (p>e && e>=-4) {