4.1.1. About GNU Toolchain
The official toolchain repository is located at https://github.com/riscv-collab/riscv-gnu-toolchain.git.
Nuclei maintained toolchain repo is located at https://github.com/riscv-mcu/riscv-gnu-toolchain.
The latest release 2026.10 branch for gcc14 and llvm19 is nuclei/2026.10, in which the tools included versions are: gcc 14.2.1, binutils 2.44, gdb 16.2, newlib 4.5.0, llvm 19.1.7, glibc 2.41, and also have merged some important patches from their upstream, as well as additional support for Nuclei custom extensions and pipelines, etc.
Note
The toolchain is implemented based on the upstream version. Many features can be referenced in the GCC online documentation: https://gcc.gnu.org/onlinedocs/. Please check the corresponding GNU release version in the online documentation for accurate details. Additionally, local documentation is available under gcc/share/doc in the toolchain directory.
4.1.2. Extensions Support
Standard Extensions
Basic Extensions
i, m, a, f, d, c, h, q(Assembly only), zaamo, zalrsc, zicsr, zifencei, zicond, zibi, zawrs, zfh, zfhmin, zmmul, svinval, svnapot.
Z*inx Extensions
zfinx, zdinx, zhinx, zhinxmin.
CMO Extensions
zicboz, zicbom, zicbop.
Bitmanip Extensions
zba, zbb, zbc, zbs
Crypto Extensions
zbkb, zbkc, zbkx, zknd, zkne, zknh, zkr, zks, zksed, zksh, zkt.
Vector Extensions
zve32x, zve32f, zve64x, zve64f, zve64d, zvfh, zvfhmin, v.
Zc Extensions
zca, zcb, zce, zcf, zcd, zcmp, zcmt.
zce = zca + zcb + zcmp + zcmt
f + zce = zca + zcb + zcf + zcmp + zcmt
f + d + zce = zca + zcb + zcf + zcd + zcmp + zcmt
Note
The Zcmt table jump auto-generation conditions (the linker relaxes the jumps into jt/jalt table jump instructions):
2025.10: enabled by default. When
zcmtis present in-march=, the Zcmt table jump instructions are generated automatically.2026.10: both conditions must be satisfied:
zcmtpresent in-march=, and the linker option--relax-zcmt(pass it as-Wl,--relax-zcmtwhen linking with GCC). The default--no-relax-zcmtdisables the auto-generation.
Attention
The Zcmt table jump support has not been merged into the binutils mainline branch yet, it is an experimental feature in the Nuclei toolchain. Please be aware of the risks when using it in production.
Zvb Extensions
zvbb, zvbc
Zvk Extensions
zvkg, zvkned, zvknha, zvknhb, zvksed, zvksh, zvkn, zvknc, zvkng, zvks, zvksc, zvksg, zvkt.
BFloat 16 Extensions
Standard: Zfbfmin, Zvfbfmin, Zvfbfwma
Nuclei customized: Xxlfbf, Xxlvfbf
Zilsd Extensions
Zilsd, Zclsd
Smrnmi & Double Trap Extensions (added since 2026.10)
smrnmi, smdbltrp, ssdbltrp.
Nuclei Custom Extensions
Packed SIMD Extension 0.5.4 + Nuclei Customized DSP Extensions
xxldsp, xxldspn1x, xxldspn2x, xxldspn3x.
xxldsp: P-spec-v0.54 + Nuclei Custom EXPD* instructions
xxldspn1x: xxldsp + Nuclei Custom N1
xxldspn2x: xxldsp + Nuclei Custom N1 & N2
xxldspn3x: xxldsp + Nuclei Custom N1 & N2 & N3
Xxlcz Extensions
xxlczpstinc, xxlczbmrk, xxlczbitop, xxlczslet, xxlczabs, xxlczmac, xxlczbri, xxlczbitrev, xxlczgp.
Nuclei Custom Vector MAC Extension
Nuclei Custom Xxlvw Vector Wireless DSP Extension
Note
Extensions starting with x are generally reserved for manufacturers to customize, and should be placed after extensions starting with z when used.
4.1.3. General Options
-march=ISA-string
Generate code for given RISC-V ISA. ISA strings must be lower-case. Examples include
rv64i,rv32g,rv32e, andrv32imaf. When-march=is not specified, use the setting from-mcpu. If both-marchand-mcpu=are not specified, the default for this argument is system dependent, users who want a specific architecture extensions should specify one explicitly.
-mabi=ABI-string
Specify integer and floating-point calling convention. ABI-string contains two parts: the size of integer types and the registers used for floating-point types. For example
-march=rv64ifd -mabi=lp64dmeans that long and pointers are 64-bit (implicitly defining int to be 32-bit), and that floating-point values up to 64 bits wide are passed in F registers. Contrast this with-march=rv64ifd -mabi=lp64f, which still allows the compiler to generate code that uses the F and D extensions but only allows floating-point values up to 32 bits long to be passed in registers; or-march=rv64ifd -mabi=lp64, in which no floating-point arguments will be passed in registers.The default for this argument is system dependent, users who want a specific calling convention should specify one explicitly. The valid calling conventions are:
ilp32,ilp32f,ilp32d,lp64,lp64f, andlp64d. Some calling conventions are impossible to implement on some ISAs: for example,-march=rv32if -mabi=ilp32dis invalid because the ABI requires 64-bit values be passed in F registers, but F registers are only 32 bits wide. There is also theilp32eABI that can only be used with therv32earchitecture. This ABI is not well specified at present, and is subject to change.
-mcmodel=medlow
Generate code for the medium-low code model. The program and its statically defined symbols must lie within a single 2 GiB address range and must lie between absolute addresses -2 GiB and +2 GiB. Programs can be statically or dynamically linked. This is the default code model.
-mcmodel=medany
Generate code for the medium-any code model. The program and its statically defined symbols must be within any single 2 GiB address range. Programs can be statically or dynamically linked.
The code generated by the medium-any code model is position-independent, but is not guaranteed to function correctly when linked into position-independent executables or libraries.
-mtune=processor-string
Optimize the output for the specified processor by either microarchitecture or a specific CPU name. The allowable values for this option include:
nuclei-100-series,nuclei-200-series,nuclei-300-series,nuclei-600-series,nuclei-900-series,nuclei-1000-series,nuclei-1000-3w-series, andnuclei-1000-4w-series. Note thatnuclei-1000-seriesandnuclei-1000-4w-seriesare considered equivalent. All these options are valid for the -mcpu= flag.When
-mtune=is not specified, use the setting from-mcpu, the default isrocketif both are not specified.The
sizechoice is not intended for use by end-users. This is used when -Os is specified. It overrides the instruction cost info provided by-mtune=, but does not override the pipeline info. This helps reduce code size while still giving good performance.
-fno-strict-aliasing
It is recommended to add the optimization option
-fno-strict-aliasingto the project. In some circumstances,-fstrict-aliasing(enabled by default at-O2and above) allows the compiler to assume that pointers to different types do not alias, which may break code that accesses the same memory through pointers of different types.
-ftree-loop-vectorize
If you need to disable the RISC-V RVV automatic vectorization, you can use the options
-fno-tree-loop-vectorizeand-fno-tree-slp-vectorize. Since 2026.10, you can also use the option-mno-autovec-rvv. For GCC 13, you can use--param=riscv-autovec-preference=none.
-fno-builtin
The
-fno-builtinoption instructs the compiler to avoid replacing standard library function calls with optimized built-in versions. If your program requires implementing its own system functions, such as memcpy, memset, etc., you need to use this option.
-fstack-usage
Generate a stack usage file (
<auxname>.su) for each translation unit at compile time, which can be used to analyze the static stack usage of each function. Each entry records the function name, the size of its stack frame in bytes, and one or more qualifiers:static(a fixed number of bytes allocated at entry and released at exit),dynamic(the function also adjusts the stack in its body, such as alloca or variable length arrays) andbounded(the dynamic adjustments are bounded at compile time, and the number is an upper bound on the total stack usage). The file is generated next to the object file.
-fcallgraph-info
Generate a callgraph file (
<auxname>.ciin VCG format) for each translation unit at compile time, which records the static call relationships between functions. With thesumark (-fcallgraph-info=su), each function in the callgraph is annotated with its stack usage information, so that the call chains and the worst-case stack usage can be analyzed statically. For example:riscv64-unknown-elf-gcc -c -O2 -fcallgraph-info=su -fstack-usage main.c -o main.ogenerates
main.o,main.suandmain.ciin the output directory.Note
When compiling with
-flto, no callgraph information is output along with the object file.Third-party tools can be used to analyze the generated files, for example:
callgraph: aggregates the
.cicallgraph files generated by GCC into a single DOT file, which can be rendered by Graphviz to visualize the call graph of the whole program.checkStackUsage: combines the
.sustack usage files with the disassembly of the ELF binary to compute the accumulated worst-case stack usage of each call chain. Note that calls made through function pointers cannot be seen by the static analysis.
Optimization Options
- -O0
Reduce compilation time and make debugging produce the expected results. This is the default.
- -O/-O1
With -O, the compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time.
- -O2
Optimize even more. GCC performs nearly all supported optimizations that do not involve a space-speed tradeoff. As compared to -O, this option increases both compilation time and the performance of the generated code.
- -O3
This option turns on all options in -O2, as well as several other optimizations to improve the performance of the object code.
- -Os
This optimization option is often used to tell the compiler to reduce the size of the object code as much as possible while maintaining performance. It will remove some optimization strategies that increase the object code size from all options enabled by -O2.
- -Ofast
Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs.
For more information about RISC-V Options used in GCC, please check https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/RISC-V-Options.html
For RISC-V ELF psABI Document, please check https://github.com/riscv-non-isa/riscv-elf-psabi-doc
4.1.4. Nuclei Custom Options
In addition to the standard RISC-V options above, the Nuclei GNU toolchain provides the following Nuclei custom options:
-mautovec-rvv/-mno-autovec-rvv
Controls the RISC-V RVV automatic vectorization. Enabled by default, use
-mno-autovec-rvvto disable it. This option is added since 2026.10.Since 2026.10, RVV automatic vectorization is always disabled in interrupt handlers (functions marked with the
interruptattribute), regardless of this option. In interrupt handlers, vector registers are only saved when they are directly used by the handler itself; if the handler or its callees use the vector unit, the full vector state must be saved and restored by the user.
-mautovec-dsp/-mno-autovec-dsp
Controls the generation of automatic vectorization of Nuclei DSP instructions. Since 2026.10, Nuclei DSP instruction auto-vectorization is disabled by default, use
-mautovec-dspto enable it.
-mautogen-xxlcz/-mno-autogen-xxlcz
Controls the auto-generation of the Nuclei
xxlczextension instructions (including thexl.addibneinstruction). Disabled by default, use-mautogen-xxlczto enable it. This option is added since 2026.10, and replaces the-maddibne/-mno-addibneoption which was removed in 2026.10.
4.1.5. Libraries
Note
glibcis used in Linux GNU Glibc toolchain used to compile linux kernel, opensbi, uboot, and linux applications.newlibis used in Baremetal or RTOS toolchain, used to compile baremetal or rtos source code, which containsnewlib,newlib-nanoand libncrt
glibc
glibc stands for GNU C Library which is the standard system C library for all GNU systems. It provides the system API for all programs written in C and C-compatible languages such as C++ and Objective C; the runtime facilities of other programming languages use the C library to access the underlying operating system. This library is only supported on Nuclei linux toolchain, not on Nuclei bare-metal toolchain.
newlib
newlib is written as a glibc replacement for embedded systems. It can be used with no OS (“bare metal”) or with a lightweight RTOS. Newlib is the default library for embedded GCC distributions.
newlib-nano
Newlib-nano is a derivative of the newlib C library for embedded systems. It is smaller and faster than newlib by code and data size reduction through optimization and removal of non-MCU features.
libncrtis short for Nuclei C Runtime Library, which currently supports Nuclei RV32 processor, and is released by Nuclei to reduce c library code size, and improve math library speed, for details, please refer to the user guide located ingcc/share/pdf/Nuclei C Runtime Library Doc.pdf
4.1.6. Changelog
Please check Changelog here.
4.1.7. Install and Setup
Build Toolchain
For more information about how to build a toolchain, see https://github.com/riscv-mcu/riscv-gnu-toolchain/tree/nuclei/2025/scripts/toolchain. (Only for Nuclei internal use, no technical support is provided)
Development
The process of user compilation and development can see from https://github.com/riscv-mcu/riscv-gnu-toolchain/blob/nuclei/2025/README.md. To get other technical support, please send issues directly to the upstream repository https://github.com/riscv-collab/riscv-gnu-toolchain.
Examples
If you choose a core of Nuclei N300FD, then the parameter you pass to ‘march’ should be
rv32*fd*, and ‘mabi’ should chooseilp32d.If you want to bring the full
B/K/Pextension, then you also need to bring all the subsets of them in the ‘march’. For example, for theBextension, the parameter you pass to ‘march’ is_zba_zbb_zbc_zbs.
3. When using a library, we can tell the linker which library we need to link by using the ‘-l’, for example, -lc for newlib-full, -lc_nano for newlib-nano. For libncrt, you should pass --specs=libncrt_xxx.specs when using gcc. In addition, you need to link extra ‘fileops’ and ‘heapops’ static libraries during the linking phase by using the ‘-l’, and for the ‘fileops’, you must select one of the three options: ‘uart’, ‘semi’ or ‘rtt’,
and for the ‘heapops’, you must select one of the three options: ‘basic’, ‘realtime’ or ‘minimal’.
4.1.8. Testsuite
Since 2026.10, a GCC testsuite test framework has been added to the Nuclei toolchain, and the built-in testcases of GCC and Binutils are already covered by it:
The built-in GCC and Binutils testsuites are run against the multilib combinations (target/library/extension/ABI) of the toolchain in the CI.
The known failing testcases are recorded in the allowlist files under
test/allowlist/<toolname>/of the toolchain repository, named by the rule[<lib>.][rv(32|64|128).][<ext>.][<abi>.]logand filtered byscripts/testsuite-filter, so the regressions can be detected easily.Nuclei custom extension testcases, such as
xxlfbf,xxlvfbf,xxlvw,xxlvqmacc,xxlcz,xxldspand the ECLIC V2 CSRs, are also added to the testsuite.
4.1.9. Checking GNU Version
To check the basic version information of GCC, you can use the command riscv64-unknown-elf-gcc -v.
If you need to report an issue to the developers, please provide:
The
gcc/build.txtfile (located in the toolchain directory) for toolchain build details.The
gcc/gitrepo.txtfile to confirm commit IDs of each tool, which helps determine more detailed build information.
4.1.10. Known Issues
4.1.10.1. sscanf Format Specifiers Issue in Newlib-nano
sscanf fails with hhu, llu, etc., due to missing C99 support (%hhX, %llX, %jX, %zX, %tX).
References:
4.1.10.2. GDB RISC-V Memory Access at Address 0 When Symbols Are Missing
When debugging a RISC-V target via OpenOCD+GDB, running a stepping command (si) before loading an ELF with symbols causes GDB to incorrectly read memory near address 0x0.
References:
4.1.10.3. Access to Address 0 Is Compiled Into ebreak
GCC enables the -fdelete-null-pointer-checks optimization by default on most targets at all optimization levels. It assumes that a program cannot safely dereference the null pointer and that no code or data element resides at address zero. Under this assumption, access to address 0 is treated as undefined behavior and compiled into a trap instruction (ebreak), and null-pointer checks after a dereference are removed by the data flow analysis.
However, this assumption does not always hold on Nuclei CPUs: the IREGION can be configured so that address 0 is a valid address, for example when the IINFO region is mapped to address 0. In this case, accesses to address 0 are legal and the generated ebreak is wrong.
If the CPU is configured with IREGION mapped to address 0, you need to add the -fno-delete-null-pointer-checks option globally to your project to disable this optimization.
References:
4.1.10.4. naked Attribute With Variadic Functions Is Not Supported
On RISC-V, do not use the naked function attribute together with variadic functions (varargs). When a naked function has a variadic parameter list, GCC still emits code from riscv_setup_incoming_varargs to spill the unnamed argument registers to the stack. Since the naked attribute suppresses the function prologue, these stores write into the caller’s stack frame and corrupt memory.
Upstream has confirmed that naked functions and varargs are fundamentally incompatible with each other and should not be used together, and this issue is closed as WONTFIX and will not be fixed (GCC bug 125798).
4.1.10.5. -Wa,-adhlns Breaks the Frame Unwind Information for GDB Debugging
Using the assembler listing option -Wa,-adhlns=xxx.lst on RISC-V emits extra relocations into the .eh_frame/.debug_frame sections, which corrupts the frame unwind information (tools such as readelf will show invalid CFI operations), and breaks the GDB debugging and backtrace which rely on it.
Upstream has confirmed the extra relocations, but there is no fix or further response yet (binutils bug 33776). If you need to debug your program with GDB, avoid passing the -Wa,-adhlns=xxx.lst option.