free little xtensa emulator. boots real esp-idf and arduino firmware on virtual esp32 and esp32-s3 hardware.
$ cmake -S . -B build && cmake --build build --target xtensa-emu -j # c17, cmake, openssl, zlib, and pthreads. $ ./build/xtensa-emu -q -s hello_world.elf -c 5000000 hello_world.bin I (0) cpu_start: Starting scheduler on PRO CPU. Hello world! $ FLEXE_ROMS=./roms MAX_UNMAPPED=0 REPS=5 ./scripts/bench-firmware.sh # release + lto; both engines must pass and produce the same uart digest: meshtastic 25.03× real-time nerdminer 12.84× real-time openhasp 8.31× real-time tasmota 8.29× real-time wled 2.32× real-time # same s3 image, same host, esp-emulator 0.48.0 vs flexe (2026-10-09): cpuburn 0.74s jit vs 13.91s official (1.21b insns, identical checksum)
traces hot basic blocks through conditional branches, chains them into long native runs (arm64 + x86-64), and constant-folds flash literal loads. cold code stays interpreted. no correctness cliff — unhandled instructions just run in the interpreter.
unmodified bruce, esp32 marauder, meshtastic, nerdminer, openhasp, tasmota, and wled images pass scripted hardware and service scenarios on both engines. pinned output digests catch a jit that produces the wrong result rather than no result.
integer and floating-point execution, register windows, loops, exceptions, and interrupts. target descriptors select esp32/lx6 or esp32-s3/lx7 geometry and supported behavior.
two guest cores take turns on one deterministic timeline, sharing memory and interrupts. retired instructions count work on both cores; idle jumps count only toward elapsed time.
rom functions (ets_printf, memcpy, sha/aes), freertos tasks/queues/semaphores, esp_timer callbacks, nvs, vfs/spiffs with host file backing, even lwip sockets bridged to the host network.
elf symbols, breakpoints, verbose + windowed traces, function-call trees, hierarchical traces for billion-cycle runs, checkpoints you can save and resume later.
plain c17, a switch-based interpreter, and hand-rolled jit backends. the implementation stays inspectable even as production firmware expands the hardware model.
functional hardware, with explicit limits. each firmware pass belongs to a pinned image and scenario; host-backed services and modeled controllers have separate support boundaries.
production benchmarks measured on apple silicon with a release, lto, host-native build. jit is on by default. real-time factor is measured against a 240 mhz esp32. the esp-emulator 0.48.0 head-to-head (2026-10-09, same s3 images, same host) is documented with the other dated results.