Palm OS Programmer’s Companion Volume I/14-4 - project-enigma

Palm OS Programmer’s Companion Volume I/14-4

>> Site top >> Misc >> In my palm >> Palm開発ドキュメントの和訳 >> Palm OS Programmer’s Companion Volume I >> Palm OS Programmer’s Companion Volume I/14-4

最終更新日付:2014/01/01 00:00:00

← 3 節に戻る ↑14 章トップへ 5 節に進む →

14-4 ARM ネイティブサブルーチンの作成

 

ARM ネイティブサブルーチンは、正しい形式のプロトタイプと必要な ARM コードが含まれている必要があります。サンプルの ARM ネイティブサブルーチンである armlet-simple.c は必要最小限のコードを示すために SDK に含まれています。

ARM ネイティブサブルーチンは Palm OS API 関数をコールすることもできますし、68K コードをコールバックすることもできます。414 ページの"ARM コードからの Palm OS API の呼び出し"を参照して下さい。SDK に含まれる armlet-oscall.c も、Palm OS 関数コールの例になっています。

以下のセクションでは、ARMネイティブサブルーチンの作成手順を説明しています。

  1. 68K アプリケーションのパフォーマンス上重要な部分を隔離する
  2. ARM ネイティブサブルーチンが引数を1つだけとるように修正する
  3. 68K と ARM の技術的な違いを処理する
  4. ARM ネイティブサブルーチンをテストする
  5. ARM ネイティブサブルーチンをビルドする
  6. 68KアプリケーションにARMコードを組み込む

 

68K アプリケーションのパフォーマンス上重要な部分を隔離する

どのアルゴリズムを ARM ネイティブサブルーチンにすれば良いかを決めるには、まず68Kアプリケーションのパフォーマンス分析から始める必要があります。68Kアプリケーションがパフォーマンステストの結果"十分に速く"動作しているのであれば、ARM ネイティブサブルーチンを作成する理由はありません。

オペレーティングシステムを何度もコールする関数は通常、ARM ネイティブ化の候補には適しません。なぜなら、アプリケーションの"68K側"と"ARM側"の同時デバッグは容易ではなく、またパラメータのバイトスワップにオーバーヘッドがかかるからです。

 

ARM ネイティブサブルーチンが引数を1つだけとるように修正する

PceNativeCall 関数は 68Kアプリケーションから ARM ネイティブサブルーチンをコールするのに使用する関数です。この関数は引数を2つしかとりません。ARM ネイティブサブルーチンのポインタとデータブロックを指すポインタです。結果的に、サブルーチンが入力パラメータを1つしかとらない場合が一番書き易いことになります。

68K側から呼ばれる ARM 関数 —— すなわち ARM コードのエントリとなる関数 —— のプロトタイプは、以下のようになっている必要があります( PceNativeCall.h で宣言されています) 。

typedef unsigned long NativeFuncType (const void *emulStateP,
                                      void *userData68KP, Call68KFuncType *call68KFuncP)

 

この関数のパラメータは以下のように定義されます。

→ emulStateP

PACE の(不透明な)エミュレーション状態を指すポインタ。このポインタは Palm OS 関数やアプリケーションコールバック関数をコールする際に使用します。詳細は"ARM コードからの Palm OS API の呼び出し"を参照して下さい。

←→ userData68KP

PceNativeCall 関数に渡した userDataP 引数が、ARM コードで直接デリファレンスできるようにバイトスワップされて渡されます。このポインタが指すデータブロックにアクセスする際の注意点については、"68K と ARM の技術的な違いを処理する"を参照して下さい。

→ call68KFunc

ARM コードから PACE がエミュレートする環境にコールバックするためのフックが指定されます。これは OS 関数とアプリケーションコールバックの両方で使用されます。詳細は"関数ポインタを使用した関数呼び出し"を参照して下さい。

 

ARM のエントリポイントとなる関数の名前は PNOMain でなければなりません。

