現在工事中・・・。
ROM, EWRAM, IWRAMにそれぞれ同一のコードを置いた時のベンチマークを以下に表します。内容はVBLANK期間に変数のインクリメントしているだけです。インクリメント変数はs32を使用しており、CPUの1秒間(16,777,216)より小さい(溢れることはない)ということに一応ご留意ください。
s32 CodeRom(void) { while(*(vu16*)0x4000006 < 160) {}; s32 ret = 0; while(*(vu16*)0x4000006 >= 160) { ret++; } return ret; } //--------------------------------------------------------------------------- EWRAM_CODE s32 CodeEwram(void) { // 上記の処理と同じ } //--------------------------------------------------------------------------- IWRAM_CODE s32 CodeIwram(void) { // 上記の処理と同じ }
生成されたthumbコードは全て同一であり、それぞれ適切な領域に格納されていることを確認しています。
一部抜粋(ROM領域) 08000CA4 4A06 ldr r2,=Lxx_4000006h ;9 115 08000CA6 8813 ldrh r3,[r2] ;4 119 08000CA8 2B9F cmp r3,9Fh ;2 121 08000CAA D9FC bls Lxx_8000CA6h ;8 129 08000CAC 8813 ldrh r3,[r2] ;4 133 08000CAE 2000 movs r0,0h ;2 135 08000CB0 2B9F cmp r3,9Fh ;2 137 08000CB2 D904 bls Lxx_8000CBEh ;8 145 08000CB4 4A02 ldr r2,=Lxx_4000006h ;9 154 08000CB6 8813 ldrh r3,[r2] ;4 158 08000CB8 3001 adds r0,1h ;2 160 08000CBA 2B9F cmp r3,9Fh ;2 162 08000CBC D8FB bhi Lxx_8000CB6h ;8 170 08000CBE 4770 bx r14 ;8 178 08000CC0 0006 movs r6,r0 ;2 180 08000CC2 0400 lsls r0,r0,10h ;2 182
エミュレータ画面ですが、実機(初代GBA、GBA SP)と同じ値になっています。まず1番目の「REG_WSCNT = 0x0000」についてはカードリッジ実行直後の値で、2番目の「REG_WSCNT = 0x4317」は一般的な市販ゲームで使用されている設定値です。ここで理解してほしいことは0x4317 ROMは、0x4317 EWRAMに比べて1.42倍速いことです(5974 / 4181)。また、0x4317 ROMは0x0000 ROMに比べて1.71倍(5974 / 3484)速い、ということもわかります。IWRAMはどちらも非常に高速です。
ROMはプリフェッチ機能がある為、たまたま良いアクセスを引いただけと思われるかもしれません。なので無効化した状態を3番目「REG_WSCNT = 0x0317」に用意しました。プリフェッチをOFFにしてもEWRAMが優位になることはなく(4646 vs 4181)EWRAMにコードを置くことは選択肢としてないということがわかります。EWRAMはマルチブート用か、何かROMで動かせない場合に限ります。
変数については以下のように考えてください。リードオンリーな定数はROMか高速なIWRAM、EWRAMは選択外。読んだり書いたりする変数はIWRAMかEWRAMということになります。とりあえずIWRAMに全て投げて、mapファイルを見て考えるというムーブを個人的にしています。
wikiでは昔からEWRAM_CODEの使用をROMより優位として紹介しており、間違った説明をしていました。申し訳ありませんでした。ドキュメントとチュートリアルは既に修正していますがサンプルプログラムはあまりの数に断念しています。もし仮に読むようなことがある場合は注意のほどお願いいたします。