bfin-elf-asは、gnuツールチェーンのBlackfin用アセンブラです。おおよそVisualDSP++のアセンブラと同じですのでプログラムをVisualDSP++環境からgnu環境に移植するのは簡単でしょう。
アセンブル環境がbfin-elf-asあらかじめ宣言されているマクロの有無によって容易に知ることができます。
問題はVisualDSP++のアセンブラであるか否かを区別する方法です。VDSP++のアセンブラ・プリプロセッサは識別氏ASMをあらかじめ宣言します。ところがこのマクロはターゲットがADI DSPであることを宣言しているのかアセンブラ・ベンダーがADIであるのかがきちんと記述されていません。仕方がないので、Blackfin依存部2.0ではコマンドラインから__ECC__を宣言してコンパイラ同様に使っています。
TOPPERS/JSP for Blackfinでは、どちらも宣言されていない場合にエラーメッセージを表示するようにしています。
Blackfinの命令セットは32bit値のロード命令を持っていません。したがって、32bitの即値は、二つに分割してロードしなければなりません。
VisualDSP++の場合、これは簡単です。
// ラベルのアドレスをロード P0.L = lo( LABEL ); P0.H = hi( LABEL ); // 32bitのデータをロード R0.L = Lo( VALUE ); R0.H = hi( VALUE );
ロードするのがラベルであってもデータであっても組み込み関数lo(), hi()を使うことができます。しかしながら、bfin-elf-asはこれらの関数を用意していません。そこで次のようにします。
// ラベルのアドレスをロード P0.L = LABEL; P0.H = LABEL; // 32bitのデータをロード R0.L = ( VALUE ) & 0xFFFF; R0.H = ( VALUE >> 16) & 0xFFFF;
ラベルとデータで扱いが異なります。この二つを混同することは許されません。不便ですが、アセンブラの構造を考えてみればむしろ普通で、VisualDSP++のアセンブラががんばっているということでしょう。二つを書き分けるのは不便ですし、32bit即値ロードはバグの混入が多いところです。hi(), lo()は実装してほしいのですが、blackfin.uclinux.orgのHelp forumで提案したところ、そこまで互換性を追及する気はないとのことでした。
仕方がないので、TOPPERS/JSP のBlackfin依存部2.0では、LOADVALUE, LOADLABELマクロを用意して使い分けています。
VisualDSP++のCコンパイラは、出力オブジェクトのセクションとして大きく2種類を使います。
VisualDSP++のアセンブリ言語を使う場合には、これらにあわせてデータを配置するのが一番簡単な方法でした。
.section program; .section data1;
VisualDSP++の標準的な扱いでは、大域変数を初期化する場合もしない場合も同じセクションに配置し、初期値が指定されない場合は0で初期値を与えます。また、多くの組込み系と異なり、初期化を行った変数の値もどんどん変えていいことになっています。これはプログラムを高速RAMやSDRAMにロードしてから使うというDSPの文化の影響でしょう。
gnuツールチェーンでは、セクション配置は次のようになります。
VisualDSP++用に書いたプログラムを使う場合にはこういった点に気をつけて書き換えを行うことになります。
Blackfinのジャンプ命令はPC相対命令です。VisualDSP++では、設定にもよりますが次のように書いておけばショート・ジャンプかロング・ジャンプのうち適切なほうを使ってくれます。
jump label;
gnuツールチェーンは、2006年8月の段階でそこまで自動化していません。上のプログラムはショート・ジャンプに翻訳され、ディスティネーションが遠すぎるとエラーが発生します。その場合は次のようにロング・ジャンプを強制してください。
jump.x label;