web-dev-qa-db-ja.com

Cコードをコンパイルして、最小限のRISC-Vアセンブリプログラムのベアメタルスケルトンを取得するにはどうすればよいですか?

私は次の簡単なCコードを持っています:

   void main(){
    int A = 333;
    int B=244;
    int sum;
    sum = A + B;  
}

これをコンパイルすると

$riscv64-unknown-elf-gcc code.c -o code.o

使用しているアセンブリコードを見たい場合

$riscv64-unknown-elf-objdump -d code.o 

しかし、アセンブリコードを調べると、プロキシカーネルサポート用であると思われる多くのコードが生成されていることがわかります(私はriscvの初心者です)。ただし、このコードがプロキシカーネルをサポートすることは望ましくありません。これは、FPGA内にこの単純なCコードのみを実装することを目的としているためです。

Riscvは、ベアメタルモード、newlibプロキシカーネル、riscvLinuxの3種類のコンパイルを提供していることを読みました。以前の調査によると、私がすべきコンパイルの種類はベアメタルモードです。これは、オペレーティングシステムやカーネルプロキシをサポートせずに最小限のアセンブリが必要なためです。システムコールとしてのアセンブリ関数は必要ありません。

ただし、最小限のriscvアセンブリプログラムのスケルトンを取得するためにCコードをコンパイルできるため、まだ見つけることができませんでした。上記のCコードをベアメタルモードでコンパイルしたり、最小限のriscvアセンブリコードのスケルトンを取得したりするにはどうすればよいですか?

13
Adrian

警告:この回答は、tohostコントロールの削除を含む最新のRISC-V特権仕様v1.9の時点ではやや古くなっています。 /ステータスレジスタ(CSR)。これは非標準のホストターゲットインターフェイス(HTIF)の一部であり、その後削除されました。現在の(2016年9月現在)riscv-testsは、代わりにtohostメモリ位置にメモリマップされたストアを実行します。これは、テザー環境ではfront-end serverによって監視されます。


本当におよび本当にRISC-Vコードを実行する必要がある/実行したい場合ベアメタルの場合は、その手順を次に示します。 riscv-pk(プロキシカーネル)が提供するprintfやFP-trapソフトウェアエミュレーションなどの便利なものがたくさん失われます。

まず最初に-スパイクは0x200で起動します。 SpikeはゴールデンISAシミュレータモデルであるため、コアも0x200で起動する必要があります。

cough、2015年7月13日現在、riscv-toolsの「マスター」ブランチ(- https://github.com/riscv/riscv-tools )は古いv1.7より前の特権ISAを使用しているため、0x2000から始まります。この投稿では、v1.7 +を使用していることを前提としています。 riscv-toolsの「new_privileged_isa」ブランチを使用する必要がある場合があります)。

したがって、ベアメタルプログラムを逆アセンブルするときは、0x200から開始することをお勧めします!!!プロキシカーネル上で実行する場合は、0x10000から開始することをお勧めします(Linuxの場合は、さらに大きくなります…)。

ここで、ベアメタルを実行する場合は、プロセッサのブートコードを作成する必要があります。うん。しかし、それをパントして、それが必要ではないふりをしましょう。

(物理的にアドレス指定されたマシンの「仮想マシン」の説明については、riscv-tests/env/pを調べることもできます。必要なリンカースクリプトと、初期セットアップコードを説明するためのmacros.hがいくつかあります。それでも、riscv-tests/benchmarks/common.crt.S)。


とにかく、上記の(紛らわしい)知識を武器に、それをすべて捨てて、最初から始めましょう...

hello.s:
 .align 6
 .globl _start
 _start:
 # screw boot code, we're going minimalist
 # mtohost is the CSR in machine mode
 csrw mtohost, 1;
 1:
 j 1b

および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 = .;
 }

これをコンパイルするには…

riscv64-unknown-elf-gcc -nostdlib -nostartfiles -Tlink.ld -o hello hello.s

これは(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>

そしてそれを実行するには:

spike hello

それは美しいものです。

リンクスクリプトは、コードを0x200に配置します。 Spikeは0x200から開始し、制御/ステータスレジスタ「tohost」に#1を書き込みます。これにより、Spikeは「実行を停止」します。そして、フロントエンドサーバーがメッセージを受信して​​私たちを殺すまで、アドレス(1:j 1b)をスピンします。

コンパイラに<_start>を0x200に移動するように指示する方法がわかれば、リンカスクリプトを破棄できる可能性があります。


他の例については、次のリポジトリを熟読することができます。

Riscv-testsリポジトリは、非常に最小限のRISC-V ISAテスト( https://github.com/riscv/riscv-tests ))を保持します。

このMakefileにはコンパイラオプションがあります: https://github.com/riscv/riscv-tests/blob/master/isa/Makefile

また、「仮想マシン」記述マクロとリンカースクリプトの多くは、riscv-tests/env( https://github.com/riscv/riscv-test-env )にあります。

riscv-tests/isa/rv64ui-p-simple.dump)で「最も単純な」テストを見ることができます。

また、ベアメタルを実行するためのスタートアップおよびサポートコードについてはriscv-tests/benchmarks/commonを確認できます。

14
Chris

「余分な」コードはgccによってそこに置かれ、あらゆるプログラムに必要な種類のものです。プロキシカーネルは、そのようなものを実行するために必要な最低限のサポートになるように設計されています。プロセッサが動作したら、ベアメタルではなくpkの上で実行することをお勧めします。

それまでの間、単純なアセンブリを見たい場合は、「-c」を使用してリンクフェーズをスキップすることをお勧めします。

riscv64-unknown-elf-gcc code.c -c -o code.o
riscv64-unknown-elf-objdump -d code.o

Pkまたはlinuxを使用せずにコードを実行する例については、 riscv-tests を参照してください。

5
user2548418