IMPORTANT

ARM のエントリポイントとなる関数の名前が PNOMain でない場合、コンパイラは "***[ARMC1000.bin.elf]Error 1"というメッセージを出力します。Palm OS Developer Suite を使用して "Simple" テンプレートで "Managed Make 68K PNO C/C++ Project" を作成した場合、エントリポイント関数の名前を変更しないで下さい。

ARM のエントリポイント関数が返す値は呼出し元に戻されるため、68K側にとって重要な意味を持ちます。復帰値に意味がなければ0を返すようにして下さい。レジスタ A0 と D0 の両方にこの復帰値が設定されると、ポインタまたは即値の返却を想定するコードにとって意味があります。

※訳注

上の段落の最後の文が訳しきれません。原文は以下の通りです。

Both register A0 and D0 are set to this return value, making it meaningful to code that is expecting either a pointer or an immediate result.

 

68K と ARM の技術的な違いを処理する

ARM ネイティブサブルーチンをインプリメントする場合、68Kプロセッサと ARM プロセッサの違いを意識する必要があります。以下のセクションでは、ARM ネイティブサブルーチンを扱う上で必要ないくつかの技術的な留意点を説明します。

 

ビッグエンディアンとリトルエンディアン

68Kプロセッサの整数はビッグエンディアンであり、ARMプロセッサはリトルエンディアンです。ビッグリトルは、マルチバイト整数が保存される際のバイト順を示しています。ビッグエンディアンでは、最上位バイトが最初に配置され、リトルエンディアンでは最上位バイトが最後に配置されます。

このことは、2 バイトおよび 4 バイト整数が逆のバイト順で保存され、結果として ARM と 68K のプロセッサ間でデータを交換する際にバイトスワップをしなければならないことを意味します。エンディアンは 2 バイトおよび 4 バイト整数(ポインタを含む)のコンテキストにのみ関係します。文字列など、その他のデータ型はバイトスワップの必要はありません。

PACE は PceNativeCall 関数の userData68KP パラメータを自動的にバイトスワップするため、ARM 関数内で変更することなく直ちに参照することができます。PACE は呼び出し元関数に戻される 4 バイトの復帰値についても自動的にバイトスワップを行ないます。

PACE は userData68KP パラメータが指しているデータについてはバイトスワップを行ないません。これは、どのような種類のデータが渡されているかについて PACE は何も知らないためです。(バイトスワップする必要があるのは 2 および 4 バイト整数だけであることと、userData68KP パラメータは任意のデータ構造を指す単なるポインタに過ぎないことを思い出して下さい。)

 

ARMネイティブサブルーチンで使用するバイトスワップマクロ

Endianutils.h には、ARM ネイティブサブルーチンで 2 および 4 バイト整数のバイトスワップをするための便利なマクロが含まれています。

ByteSwap16(integer)

2 バイト(16ビット)整数値をバイトスワップします。

ByteSwap32(integer)

4 バイト(32ビット)整数値をバイトスワップします。

ARM ネイティブサブルーチンはデータブロック内の整数値を必要に応じてバイトスワップしなければなりません。

 

整数値のアライメント

ARM プロセッサでは、4 バイト整数は 4 バイト境界に揃えられていることが要求されます。68K プロセッサでは、偶数アドレスに揃えられていることだけが要求されます。

整数データのアライメントの違いに対応するには、以下の2つの選択肢があります。

  1. MemPtrNew を使用してデータをアロケートし、整数型データのアライメントに注意してデータ構造を定義します。MemPtrNew は常に 4 バイト境界に揃えられたアドレスを返すので、データが 4 バイト境界から始まることを確実にできます。ただし、データ自体が正しく揃えられていることにも注意しなければなりません。データオブジェクトを並べる場合、68K と ARM では 4 バイトオブジェクトが異なる方法で揃えられることを知っておく必要があります。この様子を表 14.1 に示します。4 バイトデータが正しく揃えられていない場合、ARM プロセッサは 4 の倍数アドレスを使用してデータにアクセスしようとし、結果としてデータの破損が発生します。
  2. 4 バイト整数値を使用する前にローカル変数にコピーします。Endianutils.h には 4 バイト変数をバイトスワップしながら読み込んだり書き込んだりするのに便利なマクロが含まれています。Read68KUnaligned32(address) は指定されたアドレスから値を読み込み、Write68KUnaligned32(address, value) は指定されたアドレスに指定された値を書き込みます。

