RISC-V 常識集
RISC-Vの常識を集めて仕様アスペを脱出しましょう.
汎用レジスタと慣習
ご存じの通り,RISC-Vには汎用レジスタがいっぱいある.具体的にはx0-x31の32個ある.これらの長さはRV32の場合は32-bitとなり,RV64の場合は64-bitになる.
RISC-V Unprivileged ISA Specificationの頭の方には,x0-x31の汎用レジスタの一覧が書いてあり,なんか全部自由に適当に使っていい気がしてくるが,実際はそんなことはない.
これら32個のレジスタには,それぞれ慣習的に別名が付けられており,その別名に応じて使い方が大まかに定められている.というわけでx0-x31という名前は,実際のプログラミングで使う事も,コンパイラが吐いたアセンブリに出てくることも殆どない.
じゃあx0-x31にどんな別名が存在し,どんな慣習が与えられているのか知りたくなってくるが,これはRISC-V Unprivileged ISA SpecificationではなくRISC-V ABIs Specificationに載っている.
その内容は以下の通り.なんかごちゃごちゃ書いてあるが,この表の後に詳説する.
| 名前 | ニーモニック | 役割 | callを跨いで値が保存されるか |
|---|---|---|---|
x0 |
zero |
ゼロレジスタ | -(Immutable) |
x1 |
ra |
戻りアドレス | No |
x2 |
sp |
スタックポインタ | Yes |
x3 |
gp |
グローバルポインタ | - |
x4 |
tp |
スレッドポインタ | - |
x5-x7 |
t0-t2 |
一時レジスタ | No |
x8-x9 |
s0-s1 |
Callee-saved レジスタ | Yes |
x10-x17 |
a0-a7 |
引数レジスタ | No |
x18-x27 |
s2-s11 |
Callee-saved レジスタ | Yes |
x28-x31 |
t3-t6 |
一時レジスタ | No |
表の見方としては,名前は名前であり,ニーモニックは与えられた別名であり,アセンブリを書くときは大体これを使う.その隣は役割であり,詳しい事はAIに聞いてください.最右は関数呼び出しの前後で値が変わらない保証があるか否かであり,Noと書かれているレジスタに値を保存すべきではない.
この「callを跨いで値が保存されてるか」というのはあくまで慣例であるので,callで呼び出された関数がヘボければ値が破壊され得る.つまり話半分程度に捉えておいた方がいい.
基本的にはどうでもいい値はt0-t6に格納し,どうでもよくない値はs0-s11に格納するのがよい.
というか実際のレジスタの名前とt0-t2,t3-t6が連続してないのがキモいが,これはレジスタを半分に減らした組み込み向けの縮小命令セット,RV32E/RV64Eのための工夫らしい.
上記の表の通りいろんなレジスタが存在するが,この後はマジで重要なレジスタ,ゼロレジスタについてのみ説明する.
ゼロレジスタと擬似命令
レジスタ番号0のレジスタ,x0/zeroはゼロレジスタと呼ばれており,値が常に0のレジスタである.なのでこれに何を書き込もうが常にゼロになる.ならなければならない.ゼロ以外になり得る場合はそれはもはやRISC-Vではない.
このゼロレジスタ,聡明な読者の諸君(死ね)なら様々な用法を思いつくだろうが,RISC-Vではpseudoinstructions(擬似命令)でよく用いられる.
RISC-Vのアセンブリを読んでいると,よくliやjやretなど,RISC-V ISA Specificationには存在しない命令が出てくることがある.これらは擬似命令と呼ばれ,特定の命令に特定のオペランドを与えたものの別名であり,頻出する命令とオペランドの組み合わせに与えられる.便利なので.
アセンブル時には,アセンブラがいい感じに解釈して元の命令に戻してくれる.
ではアセンブラが対応している擬似命令には何があるか,これはRISC-V ISA Specificationでなく,Non-ISAのカテゴリのRISC-V Assembly Programmer’s Manualに,ISA準拠の命令と共に書かれている.
RISC-V Assembly Programmer’s Manual
具体的なものを抜粋したのが以下の通り.
| 擬似命令 | 実態 | 意味 |
|---|---|---|
nop |
addi x0, x0, 0 |
nop |
li rd, immediate |
色々 | 即値ロード |
mv rd, rs |
addi rd, rs, 0 |
move命令 |
j offset |
jal x0, offset |
ジャンプ命令 |
ret |
jalr x0, x1, 0 |
Return |
上記の通り,nopやmv,ジャンプといった便利どころの命令は,すべて既存の命令とx0/zeroを組み合わせて実現される.
TBD
あとなんかある?サッと教えてくれれば書きます