仮想オペコード
AVR32 StudioについてくるGAS(Gnu ASM)には仮想オペコードというのがあり、これはAVR32 Architecture Manualに載っていない。それでいてプロジェクトのテンプレートに含まれているので、ソースコードを追っていると面食らってしまう。
仮想オペコードの情報は、AVR32 Studioインストール・ディレクトリのAVR Tools\AVR32 Toolchain\share\info\as.infoの「9.5.4 Opcodes」にある。infoファイルはテキスト・エディタでも見ることが出来るが、たしかフォーマットして表示するビューワinfoが必要となる。ところどころ「!」とか記号が出てくるが、これは文字ではなく、制御記号なのでエディタで見るときには無視する必要がある。
「9.5.4 Opcodes」に記述がある仮想オペコードは2つだけなので、ここにまとめておく。
LDA.W
lda.w REG, SYMBOL
この命令はSYMBOLのアドレスをREGにロードする。命令は、シンボルと定数プールへの相対距離、そして--picオプションに依存し、以下の内1つに評価される。
--pic の有無 | 評価条件 | 展開されるコード |
---|---|---|
無し | SYMBOLは十分小さな値と見なす。 | mov REG, SYMBOL |
「. - SYMBOL」は十分小さな値と見なす。 | sub REG, pc, . - SYMBOL | |
固定データ・プール(CPENT)は閉じられている。 | lddpc REG, CPENT ... CPENT: .long SYMBOL | |
その他(まだ実装していないが、たぶんその必要はない) | mov REG, lo(SYMBOL) orh REG, hi(SYMBOL) | |
有り | 「. - SYMBOL」は十分小さな値と見なす。 | sub REG, pc, . - SYMBOL |
オプション--linkrelaxが無い | ld.w REG, r6[SYMBOL@got] | |
その他 | mov REG, SYMBOL@got / 4 ld.w REG, r6[REG << 2] |
CALL
call SYMBOL
この命令は、SYMBOLで識別される関数呼び出しコードを挿入する。
--linkrelaxや--picのコマンド・オプションによるシンボルとの相対距離に依存した条件により、以下の1つに評価する。
SYMBOLが同一セクションかつ同一ファイルで定義されていて、かつ十分距離が小さいなら、rcall命令が挿入される。
rcall SYMBOL
それ以外で、--picオプションが無ければ次のようになる。
mcall CPENT ... CPENT: .long SYMBOL
最後に、--picオプションがあるなら、アセンブラはグローバル・オフセット・テーブルを経由した間接呼び出しを挿入する。
/* If `--linkrelax' not specified */ mcall r6[SYMBOL@got] /* If `--linkrelax' specified */ mov lr, SYMBOL@got / 4 ld.w lr, r6[lr << 2] icall lr
SYMBOLの最終値が決定した後、リンカは最適な選択肢により、上記のいくつかを変更するかもしれない。これらは削除できる余分な定数プールとGOTエントリを含んでいる。