NOTE: Since this was written the riscv-toolchain-conventions document has been released.
Getting started with RISC-V. Compiling for the RISC-V target. This post covers the GCC machine architecture (-march), ABI (-mabi) options and how they relate to the RISC-V base ISA and extensions. It also looks at the multilib configuration for GCC.
Selecting
- the base ISA,
- the extensions, and
- the target ABIs.
Machine Architecture and ABI
When compiling for RISC-V figuring out the compiler target correct is one of the first complications of having an extendable architecture. GCC has the following options:
-
The -march= option selects the base ISA + extensions. The extensions should be specified in a canonical order that the compiler can recognize. Only the extensions relevant to the compiler are needed.
-
The -mabi= option selects the calling convention ABI.
- e.g. ilp32e for the rv32e eabi
- e.g. ilp32, for the rv32i without floating point hardware, or ilp32{f,d} with single or double precision registers.
- e.g. ilp64, for the rv64i without floating point hardware, or ilp64{f,d} with single or double precision registers.
The architecture string has a canonical order and format:
- The base ISA is first. (e.g. rv32e, rv32i, rv64i)
- Aliases can be used. (e.g. rv32g=rv32imafd)
- Must be lower case.
- Must be in the canonical order.
- To match the library path, order is important.
- For the current GCC (8.2.0) single letter extension names may NOT be separated by underscore.
There is also a relation between the -march= and -mabi=:
- Not specifying -mabi= seems to select a default value “.”, not a specific ABI.
- Only some combinations of base ISA and supported extensions/ABIs.
- e.g. the ipl32e ABI can’t be used with rv32i or rv64i.
- These may fail at link time rather than be detected.
The GCC source for the options parser is here: riscv-gcc-8.2.0/gcc/common/config/riscv/riscv-common.c
Code Generation
The RISC-V GCC compiler can generate code for all (supported) extensions and ABIs, a separate compiler binary is not needed for each base ISA. Depending on how the compiler was configured at build time the name may be riscv-none-embed-gcc, or riscv32-unknown-elf-gcc or riscv64-unknown-elf-gcc, however they can all compile for any base ISA and extensions and address size.
The following -march= options are recognized by the gcc compiler (as of 8.2.0) and configured at run time:
Base ISAs recognized:
- rv32 : 32 bit ISA.
- rv64 : 64 bit ISA.
- e : rv32e embedded ISA, only 16 general purpose registers.
- i : base integer ISA.
Extensions recognized:
- g : alias for imafd.
- m : multiplication and division instructions.
- a : atomic instructions.
- f : floating point instructions.
- d : double float.
- c : compressed instructions.
Link Libraries
Unlike the code generation, the default target (when no -march= option is given) and the architecture and ABIs with supported libraries will depend on the build time configuration. The compiler’s build configuration selects:
- The combination(s) of -march= and -mabi= used to compile the compiler’s link libraries (libgcc, libc etc).
- The compiler may have been built with a single library to support just one machine architecture.
- This will only work if you compile for the same or compatible architecture.
- The compiler may have been built with multiple libraries for several architectures (multilib).
- The GCC configure build scripts do not support all targets for multilib.
The option –print-multi-lib will indicate the supported targets. For example:
-
Single library: A GCC with a custom configuration, built from source (from github ) supporting only one target library.
- I’m not sure the correct way to check the libgcc architecture in this case.
- GCC can give the path of libgcc, inspecting the debug contents reveals the compile options.
- I’m not sure the correct way to check the libgcc architecture in this case.
- Multlib: For the GCC from 8.2.0-2.2-20190521-0004 build of GCC from the GNU MCU Eclipse project.
If you are compiling for other architectures not listed by –print-multi-lib a compatible library may be selected. This may not be optimal.
- e.g. When using riscv-none-embed-gcc for -march=rv32ec, the rv32e library is selected. This will not include compressed instructions so will be larger than necessary.
Notes
An example of compiling for different targets is here.
The compiler needs to be able to translate the -march= and -mabi= options into a fixed path. For 8.2.0-2.2-20190521-0004 directories are:
These are the C runtime and compiler support files that are compiled for each architecture: