🧸

RISC-VのCalling Convention

2023/08/03に公開

Calling Conventionとは

C ABIで関数を呼び出すときの規約です。主にCPUレジスタの使い方が示されています。
コンパイラツールチェインやライブラリはこれに沿うように作られています。
C以外の多くの言語でもC ABIでライブラリを呼び出す仕組みを備えています。
アセンブラ出力を見る時にはまずこのコーリングコンベンションを頭に入れておくとよいと思います。

こちらのドキュメントを元に書いています。この表もそこからの引用です。

x0(zero)は読んだらゼロ、書いたら無視されます。
x1(ra)は関数のリターンアドレス。
x2(sp)はスタックポインタ。
x3(gp)はグローバルポインタ。
x4(tp)はスレッドポインタ。
a0-a7は引数を渡すのに使われ、そのうちのa0, a1はリターン値の格納に使われます。
t0-t6はテンポラリレジスタ。関数内で自由に使うことができます。別の関数を呼んだ時には破壊されます。
s0-s11は保存レジスタ。関数を呼び出された側が保存します。
フロートのレジスタも同様で、
fa0-fa7は引数を渡すのに使われ、そのうちのfa0, fa1はリターン値の格納に使われます。
ft0-ft11はテンポラリレジスタ。
fs0-fs11は保存レジスタです。

zeroレジスタはハードウェア的にゼロに固定されています。
ra, sp, gp, tp はmain関数が呼び出された時点でランタイムにより適切な値がセットされています。

ポインタサイズの2倍のサイズの値は2つの偶数奇数のレジスタのペアに格納します。[1]
それ以上のサイズの値は参照渡しにします。
スタックポインタは16バイトにアラインされていることを維持することがコーリングコンベンションで定められています。[2]

関数の入り口

			 addi    sp, sp, -48  /* スタックポインタを16の倍数分ずらす */
                         sd      s0, 32(sp)   /* レジスタをスタックに保存 */
                         sd      ra, 40(sp)
                         sd      s1, 24(sp)
                         sd      s2, 16(sp)
                         sd      s3, 8(sp)
                         sd      s4, 0(sp)

関数の出口

                         mv      a0, zero     /* リターン値のセット */
                         ld      ra, 40(sp)   /* スタックからレジスタの復帰 */
                         ld      s0, 32(sp)
                         ld      s1, 24(sp)
                         ld      s2, 16(sp)
                         ld      s3, 8(sp)
                         ld      s4, 0(sp)
                         addi    sp, sp, 48   /* スタックポインタを元に戻す */
                         ret                  /* jr ra と同じ。リターンアドレスにジャンプ */

参考

https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
https://inst.eecs.berkeley.edu/~cs61c/resources/RISCV_Calling_Convention.pdf

関連

https://zenn.dev/tetsu_koba/articles/554cad6a46149e

脚注
  1. 例えばRV32で関数 void foo(int, long long)の場合では最初の引数はa0に入り、2番目はa2とa3のペアに入ります。a1は使われません。 ↩︎

  2. AArch64でもスタックポインタは16バイトにアラインされています。しかもAAarch64ではSPは専用レジスタなので16バイトの倍数以外の値をセットすると例外が発生するようになっています。 ↩︎

Discussion