Which registers can C.ADD use?
The CR-format rd and rs2 fields are full 5-bit fields, so the encoding can name registers x0-x31; regular C.ADD semantics require both rd and rs2 not to be x0.
Regular C.ADD adds rd and rs2 and writes the result to rd. CR format; both rd and rs2 must be nonzero.
C.ADD (CR format, with access to all 32 registers) adds rd and rs2 and writes the result to rd, equivalent to add rd, rd, rs2. Regular C.ADD requires rd!=x0 and rs2!=x0: with rs2=x0, rd!=x0 encodes C.JALR and rd=x0 encodes C.EBREAK. With nonzero rs2 and rd=x0, the encoding is normally a HINT; when Zihintntl is implemented, rs2=x2-x5 instead encode C.NTL.P1, C.NTL.PALL, C.NTL.S1, and C.NTL.ALL.
Decodes the real 16-bit CR or CI encoding and distinguishes normal instructions, HINTs, and shared encodings.
funct4, rd/rs1, rs2, and op together identify this 16-bit C.ADD instruction.
0x952E = 1001010100101110x[rd] ← old x[rd] + x[rs2] (write back only the low XLEN bits)
rd is both the first source and the destination: old x[rd] is read before the result overwrites it.
funct4=1001 and op=10; rd/rs1=x10, rs2=x11. Both are nonzero, so this is ordinary C.ADD.
Registers have not been read yet; x[rd] must not be overwritten.
No calculation yet; read both source values first.
No writeback yet; the architecturally visible x[rd] is still the old snapshot.
This animation shows only officially defined decode, register reads, arithmetic, and architectural state, not a particular implementation's pipeline, cache, prediction, or timing.
C.ADD uses the CR format and writes rd + rs2 back to rd; the regular C.ADD form requires both rd and rs2 not to be x0.
Understand this scenario with real code like «c.add x10, x11 # x10 += x11».
The CR-format rd and rs2 fields are full 5-bit fields, so the encoding can name registers x0-x31; regular C.ADD semantics require both rd and rs2 not to be x0.