ARM C 呼び出し規約で保存するレジスタは?

コンパイルするプラットフォームの ABI によって異なります。 Linux には 2 つの ARM ABI があります。古いものと新しいもの。私の知る限り、新しいもの(EABI)は実際にはARMのAAPCSです。完全な EABI 定義は現在、ARM のインフォセンターにあります。

AAPCS から、§5.1.1:

  • r0-r3 引数とスクラッチ レジスタです。 r0-r1 結果レジスターでもあります
  • r4-r8 呼び出し先保存レジスタです
  • r9 呼び出し先保存レジスタであるかどうか (AAPCS の一部のバリアントでは特殊レジスタ)
  • r10-r11 呼び出し先保存レジスタです
  • r12-r15 特殊レジスタです

呼び出し先保存レジスタは、呼び出し先によって保存される必要があります (呼び出し元がレジスタを保存する呼び出し元保存レジスタとは対照的に)。そう、もし これはあなたが使用している ABI です。別の関数を呼び出す前に r10 を保存する必要はありません (別の関数がそれを保存します)。

編集: どのコンパイラを使用しても違いはありません。特に gcc は、いくつかの異なる ABI 用に構成でき、コマンド ラインで変更することもできます。それが生成するプロローグ/エピローグ コードを見ることは、各関数 および に合わせて調整されているため、あまり役に立ちません。 コンパイラは、レジスタを保存する他の方法を使用できます (たとえば、関数の途中で保存するなど)。

用語:"callee-save" は "non-volatile" または "call-preserved" の同義語です:callee および caller の保存レジスタとは何ですか?
関数呼び出しを行うとき、r4-r11 の値 (おそらく r9 を除く) は (call-preserved) 後も存在するが、r0-r3 (call-clobbered / volatile) の値は存在しないと想定できます。


32 ビット ARM 呼び出し規約は AAPCS によって指定されています

AAPCS から、§5.1.1 コア レジスタ:

  • r0-r3 引数とスクラッチ レジスタです。 r0-r1 結果レジスターでもあります
  • r4-r8 呼び出し先保存レジスタです
  • r9 呼び出し先保存レジスタであるかどうか (AAPCS の一部のバリアントでは特殊レジスタ)
  • r10-r11 呼び出し先保存レジスタです
  • r12-r15 特殊レジスタです

AAPCS から、§5.1.2.1 VFP レジスタの使用規則:

  • s16–s31 (d8–d15, q4–q7) 保存する必要があります
  • s0–s15 (d0–d7, q0–q3) および d16–d31 (q8–q15) 保存する必要はありません

元の投稿:
arm-to-c-calling-convention-neon-registers-to-save


64 ビット ARM 呼び出し規約は AAPCS64 によって指定されています

汎用レジスタ セクションでは、保持する必要があるレジスタを指定します。

  • r0 -r7 パラメータ/結果レジスタです
  • r9 -r15 一時レジスターです
  • r19 -r28 呼び出し先保存レジスタです。
  • その他すべて (r8r16 -r18r29r30SP ) には特別な意味があり、一時レジスタとして扱われるものもあります。

SIMD および浮動小数点レジスターは、Neon および浮動小数点レジスターを指定します。


64 ビット ARM、A64 の場合 (ARM 64 ビット アーキテクチャのプロシージャ コール標準より)

A64 命令セットから見える 31 個の 64 ビット汎用 (整数) レジスタがあります。これらは r0-r30 とラベル付けされています . 64 ビットのコンテキストでは、これらのレジスタは通常 x0-x30 という名前を使用して参照されます; 32 ビットのコンテキストでは、レジスタは w0-w30 を使用して指定されます .さらに、スタック ポインタ レジスタ、SP 、限られた数の命令で使用できます。

  • SP スタック ポインター
  • r30 LR The Link Register
  • r29 FP フレーム ポインター
  • r19…r28 呼び出し先保存レジスタ
  • r18 必要に応じて、プラットフォーム レジスター。それ以外の場合は一時登録
  • r17 IP1 2 番目のイントラ プロシージャ コール一時レジスタ (コール ベニアおよび PLT コードで使用可能)。それ以外の場合は、一時的なレジスターとして使用できます。
  • r16 IP0 最初のイントラプロシージャ コール スクラッチ レジスタ (コールベニアおよび PLT コードで使用できます)。それ以外の場合は、一時的なレジスターとして使用できます。
  • r9…r15 一時レジスター
  • r8 間接結果ロケーション レジスタ
  • r0…r7 パラメータ/結果レジスタ

最初の 8 つのレジスタ、r0-r7 、引数値をサブルーチンに渡し、関数から結果値を返すために使用されます。また、ルーチン内で中間値を保持するために使用することもできます (ただし、一般的には、サブルーチン呼び出し間のみ)。

r16 (IP0) を登録します および r17 (IP1) ルーチンとそれが呼び出すサブルーチンとの間のスクラッチ レジスタとしてリンカによって使用される場合があります。また、サブルーチン呼び出し間の中間値を保持するために、ルーチン内で使用することもできます。

レジスタ r18 の役割 プラットフォーム固有です。プラットフォーム ABI で、プロシージャ間の状態 (スレッド コンテキストなど) を運ぶ専用の汎用レジスタが必要な場合は、その目的のためにこのレジスタを使用する必要があります。プラットフォーム ABI にそのような要件がない場合は、追加の一時レジスタとして r18 を使用する必要があります。プラットフォーム ABI 仕様は、このレジスターの使用法を文書化する必要があります。

SIMD

ARM 64 ビット アーキテクチャには、さらに 32 個のレジスタ v0-v31 があります。 、SIMD および浮動小数点演算で使用できます。レジスタの正確な名前は、アクセスのサイズを示すように変更されます。

注: AArch32 とは異なり、AArch64 では、SIMD および浮動小数点レジスタの 128 ビットおよび 64 ビット ビューは、より狭いビューで複数のレジスタと重複しません。したがって、q1、d1、および s1 はすべて、銀行を登録してください。

最初の 8 つのレジスタ、v0-v7 、引数値をサブルーチンに渡し、関数から結果値を返すために使用されます。また、ルーチン内で中間値を保持するために使用することもできます (ただし、一般的には、サブルーチン呼び出し間のみ)。

v8-v15 を登録します サブルーチン呼び出し間で呼び出し先が保持する必要があります。残りのレジスタ (v0-v7、v16-v31 ) 保持する必要はありません (または、呼び出し元が保持する必要があります)。さらに、v8-v15 に保存されている各値の下位 64 ビットのみ 保存する必要があります。より大きな値を保持するのは呼び出し元の責任です。