Skip to content

riscv: trap reserved C.LUI/C.ADDI16SP encodings instead of mis-decoding them - #286

Merged
LekKit merged 1 commit into
LekKit:stagingfrom
carlosqwqqwq:fix/c-lui-reserved-trap
Aug 13, 2026
Merged

riscv: trap reserved C.LUI/C.ADDI16SP encodings instead of mis-decoding them#286
LekKit merged 1 commit into
LekKit:stagingfrom
carlosqwqqwq:fix/c-lui-reserved-trap

Conversation

@carlosqwqqwq

@carlosqwqqwq carlosqwqqwq commented Aug 12, 2026

Copy link
Copy Markdown

Fix: trap reserved C.LUI/C.ADDI16SP and C.ADDIW rd=x0 encodings

Problem

riscv_emulate_c_c1() in src/cpu/riscv_compressed.h falls through from the
reserved c.lui/c.addi16sp/c.mop code points into the c.misc-alu
decoder, executing reserved encodings as c.srli/c.srai/c.andi/c.sub-
family instructions. The RV64 c.addiw rd == x0 code points are also
reserved per the spec ("valid only when rd != x0") and fell through the same
way.

Change

Both affected paths now return explicitly instead of falling through:

  • case 0x01 (RV64): c.addiw with rd == x0 (reserved) -> riscv_illegal_insn()
  • case 0x03: c.lui/c.addi16sp with nzimm == 0 that is not a valid c.mop.N
    -> riscv_illegal_insn()

Verification

  • 24 reserved c.lui-slot encodings: trap on native RISC-V hardware (SIGILL), QEMU
    (SIGILL), and now RVVM (both JIT and interpreter).
  • RV64 c.addiw x0, imm reserved encodings: now raise an illegal-instruction
    trap, matching the spec and QEMU (c64_illegal).
  • Regression: c.lui x0, 1 hint, c.mop.N (Zcmop), c.addiw with rd != 0,
    and all other C1 encodings still execute correctly.

Fixes #284.

@LekKit

LekKit commented Aug 12, 2026

Copy link
Copy Markdown
Owner

How come is c.addiw with rd = 0 a valid instruction? The documentation says:

C.ADDIW is only valid when rd≠x0; the code points with rd=x0 are reserved.

https://docs.riscv.org/reference/isa/v20260120/unpriv/c-st-ext.html#27-1-5-2-integer-register-immediate-operations

@LekKit

LekKit commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Other than that, the fix is sound. Previously both cases fell through into riscv_illegal_insn(vm, insn);, but the interpreter code was moved around and now incorrectly decodes them

…ng them

riscv_emulate_c_c1() falls through from the reserved c.lui/c.addi16sp
code points (nzimm == 0, not a valid c.mop.N) into the c.misc-alu
decoder, executing reserved encodings as c.srli/c.srai/c.andi/c.sub
instructions. The RV64 c.addiw rd == x0 code points are also reserved
per the spec ("valid only when rd != x0") and were falling through the
same way.

Both paths now return explicitly: the c.lui/c.addi16sp reserved slot
raises an illegal-instruction trap, and c.addiw rd == x0 raises an
illegal-instruction trap instead of being executed or treated as a
HINT.
@carlosqwqqwq
carlosqwqqwq force-pushed the fix/c-lui-reserved-trap branch from b11a8aa to 47c19fe Compare August 13, 2026 01:53
@carlosqwqqwq

Copy link
Copy Markdown
Author

You are right - thank you for the catch. I checked the spec: C.ADDIW is valid only when rd != x0; the rd == x0 code points are reserved (not HINTs), and QEMU decodes them as c64_illegal. I have updated the patch so c.addiw rd == x0 now raises an illegal-instruction trap instead of being treated as a no-op, and force-pushed. The c.lui/c.addi16sp nzimm == 0 slot (the main subject of the PR) is unchanged.

@LekKit
LekKit merged commit 33ea63a into LekKit:staging Aug 13, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RVVM executes reserved C.LUI/C.ADDI16SP and C.ADDIW rd=x0 encodings

2 participants