Five EmbedDev logo Five EmbedDev

An Embedded RISC-V Blog

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

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 architecture string has a canonical order and format:

There is also a relation between the -march= and -mabi=:

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:

Extensions recognized:

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 option –print-multi-lib will indicate the supported targets. For example:

$ riscv32-unknown-elf-gcc --print-multi-lib
.;

$ riscv32-unknown-elf-gcc --print-multi-directory
.
$ riscv32-unknown-elf-gcc -print-libgcc-file-name
...gcc_riscv32_unknown_elf-8.2.0/bin/../lib/gcc/riscv32-unknown-elf/8.2.0/libgcc.a

$ riscv32-unknown-elf-objdump --debugging ...gcc_riscv32_unknown_elf-8.2.0/bin/../lib/gcc/riscv32-unknown-elf/8.2.0/libgcc.a | grep -m 1 DW_AT_producer
    <c>   DW_AT_producer    : (indirect string, offset: 0x5b4): GNU C17 8.2.0 -mcmodel=medlow -mcmodel=medlow -march=rv32ec -mabi=ilp32e -g -Os -O2 -Os -fbuilding-libgcc -fno-stack-protector -fvisibility=hidden
$ riscv-none-embed-gcc --print-multi-lib
.;
rv32e/ilp32e;@march=rv32e@mabi=ilp32e
rv32em/ilp32e;@march=rv32em@mabi=ilp32e
rv32eac/ilp32e;@march=rv32eac@mabi=ilp32e
rv32emac/ilp32e;@march=rv32emac@mabi=ilp32e
rv32i/ilp32;@march=rv32i@mabi=ilp32
rv32im/ilp32;@march=rv32im@mabi=ilp32
rv32iac/ilp32;@march=rv32iac@mabi=ilp32
rv32imac/ilp32;@march=rv32imac@mabi=ilp32
rv32imaf/ilp32f;@march=rv32imaf@mabi=ilp32f
rv32imafc/ilp32f;@march=rv32imafc@mabi=ilp32f
rv32imafdc/ilp32d;@march=rv32imafdc@mabi=ilp32d
rv64imac/lp64;@march=rv64imac@mabi=lp64
rv64imafc/lp64f;@march=rv64imafc@mabi=lp64f
rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d

$ riscv-none-embed-gcc --print-multi-directory
rv32imac/ilp32

If you are compiling for other architectures not listed by –print-multi-lib a compatible library may be selected. This may not be optimal.

$ riscv-none-embed-gcc -march=rv32ec -mabi=ilp32e --print-multi-directory
rv32e/ilp32e

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:

lib/gcc/riscv-none-embed/8.2.0/
     rv32e/ilp32e
     rv32eac/ilp32e
     rv32em/ilp32e
     rv32emac/ilp32e
     rv32i/ilp32
     rv32iac/ilp32
     rv32im/ilp32
     rv32imac/ilp32
     rv32imaf/ilp32f
     rv32imafc/ilp32f
     rv32imafdc/ilp32d
     rv64imac/lp64
     rv64imafc/lp64f
     rv64imafdc/lp64d

These are the C runtime and compiler support files that are compiled for each architecture:

lib/gcc/riscv-none-embed/8.2.0/<march>/<mabi>
     crtbegin.o
     crtend.o
     crti.o
     crtn.o
     libgcc.a
     libgcov.a
riscv-none-embed/lib/<march>/<mabi>
     libc.a
     libc_nano.a
     libg.a
     libgloss.a
     libg_nano.a
     libm.a
     libnosys.a
     libsim.a
     libstdc++.a
     libstdc++_nano.a
     libsupc++.a
     libsupc++_nano.a