ので docker + qemu で試してみます。
ファイルを作った後 WSL で以下のようにして環境を作りました。
sudo apt install qemu-user-static
docker compose build
アーキテクチャのエミュレーションが挟まるのでただの apt update
でも大変遅いです。待つしかありません。
環境が出来上がったら、C のコードをビルドしてみます。
make
で出来上がったものがこちらです。
なるほど何もわからない。RISC-V の呼び出し規約も命令セットも知らないのでわかるわけがない。 "riscv (abi OR call-convention)" で Google 検索してみると、日本語もわかりやすい解説、riscv.org 公式など多数の文書が見つかります。
あたりが今もっとも欲しい情報に近そうです。なんとなく読み取れた情報を列挙します。
- (float 系はややこしくなるのでとりあえず無視する)
- x0-31 のレジスタがある
- レジスタは役割によって別名がついている
- x0
- zero
- x1
- ra
- x2
- sp
- x3
- gp
- x4
- tp
- x5 - x7
- t0 - t2
- x8 - x9
- s0 - s1
- x10 - x17
- a0 - a7
- x18 - x27
- s2 - s11
- x28 - x31
- t3 - t6
- (aarch64 に馴染みがあれば理解は早いかも?すみません適当言っています)
- x0
- スタックポインタ sp (x2)を減算してヒープ=作業領域を確保する。
- (だいたいそうだと思うので当たり前と言えば当たり前かもしれない)
addi sp, sp, -48
のように負数を add する- sub とは言わないようだ
sd s0, 32(sp)
は「レジスタ s0(x8)の値を (sp+32) 番地に store (書き込み)する 」と読むld s0, 32(sp)
は「レジスタ s0(x8)に (sp+32) 番地の値を load (読み込み)する 」と読むret
はjr ra
つまり「レジスタ ra(x1)の値の番地にジャンプする」と読む
ほんのり何かわかった気になってきました。ここで命令列も見てみます。やっとです。普通最初に見るべきでは?というのはその通りなのですが、いきなりドカンと命令列を見ても結局よくわからなさそうだと思ったので後回しにしました。
- RISC-V Instruction Set Specifications
- RISC-Vの命令セット
- 一覧ではなく、考え方やグルーピングについての解説
ざっと見た感想を列挙します。
- 末尾の "i" は immediate つまり即値を表していそう
- x0 が常にゼロなことを利用して x0 +- imm をするパターンが面白い
mv reg1, reg2
は reg1 に reg2 の値 を 入れるということで、直感的な並び順でよかった- store 系も mv と同じ順、つまり dst, src の並びにした方が覚えやすいのでは?と個人的には思う
- load 系と同じ並びにすることに何か意味があるんだろうからそこはそういうものだと思うしかない
- "c." で始まる圧縮命令がかなり多そう
楽な方法ばかり取っていましたが、公式ドキュメントが正しい拠り所であろうとは思います。
「りすくぶい」って勝手に読んでたんですが「りすくふぁいぶ」なんですね。 RISC-I, RISC-II, SOAR, SPUR があって 5 世代目とのこと。へー。