Fuzix for Pico Computer 2/3 v0.3 - native code generation
The compiler now generates native ARM code — and its output runs as ./prog.
# cc hello.c
# ./hello.bc
hello from Fuzix
cc still reads the same C89-plus dialect and still validates against gcc byte-for-byte (165 of 175 applicable c-testsuite tests, unchanged), but what it emits is no longer interpreted bytecode alone: every function the translator covers is compiled to ARM Thumb-2 machine code and runs on the metal, with the bytecode retained as a per-function fallback. Coverage is complete enough that whole real programs go fully native.
Measured on the Pico Computer 3, same programs, before → after:
| benchmark | v0.2 (interpreted) | v0.3 (native) |
|---|---|---|
| sieve of Eratosthenes | 3.85 s | 47 ms |
| fib(27) | 2.64 s | 71 ms |
| shellsort | 3.66 s | 74 ms |
| xorshift PRNG | 8.18 s | 57 ms |
| Dhrystone 2.1 | 3,900/s | 16,961/s |
| solar eclipse (3,200-line BASIC → C) | 9.19 s | 3.47 s |
For calibration, the same Dhrystone cross-compiled by arm-none-eabi-gcc as a native Fuzix binary runs at 379,000/s — the bytecode machine's compiler now stands within ~22× of a first-class optimizing compiler, from ~100× in v0.2. The eclipse figure beats MicroPython on the same silicon (8.77 s) and MMBasic (12.5 s) — a BASIC program machine-translated to C, compiled on this machine or off it, running faster than both interpreters.
Under the hood, in the order it happened: double-precision arithmetic moved to the RP2350's DCP coprocessor (benefits everything, BBC BASIC included); the code generator grew 64-bit and floating-point coverage, switch, struct copy, direct calls between native functions, and compare/branch fusion; the runtime binds every library call once instead of string-matching per call; and dead bytecode is reclaimed so full-native programs fit a 256 KiB process.
New: a PSRAM arena. A process can ask the kernel for a region of the 8 MiB PSRAM outside its own image — not counted against the process size, never copied on context switch, never swapped (PSRAMIOC_ALLOC/FREE/STAT on /dev/sys, 1 MiB pool by default, psram=<n>[K|M] at the bootdev prompt to retune). The compiler is its first client: cc2's tables live there, which is what lifted the on-board compiler to host-class capacity limits. Fork leaves an arena with the parent; exec and exit reclaim it.
New: #! execution. The kernel execs #!-marked files through /usr/bin/bcrun; cc marks and chmods its output, so compiled programs launch like any other binary. Older .bc files still run via bcrun prog.bc.
Also fixed along the way: a block-device bounds check that only covered the first sector of a transfer, warm-reset SD/flash/boot-state bugs that could brick a reset until reflash (three separate causes, all found and fixed), a latent truthiness bug on denormal comparison results, and %lld printing through a libc that reads long for ll.
Flash fuzix.uf2, write pc3-sd.img.gz (decompressed) to an SD card, and the samples in /root/cc are waiting. The manual is unchanged from v0.2; the new features are documented in the tree (PC3-PSRAM-ARENA.md, Applications/CC/PLAN-arm-backend.md).
🤖 Generated with Claude Code