4.3.1. インターワーク用コードのコンパイル

--apcs /interwork コンパイラオプションを指定すると、もう一方のプロセッサ状態に合わせてコンパイルされたルーチンから呼び出すことができるルーチンを含む C および C++ モジュールを、ARM コンパイラでコンパイルできます。

armcc --c90 --thumb --apcs /interwork
armcc --c90 --arm --apcs /interwork
armcc --cpp --thumb --apcs /interwork
armcc --cpp --arm --apcs /interwork

Note

--arm がデフォルトオプションです。は拡張子が .c のファイルのデフォルトオプションは --c90 です。また、拡張子が .cpp のファイルのデフォルトオプションは --cpp です。

ARMv4T でインターワークさせるモジュールをコンパイルすると、生成されるコードのサイズが若干大きくなります。ARMv5 では違いはありません。

本体に関数呼び出しが含まれないリーフ関数の場合、コンパイラによって生成されるコードで唯一異なるのは、MOV pc,lrBX lr に置き換えられるという点です。MOV 命令では、必要な状態の切り替えを行うことができません。

Thumb モードの ARMv4T 用にビルドされた非リーフ関数では、コンパイラが、例えば以下のような 1 つの命令を

     POP  {r4,r5,pc}

以下のようなシーケンスに置き換える必要があります。

     POP  {r4,r5}	
     POP  {r3}	
     BX   r3

これによるパフォーマンスへの影響はほとんどありません。インターワークを使用するモジュールがないことが確実に分かっている場合を除き、ソースモジュールはすべてインターワーク用にコンパイルして下さい。

また、--apcs /interwork オプションを使用すると、モジュールのコンパイルによって生成されるコードエリアにインターワーク属性が設定されます。リンカでは、この属性を検出して適切なベニアを挿入します。

Note

ARMv4T 以前のアーキテクチャのプロセッサには BX 命令が実装されていません。そのため、インターワーク用にコンパイルされた ARM コードは、ARMv4T 以降でしか使用できません。

ベニアによって使用される容量を確認するには、--info veneers リンカオプションを使用して下さい。

C 言語を使用したインターワークのサンプル

Example 4.3 は、ARM サブルーチンのインターワーク呼び出しを実行する Thumb ルーチンを示しています。この ARM サブルーチン呼び出しによって、Thumb ライブラリ内の printf() のインターワーク呼び出しが実行されます。これら 2 つのモジュールは、thumbmain.c および armsub.c という名前で、主なサンプルディレクトリの ...\interwork に保存されています。

Example 4.3. 

     /*********************
     *       thumbmain.c  *
     **********************/
     #include <stdio.h>
     extern void arm_function(void);
     int main(void)
     {
          printf("Hello from Thumb\n");	
          arm_function();	
          printf("And goodbye from Thumb\n");	
          return (0);	
     }

     /*********************
     *        armsub.c    *
     **********************/
     #include <stdio.h>
     void arm_function(void)
     {
          printf("Hello and Goodbye from ARM\n");	
     }

上記のモジュールをコンパイルしてリンクするには

  1. 以下のように入力して、Thumb コードをインターワーク用にコンパイルします。

    armcc --thumb -c -g -O1 --apcs /interwork -o thumbmain.o thumbmain.c
    
  2. 以下のように入力して、ARM コードをインターワーク用にコンパイルします。

    armcc -c -g -O1 --apcs /interwork -o armsub.o armsub.c
    
  3. 以下のように入力して、オブジェクトファイルをリンクします。

    armlink thumbmain.o armsub.o -o thumbtoarm.axf
    

    または、以下のように入力して、インターワークベニアのサイズ(Example 4.4 参照)を確認します。

    armlink armsub.o thumbmain.o -o thumbtoarm.axf --info veneers
    

Example 4.4. 

    Adding TA veneer (4 bytes, Inline) for call to 'arm_function' from thumbmain.o(.text).
    Adding AT veneer (8 bytes, Inline) for call to '__0printf' from armsub.o(.text).
    Adding AT veneer (8 bytes, Inline) for call to '__rt_lib_init' from kernel.o(.text).
    Adding AT veneer (12 bytes, Long) for call to '__rt_lib_shutdown' from kernel.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '__aeabi_memclr4' from stdio.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '_mutex_initialize' from stdio.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '__rt_raise' from stdio.o(.text).
    Adding AT veneer (8 bytes, Inline) for call to '__raise' from rt_raise.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '__heap_extend' from malloc.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '__user_perproc_libspace' from malloc.o(.text).
    Adding TA veneer (8 bytes, Short) for call to '__rt_exit' from exit.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '_fp_init' from lib_init.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '__ARM_argv_veneer' from lib_init.o(.text).
    Adding TA veneer (4 bytes, Inline) for call to '_sys_exit' from abort.o(.text).

14 Veneer(s) (total 80bytes) added to the image.	
Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203GJ
Non-Confidential