プログラムを埋め込む際の制限と注意点

@分岐命令によるループの制限

分岐命令によるループとは、分岐命令で上方向へ処理を戻し
同じ処理を繰り返す物の事を指します
実例では、アイテムを持っているかどうかのチェックに
ループを使って各アドレスの個数を読み込んでいたり
自作プログラムの連続書き込み再現プログラムで使用するなど
ループはプログラムには欠かせない要素です。

しかし、困った事に分岐命令を使用したループには制限が存在し
ある特殊な条件下において、分岐命令のループが
設定された回数繰り返す前に終了してしまう場合があります
どうもバグが原因のようですが・・・

その特殊な条件というのが「ループさせた時の戻る命令数」で
分岐命令とループさせる先との間に、分岐命令を含め
6命令以上のスペースが必要になります
スペースと言っても別にnopにするという訳ではなく
間に命令が存在していても行数さえ空けば良いです。

〜ループ処理悪い例〜
    000F0000 lui t0, $0034 
    000F0004 addiu t1, zero, $001E
000F0008 addiu t2, zero, $270F
000F000C sw t2, $5678(t0)
000F0010 addiu t0, t0, $0004
000F0014 addiu t1, t1, $FFFF
000F0018 bne t1, zero, $000F0008

〜ループ処理良い例〜
    000F0000 lui t0, $0034 
    000F0004 addiu t1, zero, $001E
000F0008 addiu t2, zero, $270F
000F000C nop
000F0010 sw t2, $5678(t0)
000F0014 addiu t0, t0, $0004
000F0018 addiu t1, t1, $FFFF
000F001C bne t1, zero, $000F0008


高速化改造で使用するVSyncプログラムを見ると分かりますが
このループ制限に沿ってスペースが空けられています





Aプログラムエリアとデータエリアの境界線

自分でテーブル管理を作成したりする場合の注意点がこれで
プログラム部分とプログラムではない数値部分の境界線に
最低でも5つ以上のnop命令が必要になります。

実例ではゼノサーガエピソード1の
「特定キャラのステータスMAX」コードの

000F5000 lui t0,$0041
000F5004 ori t0,t0,$d800
  〜中略〜
000F5030 jr ra
--------------------------------
000F5100 0063270F
000F5104 03E703E7
000F5108 03E703E7
000F510C 00636363

点線部分から上がプログラムエリア
点線部分から下がプログラムではないデータエリアとなりますが
プログラム末尾の000F5030からテーブルまでの間に
5つ以上のnopがあるので動作に問題はありませんが
これがもし以下の様であるとnopが足りず不具合が出る可能性があります

000F5000 lui t0,$0041
000F5004 ori t0,t0,$d800
  〜中略〜
000F5030 jr ra
--------------------------------
000F5040 0063270F
000F5044 03E703E7
000F5048 03E703E7
000F504C 00636363


この制限の対策法はもう1つあり、プログラムとデータとの境界線に
「1つのnopとsync.p命令を入れる」という方法でも回避できます
しかし、コードにすると1行は余分に増えるのでオススメしません。