RISC-V ISA Strings: Diagnose CSR Instructions Rejected After a Toolchain Upgrade
Startup assembly that previously accepted a CSR instruction can fail after a RISC-V toolchain upgrade even when the board has not changed. One possible cause is a changed interpretation of the declared ISA: CSR access and instruction-fetch fencing are separate named extensions in newer specifications.
Investigate the instruction, effective ISA string and specification selection before replacing the board support package or broadening the target to every available extension.
Identify which extension owns the rejected instruction
The examined Zicsr 2.0 specification defines CSR instructions separately from the base integer ISA. Its introductory note explains that these instructions moved out of the base chapter when counters and timers ceased being mandatory base-ISA components.
Likewise, Zifencei 2.0 defines FENCE.I as its own extension. A declaration such as rv32imac therefore should not be treated as an unversioned promise that every historical instruction accepted under that spelling remains included.
Classify the actual diagnostic. A rejected csrr or csrw points toward CSR instruction support; fence.i points toward instruction-fetch synchronization support. A runtime illegal-instruction trap is a different observation from an assembler rejection and still requires checking privilege and implemented hardware behavior.
Inspect the toolchain’s effective ISA contract
The GCC 15.2 RISC-V options distinguish -march from -misa-spec. The latter selects an unprivileged ISA specification version; its documented default is 20191213 unless the compiler was configured with another default.
For a target that actually implements the required extensions, an explicit spelling such as rv32imac_zicsr_zifencei makes those requirements visible. This is an illustrative target declaration, not a recommendation for every RV32 device. Verify support in the hardware and execution environment before adopting it.
Do not use g merely as a convenient way to silence the error. GCC expands it to I, M, A, F, D, Zicsr and Zifencei, which can authorize floating-point instructions absent from a smaller core. Preserve the product's intended ISA rather than accidentally widening it.

Check how assembly receives its options
A build can configure C compilation correctly while invoking the assembler with a different target. Capture the actual command for the failing .S or .s file. Check wrappers, per-file options and whether the source goes through the compiler driver or directly to the assembler.
A proposed driver inspection is to run the configured compiler with -### and the same relevant compilation options, then inspect its reported subcommands. This does not replace examining the real build log. Also check inline assembler directives that locally change the permitted instruction set.
If an old specification selection is retained temporarily for compatibility, record that decision explicitly. Do not conceal it by changing only one source file while the rest of the image continues under a different contract.
Use object attributes as declared requirements, not hardware detection
The pinned RISC-V psABI source specifies Tag_RISCV_arch: an expanded, versioned architecture string. It also describes combining architecture requirements into a superset when objects are merged, with conflicting combinations requiring diagnostics.
Inspect individual objects and the final ELF with the target-capable readelf -A, and examine relevant instructions with objdump -dr. A final attribute set may reflect a dependency's requirements rather than the application's nominal flags. Attributes declare software requirements; they do not probe the silicon or establish permission to access a particular CSR.
The repair is complete when the source's instructions, the effective toolchain declaration and the actual target agree. No cross-compilation or board execution was performed here; the commands above are proposed checks for the delivered toolchain.