nx_rv64c.nx
buildroot/runtime/nx_rv64c.nx
about
nx_rv64c.nx -- RV64C compressed-instruction decoder.
Given a 16-bit RV64C instruction, returns the 32-bit RV64I/M
equivalent so nx_rv64_sim can execute it via its existing decode
path. This is the minimal change that lets us run binaries
produced by stock gcc / clang -- both emit C-extension
instructions whenever -march has +c (which is the default on
most distros).
Without this, every other ld/st/branch in a real binary aborts
the simulator. With it, the sim runs unmodified RV64GC code.
Encoding reference: RISC-V Unprivileged Spec v20191213-Compressed
chapter 16 (https://riscv.org/specifications/), Table 16.4 / 16.5.
Layout:
bits[1:0] = quadrant (00 / 01 / 10 / 11=non-compressed)
bits[15:13] = funct3 within quadrant
Approach:
- One dispatcher per quadrant (q0_decode / q1_decode / q2_decode)
- Each dispatcher pulls funct3 + relevant operand fields,
reconstructs a 32-bit RV64I instruction word using the
standard R/I/S/B/U/J encoders below.
- Helper register-mapping: c.* "rs1'" / "rs2'" / "rd'" fields
are 3-bit and map to x8..x15 (s0/s1/a0..a5).
Returns the expanded 32-bit instruction on success, or 0 on
"illegal compressed insn" (which the caller should treat as a
trap / fault). We never return 0 for valid c.nop (which expands
to addi x0, x0, 0 = 0x00000013).
dependencies 1 imports · 2 importers
imports: syscalls.nx
imported by: nx_dis_c.nxnx_rv64_sim.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| none |
functions
| 43 | func nx_c_field(insn: i64, hi: i64, lo: i64) -> i64 |
| 49 | func nx_c_reg3(r3: i64) -> i64 |
| 55 | func nx_c_enc_r(opcode: i64, rd: i64, funct3: i64, rs1: i64, rs2: i64, funct7: i64) -> i64 |
| 64 | func nx_c_enc_i(opcode: i64, rd: i64, funct3: i64, rs1: i64, imm: i64) -> i64 |
| 72 | func nx_c_enc_s(opcode: i64, funct3: i64, rs1: i64, rs2: i64, imm: i64) -> i64 |
| 83 | func nx_c_enc_b(opcode: i64, funct3: i64, rs1: i64, rs2: i64, imm: i64) -> i64 called by 1: nx_c_decode_q1 |
| 98 | func nx_c_enc_j(opcode: i64, rd: i64, imm: i64) -> i64 called by 1: nx_c_decode_q1 |
| 111 | func nx_c_enc_u(opcode: i64, rd: i64, imm: i64) -> i64 called by 1: nx_c_decode_q1 |
| 120 | func nx_c_sext(value: i64, bits: i64) -> i64 called by 1: nx_c_decode_q1 |
| 130 | func nx_c_decode_q0(insn: i64) -> i64 |
| 184 | func nx_c_decode_q1(insn: i64) -> i64 |
| 307 | func nx_c_decode_q2(insn: i64) -> i64 |
| 382 | func nx_rv64c_decode(insn: i64) -> i64 |
| 391 | func nx_rv64c_is_compressed(low_bits: i64) -> i64 called by 1: main |
| 398 | func main() -> i64 |