journal 2026-05-03

P46 - bitmanip but with a wart

p46riscvbitmanipautonomous-mode

Autonomous-mode rung. Pivoted from C extension (P46 in the original roadmap, multi-hour front-end rewrite) to Zba+Zbb because the latter is smaller and safer to do unsupervised. C is now P47.

What landed

13 single-cycle bitmanip ops in the chip’s ALU:

No new FSM states; all combinational ALU extensions. Decode predicates added to legal_op and legal_shift. About 100 lines of src/top.sv.

What didn’t

Hit a real bug I couldn’t pin down without supervision. With -march=...zbb... enabled in the toolchain, gcc-O2 auto-emits sext.b instructions in FreeRTOS internals. The chip then hangs after consumer prints ‘a’ - same symptom as the P42 gcc-emitted-j . collision, but with a different cause (we no longer have is_halt_loop).

The directed probe (which uses raw .insn r encoding for the 10 tested Zbb ops) PASSES. So the chip’s decode + ALU are good. But something in the gcc-emitted-sext.b → FreeRTOS interaction fails.

Diagnosis attempts:

What I didn’t have: a wave trace of the actual stuck instruction. Without that I’m guessing.

Pragmatic ship

P46 ships with -march=rv32ima_zba_zicsr_zifencei - no _zbb. The 13 Zbb ops are in the chip and accessible via explicit .insn r encoding (the probe proves this). gcc auto-emission of Zbb is disabled in our build. RV32IMAC + Zbb is on hold for a debugging follow-up rung.

This is the honest framing: “the RTL knows Zba+Zbb, the toolchain integration has one open issue, here’s what it is.” The user can pick this up with a wave-trace later.

Why this still counts as a rung

We’re closer to RV32IMAC than we were, even with the wart. And the wart is well-localised: one specific instruction (sext.b) emitted by gcc into one specific software environment (FreeRTOS).

Next

P47 (the C extension) was originally P46. Should be done supervised because the front-end rewrite has a lot of bug surface. Or fix the sext.b auto-emit issue first if motivated.