ARM Linux ディストリビューションでの浮動小数点のサポートは簡単ではありません。そのため、オペレーティング システムとハードウェアであるシステムに一致するツールチェーンを使用し、適切なコンパイル スイッチを使用する必要があります。
まず、「関数を呼び出すときに引数を渡す方法」に関する ARM の呼び出し規則を理解する必要があります。. ARM は RISC アーキテクチャであるため、レジスタでのみ動作します。メモリを直接操作する命令はありません。メモリ内の値を変更する必要がある場合は、最初にそれをレジスタにロードし、変更してからメモリに保存する必要があります。
関数を呼び出すときに引数を渡す必要がある場合は、引数をスタック (メモリ) に置くことができますが、ARM はレジスタでしか動作しないため、関数が最初に行うことはおそらくそれらをレジスタにロードすることです。この無駄を避けるために、ARM 呼び出し規約はレジスタを使用して引数を渡します。ただし、ARM には限られた数のレジスタがあるため、呼び出し規約では、最初の 4 つの引数に最初の 4 つ (r0-r3) のレジスタのみを使用するように指示されており、残りは渡されるためにスタックを使用する必要があります。
2 つ目は、初期の ARM コアには浮動小数点がサポートされておらず、操作がソフトウェアで実装されていたことです。(これは、gcc の を介してまだサポートされているものです-mfloat-abi=soft。)
次のスニペットを使用して、これが何を意味するかを簡単に示すことができます。
float pi2(float a) {
return a * 3.14f;
}
-c -O3 -mfloat-abi=softこれを viaとobdumpingでコンパイルすると、
00000000 <pi2>:
0: f24f 51c3 movw r1, #62915 ; 0xf5c3
4: b508 push {r3, lr}
6: f2c4 0148 movt r1, #16456 ; 0x4048
a: f7ff fffe bl 0 <__aeabi_fmul>
e: bd08 pop {r3, pc}
ご覧のとおり (実際には表示されません:))pi2でパラメータを取得しr0、入力pi constantしr1て使用__aeabi_fmulし、それらを乗算して結果を で返しr0ます。も同じ呼び出し規約を使用しているため__aeabi_fmul、詳細r0は表示されません。すべての関数は、データを入力r1して に委譲するために行い__aeabi_fmulます。
フローティング ハードウェア サポートが ARM に追加されたとき (これもアーキテクチャ スタイルのため)、独自のレジスタ セット(s0、s1、...)が付属していました。
同じスニペットをコンパイルし-c -O3 -mfloat-abi=softfpてダンプすると、
00000000 <pi2>:
0: eddf 7a04 vldr s15, [pc, #16] ; 14 <pi2+0x14>
4: ee07 0a10 vmov s14, r0
8: ee27 7a27 vmul.f32 s14, s14, s15
c: ee17 0a10 vmov r0, s14
10: 4770 bx lr
12: bf00 nop
14: 4048f5c3 .word 0x4048f5c3
ご覧のとおり、コンパイラは への呼び出しを作成しません__aeabi_fmulが、代わりに、 にvmul.f32ある引数を に移動しr0てs14に入力3.14した後に命令を作成しs15ます。乗算命令の後、呼び出し規約により、この関数の呼び出し元はそれを期待するため、s14利用可能な結果を元に戻します。r0
サードパーティから提供されたライブラリと考えるpi2と、soft 実装と softfp 実装の両方が同じことを行い、それらを交換可能に使用できることが理解できます。システムがそれらを提供する場合、アプリがハードウェア浮動小数点をサポートするシステムで実行されるかどうかは気にしません。これは、古いソフトウェアを新しいハードウェアで実行し続けるのに非常に役立ちました。
ただし、互換性を維持しながら、このアプローチでは、ARM レジスタと FP レジスタ間で値を移動するオーバーヘッドが発生します。これは明らかにパフォーマンスに影響し、 によって呼び出される新しい呼び出し規約によって対処さhardれgccます。この新しい規則は、関数に浮動小数点引数がある場合、通常の浮動小数点レジスタとインターリーブされた浮動小数点レジスタを利用できること、および浮動小数点レジスタで浮動小数点値を返すことができることを示していますs0。
スニペットをコンパイルし-c -O3 -mfloat-abi=hardてダンプすると、次のようになります。
00000000 <pi2>:
0: eddf 7a02 vldr s15, [pc, #8] ; c <pi2+0xc>
4: ee20 0a27 vmul.f32 s0, s0, s15
8: 4770 bx lr
a: bf00 nop
c: 4048f5c3 .word 0x4048f5c3
レジスタが移動していないことがわかります。への引数pi2が渡されs0、コンパイラが作成したコードを入力3.14し、必要な結果を取得するためにs15使用します。vmul.f32 s0, s0, s15s0
この新しい規則の大きな問題は、コンパイラによって生成されたコードを改善すると、互換性が完全に失われてしまうことです。hard規則soft/softfpに従って構築されたアプリケーションが、ハード向けに構築されたライブラリで動作することを期待することはできません。
呼び出し規則の詳細については、ARM の Web サイトを確認してください。