riscv - How can I compile C code to get a bare-metal skeleton of a minimal RISC-V assembly program? -
i have following simple c code:
void main(){ int = 333; int b=244; int sum; sum = + b; } when compile
$riscv64-unknown-elf-gcc code.c -o code.o if want see assembly code use
$riscv64-unknown-elf-objdump -d code.o but when explore assembly code see generates lot of code assume proxy kernel support (i newbie riscv). however, not want code has support proxy kernel, because idea implement simple c code within fpga.
i read riscv provides 3 types of compilation: bare-metal mode, newlib proxy kernel , riscv linux. according previous research, kind of compilation should bare metal mode. because desire minimum assembly without support operating system or kernel proxy. assembly functions system call not required.
however, have not yet been able find can compile c code skeleton of minimal riscv assembly program. how can compile c code above in bare metal mode or skeleton of minimal riscv assembly code?
warning: answer out-of-date of latest risc-v privileged spec v1.9, includes removal of tohost control/status register (csr), part of non-standard host-target interface (htif) has since been removed. current (as of 2016 sep) riscv-tests instead perform memory-mapped store tohost memory location, in tethered environment monitored front-end server.
if really , truly need/want run risc-v code bare-metal, here instructions so. lose bunch of useful stuff, printf or fp-trap software emulation, riscv-pk (proxy kernel) provides.
first things first - spike boots @ 0x200. spike golden isa simulator model, core should boot @ 0x200.
(cough, of 2015 jul 13, "master" branch of riscv-tools (https://github.com/riscv/riscv-tools) using older pre-v1.7 privileged isa, , starts @ 0x2000. post assume using v1.7+, may require using "new_privileged_isa" branch of riscv-tools).
so when disassemble bare-metal program, better start @ 0x200!!! if want run on top of proxy-kernel, better start @ 0x10000 (and if linux, it’s larger…).
now, if want run bare metal, you’re forcing write processor boot code. yuck. let’s punt on , pretend that’s not necessary.
(you can riscv-tests/env/p, “virtual machine” description physically addressed machine. you’ll find linker script need , macros.h describe initial setup code. or better yet, in riscv-tests/benchmarks/common.crt.s).
anyways, armed above (confusing) knowledge, let’s throw away , start scratch ourselves...
hello.s: .align 6 .globl _start _start: # screw boot code, we're going minimalist # mtohost csr in machine mode csrw mtohost, 1; 1: j 1b and link.ld:
output_arch( "riscv" ) entry( _start ) sections { /* text: test code section */ . = 0x200; .text : { *(.text) } /* data: initialized data segment */ .data : { *(.data) } /* end of uninitalized data segement */ _end = .; } now compile this…
riscv64-unknown-elf-gcc -nostdlib -nostartfiles -tlink.ld -o hello hello.s
this compiles (riscv64-unknown-elf-objdump -d hello):
hello: file format elf64-littleriscv disassembly of section .text: 0000000000000200 <_start>: 200: 7810d073 csrwi tohost,1 204: 0000006f j 204 <_start+0x4> and run it:
spike hello it’s thing of beauty.
the link script places our code @ 0x200. spike start @ 0x200, , write #1 control/status register “tohost”, tells spike “stop running”. , spin on address (1: j 1b) until front-end server has gotten message , kills us.
it may possible ditch linker script if can figure out how tell compiler move <_start> 0x200 on own.
for other examples, can peruse following repositories:
the riscv-tests repository holds risc-v isa tests minimal (https://github.com/riscv/riscv-tests).
this makefile has compiler options: https://github.com/riscv/riscv-tests/blob/master/isa/makefile
and many of “virtual machine” description macros , linker scripts can found in riscv-tests/env (https://github.com/riscv/riscv-test-env).
you can take @ “simplest” test @ (riscv-tests/isa/rv64ui-p-simple.dump).
and can check out riscv-tests/benchmarks/common start-up , support code running bare-metal.
Comments
Post a Comment