Skip to content

pc3-v0.4: MMBasic self-hosts on the Pico Computer 3

Choose a tag to compare

@UKTailwind UKTailwind released this 01 Aug 11:49

Fuzix for the Pico Computer — pc3-v0.4

The machine now compiles MMBasic on its own. mmbc translates a BASIC
program to C, cc compiles it to native ARM, and the result runs as an
ordinary program — all on the PC3, no PC involved.

MMBasic self-hosting

# mmbc bench.bas
wrote bench.c
# cc bench.c
# ./bench.bc
Performance:    29649 grains

MMBasic itself scores about 12,000 grains on the same board at the same
clock.

The 3,200-line solar eclipse program — Bessel elements, lunar and solar
series — translates, compiles and runs on the machine, digit-identical
to MMBasic and MicroPython, in 3.24 s against MMBasic's 12.5 s and
MicroPython's 8.8 s.

mmbc on the board writes C for the board's own compiler by default
(--gcc for the host form). Coverage: 59 statements and 69 functions,
listed in Appendix C of the manual, generated from the translator's own
tables. It grows with each release and will never be complete.

Native code generation

cc2 translates each function to Thumb-2 for the Cortex-M33 and stores
it in the object; bcrun executes native and keeps the interpreter for
whatever did not translate. Dhrystone 2.1, compiled on the machine,
runs at 90,021/s — a quarter of the same benchmark cross-compiled by
gcc -O2 for the same chip.

New this release: push/op fusion (the left operand of a binary operator
stays in a register instead of round-tripping through memory), direct
DCP arithmetic, and the statement-seam rewrite — the last of which
shipped broken in development and is now correct, with a native gate to
keep it that way.

Compiled programs run directly: ./prog.bc.

Fixes worth naming

  • Compiling a large program crashed the machine. Both compiler
    passes are recursive descent and overflowed the 8 KB stack, silently,
    into their own BSS. Binaries can now ask for what they need through
    PT_GNU_STACK; cc1 and cc2 ask for 32 KB. Nothing else pays.
  • cc1 matched index lists without comparing their lengths — an
    out-of-bounds read that could hand back another type's array
    dimensions.
  • Multidimensional array parameters were wrong. int a[5][7] passed
    to a function decayed to the element pointer, so every store through
    it went elsewhere. Dhrystone had been failing its own self-check since
    the port began.
  • The USB keyboard. The LED report is a control transfer on EP0 —
    the endpoint enumeration also needs — and was issued inline from
    wherever a lock key was decoded. That wedged EP0: the keyboard worked
    until the next lock key, and from then on a device could attach but
    never enumerate. It now goes out from the poll loop, one transfer at a
    time.
  • One stray Return after answering the boot prompt: auto-repeat firing
    on a key whose release was never fetched.
  • The PSRAM disc refuses an out-of-range block instead of memcpy'ing
    into unmapped memory, and the fault dump prints the faulting address
    before the registers.

Also

The manual gains a chapter on mmbc with worked examples taken from
the machine, and PC3-IRQ-REVIEW.md records what this port's interrupt
handling actually does — the SDK's mechanisms work here, and hand-hooked
vectors should give way to them for peripherals.

Installing

  • fuzix.uf2 — flash as usual (BOOT + RESET, copy to the drive).
  • pc3-sd-cc.img.gz — write to an SD card of 128 MB or larger.
  • FUZIX-PC3-MANUAL.pdf — the manual.

Both the kernel and the card image are needed: the card carries the
compiler, and the kernel carries the loader that honours its stack
request.