Zcmt is dictionary compression for call sites:
cm.jt / cm.jalt table jump Zcmt's cm.jt/cm.jalt (index<32 = jt, else jalt with ra link): fetch entry XLEN wide at jvt.base + index*(XLEN/8) - a second IMPLICIT INSTRUCTION FETCH (execute permission, data endianness, fence.i after table writes), then jump to entry & ~1. Faults report the table-jump PC in xEPC.
defined in ch. I·29 — open in glossary
replace 32-bit j/jal
and 64-bit auipc+jr/auipc+jalr sequences with a 16-bit index into a
256-entry, XLEN-wide function-address table. The linker builds the table;
each call site shrinks to two bytes.
Target computation: entry_addr = jvt.base + index × (XLEN/8), fetch the
XLEN-wide entry, clear bit 0, jump. Entries follow data endianness
(unlike normal instruction fetch, which is always little-endian).
The jvt CSR
jvt (0x017, URW)
Fault handling: the second fetch
Executing a table jump is two implicit instruction fetches — the 16-bit instruction, then the table entry, which the spec declares “an extension of the instruction itself”:
- Both require execute permission; read permission is irrelevant.
- A fault on either fetch reports xEPC = the table jump’s PC, xTVAL = the faulting fetch address, xCAUSE per the fault type.
- Debug triggers/breakpoints should ignore the second fetch.
- Writes to a table need
fence.ibefore table jumps may observe them (ch. I·5’s rule — this is instruction memory). Switchingjvtbetween tables that were already fenced needs no barrier.
Hardware Designer Notes
The table-entry fetch is the interesting RTL: it reuses the fetch path’s translation/PMP checks (execute, not read!) mid-execute-stage — closer to how Vol II’s SFENCE/translation machinery will feel than anything else in Volume I. If you build it, budget a dedicated fetch-like port or a stall into the icache path, and remember the entry is data-endian: on a bi-endian core the byte-swap mux keys off the DATA endianness control, not the fetch one.
Minimal Linux-boot hart MUST
- Check execute permission on the table-entry fetch and attribute its faults to the table-jump PC (xTVAL = table address)
- Fetch entries with DATA endianness; clear bit 0 of the target
- Implement jvt.mode 0 and WARL-readback discovery; keep jvt.base 64-byte aligned
- Honor fence.i as the table-update barrier
MAY simplify / trap-and-emulate
- Hardwire jvt if a fixed table serves your firmware use case
- Push the RAS on cm.jalt exactly as for jal ra
- Skip Zcmt on application-class cores — same profile exclusion as Zcmp
Check yourself — table jumps
1.A cm.jalt's table-entry fetch takes a page fault. What does the trap frame show?
2.How does one 8-bit index field encode both cm.jt and cm.jalt?
3.After the kernel updates a jump table in memory, what must happen before table jumps use it?
4.Why must jvt be saved/restored on context switches?