表 14.1 デフォルトのデータオブジェクトアライメント

データオブジェクトのサイズ 68K プロセッサのアライメント ARM プロセッサのアライメント
1 バイト 任意のアドレス 任意のアドレス
2 バイト 2 バイトアライメント(偶数アドレス) 2 バイトアライメント(偶数アドレス)
4 バイト 2 バイトアライメント(偶数アドレス) 4 バイトアライメント(4 の倍数アドレス)

 

構造体のパッキング

異なるコンパイラは、互いに異なる方法で自動的に構造体のパッキングを行ないます。コンパイラによっては、指定されたオプションに従って構造体が与えられたバイト境界に揃うようにバイトパディングを行ないます。構造体を宣言する時、および構造体のローカルコピーを作成する場合は注意して下さい。

 

ARM ネイティブサブルーチンをテストする

ARM ネイティブサブルーチンは ARM ハードウェア上の Palm OS Garnet で動作します。しかし、Palm OS シミュレータでは ARM ネイティブコードは動作しません。そのかわり、シミュレータは Microsoft Windows 上で動作する Palm OS Garnet の実装を提供しています。その結果、シミュレータで ARM ネイティブサブルーチンをテストするには、対象のサブルーチンを Windows DLL としてビルドする必要があります。シミュレータの PACE実装は、サブルーチンコールを DLL 関数呼び出しとして認識します。

SDK には、サンプル ARM ネイティブサブルーチン(同じく SDK に含まれています)と同じ関数のエントリポイントを含む DLL をビルドするサンプルアプリケーションが含まれています。

DLL をコールする場合、PceNativeCall に渡す最初の引数は DLL とその中の実行されるエントリポイント関数の名前を NULL 文字で区切った NULL 終端文字列を指すポインタになります(例えば、文字列 "test.dll\0EntryPoint" を指すポインタ)。

デフォルトでは、シミュレータは PalmSim.exe が動作しているディレクトリ内で DLL を検索します。別の場所に DLL を配置したい場合、ARM ネイティブサブルーチン DLL 名をフルパスで指定する必要があります(例えば、"c:\\projects\\armletdll\\test.dll\0EntryPoint" )。

68K アプリケーションはプロセッサの種類をチェックしなければなりません。

上記以外の場合、68K アプリケーションはサブルーチンの 68K バージョンをコールすべきです。この場合、アプリケーションは古いバージョンの Palm OS で動作していると想定されます。

 

ARM ネイティブサブルーチンをビルドする

ARM ネイティブサブルーチンをビルドするには、ARM コンパイラを使用する必要があります。PalmSource 社は ARM コンパイラのサポートを提供していませんが、ARM Developer Suite (ADS) や gcc など、いくつかのコンパイラが利用できます。

コンパイルされた ARM ネイティブサブルーチンのオブジェクトファイルは、そのまま(raw)のバイナリファイルとして 68K アプリケーションにリンクされる必要があります。アドレスオフセットの計算は、通常エントリポイント関数がバイナリファイルの先頭に配置されるため簡単です。

 

68KアプリケーションにARMコードを組み込む

ARMバイナリの生成に使用した仕組みとは無関係に、それを .prc ファイルに組み込むには2つの異なる方法があります。

 

 

 

← 3 節に戻る ↑14 章トップへ 5 節に進む →

 

 


Copyright(C) 2005-2017 project-enigma.
Generated by CL-PREFAB.