Why can rd not be sp?
rd=x2 selects C.ADDI16SP, whose fields encode a stack-pointer increment; the ordinary C.LUI upper-constant formula does not apply.
RV32/RV64 C/Zca, 16-bit CI: place the nonzero 6-bit field in bits 17:12, clear the low 12 bits, and sign-extend bit 17 to XLEN.
Ordinary C.LUI uses the full five-bit rd field, selecting x1–x31 except x2. Interpret the nonzero six-bit field as signed -32–31, shift it left by 12, then sign-extend to XLEN; it corresponds to LUI. With a nonzero field, rd=x0 is a HINT and rd=x2 selects C.ADDI16SP, whose immediate layout differs and must not use the C.LUI calculation. Zero-field encodings are reserved; Zcmop uses the eight with rd=x1,x3,…,x15 for C.MOP.n.
Shows only official 16-bit fields, address/immediate calculation, and architectural state; it does not simulate a pipeline, cache, endianness implementation, or timing.
RV32 / RV64 C / Zca
RV32/RV64 C/Zca, 16-bit CI: place the nonzero 6-bit field in bits 17:12, clear the low 12 bits, and sign-extend bit 17 to XLEN.
RV32/RV64 C/Zca: c.lui x10, 1 writes 0x1000 to x10, with zero low 12 bits; old x10 is not a source.
rd=x2 selects C.ADDI16SP, whose fields encode a stack-pointer increment; the ordinary C.LUI upper-constant formula does not apply.
It is reserved for ordinary C.LUI. With Zcmop, the eight corresponding odd rd=x1…x15 encodings become C.MOP.n, which does not write registers.