This is a minimalistic libgloss port for RISC-V M-mode that implements system calls through the Berkeley Host-Target Interface (HTIF).
$ mkdir build
$ cd build
$ ../configure --prefix=${RISCV}/riscv64-unknown-elf --host=riscv64-unknown-elf
$ make
$ make install
Note: The installation prefix must be chosen such that the libdir
variable matches one of the library search paths of the RISC-V compiler.
For a typical cross-compiler toolchain, the prefix would generally be
the sysroot directory (riscv64-unknown-elf-gcc -print-sysroot).
Use the --libdir configure option to adjust the location if the final
directory component is not /lib.
Test static linking with a suite of "Hello World" demonstration programs:
$ make check
$ spike hello.riscv
$ spike hello.nano.riscv
$ spike hello.pico.riscv
The --enable-multilib or --disable-multilib configure options
control whether both RV32 and RV64 libraries are built.
A list of ISA/ABI combinations can be passed as an argument to override
the default set:
--enable-multilib='rv32i/ilp32 rv32iac/ilp32 rv32im/ilp32 rv32imac/ilp32 rv32imafc/ilp32f rv64imac/lp64 rv64imafdc/lp64d'
If these options are omitted, configure dynamically detects the set of
multilib mappings supported by the compiler ($CC).
For convenience, the compiler/linker switches needed to replace the
standard -lgloss are encapsulated in GCC spec files, along with a
bare-metal linker script.
| Spec File | Description | 
|---|---|
| htif.specs | Link with newlib | 
| htif_nano.specs | Link with newlib-nano | 
| htif_wrap.specs | Switch to minimal stdio implementation | 
| htif_argv.specs | Retrieve argvfrom fesvr | 
$ riscv64-unknown-elf-gcc -O2 -specs=htif.specs -o hello tests/hello.c
htif_wrap.specs further reduces static code size by inserting custom
implementations of common stdio.h functions, which support only a
constrained subset of format specifiers (e.g., non-floating-point).
This depends on the --wrap feature of GNU ld and is intended to be
used in conjuction with the other newlib spec files.
$ riscv64-unknown-elf-gcc -O2 -specs=htif_nano.specs -specs=htif_wrap.specs -o hello tests/hello.c
htif_argv.specs adds extra initialization code to retrieve
command-line arguments from the frontend server.  The program will exit
with an error (typically ENOMEM) if the number or length of the
argument strings exceeds the fixed buffer size set by ARG_MAX.
If this feature is omitted, argv defaults to a static array with no
arguments.
$ riscv64-unknown-elf-gcc -O2 -specs=htif_nano.specs -specs=htif_argv.specs -o hello tests/hello.c
For simple testing, it is possible to directly link against
libgloss_htif.a in the build directory without installing:
- Add -L <builddir>to the link command.
- Pass the actual path to the spec file in -specsargument.
- Symlink htif.ldto the current working directory. (This bypasses a limitation where gcc searches only the default library path for the linker script, ignoring-L.)
Override the __stack_size_min symbol to change the minimum stack
size in bytes:
-Wl,--defsym=__stack_size_min=$N.
Override the __heap_size symbol to change the heap size in bytes:
-Wl,--defsym=__heap_size=$N.
Static TLS is supported through the Local Executable access model, which
allows the declaration of thread-local variables with the __thread
specifier.
By default, hart 0 is designated as the primary hart for handling global
initialization and executing the main() function.
A different hart ID can be specified by redefining the __boot_hart
symbol, such as with a linker option: -Wl,--defsym=__boot_hart=$N.
All other harts execute the secondary __main() function, which
defaults to a busy loop.
Multi-threaded programs should either override this function or alias
__main with main to force a common entry point:
-Wl,--defsym=__main=main.
A custom exception handler can be implemented by overriding the
handle_trap() function, which should match the following signature:
uintptr_t handle_trap(uintptr_t epc, uintptr_t cause, uintptr_t tval, uintptr_t regs[32])The return value sets the new mepc for returning from the exception.