ARMで使われる二つのABIARM用のバイナリで使用されるABI(Application Binary Interface)には、OABIとEABIの二つがあります。'O'は'Old'を、'E'は'Embedded'を意味します。EABIは、ARM社のドキュメントでは"the ABI for the ARM Architecture"として記述されます。 DebianではOABIは"arm"、EABIは"armel"として記述します("armeb"というものもありますが、これは Big Endian ARMを表します)。Debian Etchまではarm(OABI)版しかありませんでしたが、Debian Lennyはarmel(EABI)版が提供されるなど徐々にEABIを採用する機会が増えてきています。 本ページでは、OABIとEABIの違いや使用する際の注意点を紹介します。 EABIのメリットOABIと比較したとき、EABIには以下のようなメリットがあります。 - 浮動小数点演算がとても速くなる
- 効率的なシステムコール
- ソフトフロートとハードフロートのバイナリを混ぜることができる(OABIでは、混ぜることはできませんでした)
- OABIのユーザランドプログラムもEABIカーネル上で動作させることができる
参照: http://www.oesf.org/index.php?title=Q3:_What_are_OABI_and_EABI%3F 総じて処理速度が上がるというメリットがある一方で、可搬性は保たれています。いくつかあるEABIのメリットの中で、個人的には浮動小数点演算高速化がEABI採用の一番の理由だと思います。 OABIではデフォルトでハードフロートが使われることが一般的でした。ハードフロートでは、ターゲットのチップが浮動小数点演算ユニットを持っていて、かつ、それが有効になっていれば、高速に浮動小数点演算をおこなうことができます。対して、浮動小数点演算ユニットがないチップで浮動小数点演算をおこなうと、浮動小数点演算命令のたびに FPEによるコンテキストスイッチが行われるため、非常に効率が悪くなります。ARMは組み込み用途に使われることが多いため、浮動小数点演算ユニットを持っていないチップというのも多数存在します。また、チップによっては浮動小数点演算ユニットが載っていても、バグがあって使えないということもあったりします。そのため、OABIでは浮動小数点演算の速度が出ないことが問題になることがありました。 EABIでは浮動小数点演算を含むプログラムをコンパイルしたとき、浮動小数点演算命令をソフトウェアでエミュレーションするライブラリを使用します。そのため、コンテキストスイッチが発生せず、浮動小数点演算が高速におこなわれます。 OABIと比較した場合、EABIの方が 10倍以上高速になるという結果も報告されています。 EABIを使用するにはEABIのバイナリを作成するには、EABI用のツールチェイン(gccは4.1以降)を使用してソースコードをコンパイルする必要があります。EABI用のツールチェインのインストール方法は、「 ARMクロス開発環境構築」のページを参照してください。 また、EABIのバイナリを実行するには、カーネルがEABI対応していなければなりません。カーネルをEABI対応にするには、カーネルコンフィグレーションでCONFIG_AEBAIを有効にしてEABI対応のツールチェインでカーネルをコンパイルしなおす必要があります。OABIカーネルでEABIのユーザランドアプリケーションプログラムを実行することはできませんが、EABIカーネルでCONFIG_OABI_COMPATが有効になっている場合は、OABIのユーザランドアプリケーションプログラムを実行することができます。ただし、その場合、多少の効率性を犠牲にすることになります。 比較同じコードをOABIとEABIでコンパイルしてみて、比較してみます。 サンプルコードは以下のものを使用します。逆アセンブルしたときに見やすいように、__attribute__((noinline))で関数がインライン展開されないようにしています。
サンプルコード#include <stdio.h>
double __attribute__((noinline)) float_mult(double a, double b) { return a * b; }
int main(int argc, char *argv[]) { double d;
d = float_mult(12.3, 98.7);
printf("%lf\n", d);
return 0; }
OABIとEABIそれぞれでコンパイルします。デバッグ情報を残すために、 -gオプションをつけています。
コンパイル(OABI)$ arm-linux-gnu-gcc (Debian 4.3.2-1.1) 4.3.2 Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ arm-linux-gnu-gcc -Wall -g sample.c -o oabi
コンパイル(EABI)$ arm-linux-gnueabi-gcc --version arm-linux-gnueabi-gcc (Debian 4.3.2-1.1) 4.3.2 Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ arm-linux-gnueabi-gcc -Wall -g sample.c -o eabi
objdumpを使用して、逆アセンブルします。-Sオプションを使用して対応するソースコード行も表示するようにしています。
逆アセンブル結果(OABI)$ arm-linux-gnu-objdump -S oabi ... (中略) ... double __attribute__((noinline)) float_mult(double a, double b) { 84f4: e1a0c00d mov ip, sp 84f8: e92dd810 push {r4, fp, ip, lr, pc} 84fc: e24cb004 sub fp, ip, #4 ; 0x4 8500: e24dd010 sub sp, sp, #16 ; 0x10 8504: e50b0018 str r0, [fp, #-24] 8508: e50b1014 str r1, [fp, #-20] 850c: e50b2020 str r2, [fp, #-32] 8510: e50b301c str r3, [fp, #-28] return a * b; 8514: ed1b9106 ldfd f1, [fp, #-24] 8518: ed1b8108 ldfd f0, [fp, #-32] 851c: ee110180 mufd f0, f1, f0 8520: ed2d8102 stfd f0, [sp, #-8]! 8524: e8bd0018 pop {r3, r4} } 8528: e92d0018 push {r3, r4} 852c: ecbd8102 ldfd f0, [sp], #8 8530: e24bd010 sub sp, fp, #16 ; 0x10 8534: e89da810 ldm sp, {r4, fp, sp, pc} ... (以下略) ...
OABIでは、float_mult()関数部分で 浮動小数点演算(mufd)をおこなっています。
逆アセンブル結果(EABI)$ arm-linux-gnueabi-objdump -S eabi ... (中略) ... double __attribute__((noinline)) float_mult(double a, double b) { 8460: e1a0c00d mov ip, sp 8464: e92dd810 push {r4, fp, ip, lr, pc} 8468: e24cb004 sub fp, ip, #4 ; 0x4 846c: e24dd014 sub sp, sp, #20 ; 0x14 8470: e50b001c str r0, [fp, #-28] 8474: e50b1018 str r1, [fp, #-24] 8478: e50b2024 str r2, [fp, #-36] 847c: e50b3020 str r3, [fp, #-32] return a * b; 8480: e24b001c sub r0, fp, #28 ; 0x1c 8484: e8900003 ldm r0, {r0, r1} 8488: e24b2024 sub r2, fp, #36 ; 0x24 848c: e892000c ldm r2, {r2, r3} 8490: eb000024 bl 8528 <__aeabi_dmul> 8494: e1a03000 mov r3, r0 8498: e1a04001 mov r4, r1 } 849c: e1a00003 mov r0, r3 84a0: e1a01004 mov r1, r4 84a4: e24bd010 sub sp, fp, #16 ; 0x10 84a8: e89d6810 ldm sp, {r4, fp, sp, lr} 84ac: e12fff1e bx lr ... (中略) ... 00008528 <__aeabi_dmul>: 8528: e92d4070 push {r4, r5, r6, lr} 852c: e3a0c0ff mov ip, #255 ; 0xff 8530: e38ccc07 orr ip, ip, #1792 ; 0x700 8534: e01c4a21 ands r4, ip, r1, lsr #20 8538: 101c5a23 andsne r5, ip, r3, lsr #20 853c: 1134000c teqne r4, ip 8540: 1135000c teqne r5, ip 8544: 0b000075 bleq 8720 <__aeabi_dmul+0x1f8> 8548: e0844005 add r4, r4, r5 854c: e0216003 eor r6, r1, r3 8550: e1c11a8c bic r1, r1, ip, lsl #21 8554: e1c33a8c bic r3, r3, ip, lsl #21 8558: e1905601 orrs r5, r0, r1, lsl #12 ... (以下略) ...
EABIでは、浮動小数点演算をおこなうのに__aeabi_dmulという関数を呼んでいます。そして、__aeabi_dmulはバイナリの中にスタティックリンクされています。浮動小数点演算ルーチンがユーザランドで実行されるバイナリに含まれたことで、浮動少数点演算ユニットがないチップでもFPE(Floating Point Emulation: カーネルで実行されるためコンテキストスイッチが発生し低速)を使用せずに、浮動少数点演算が行えます。 |