PCEエミュを高速化したい - バンク切替をメモリコピーで実装しよう

前のエントリーで、PCEエミュのバンク切り替えをメモリコピーによって実装する話を書きました。
検討していくと、問題が発生するパターンがあることに気がつきました。

PCEのCPUであるHuC6280から見えるメモリ空間は、$0000-$FFFFの64KBです。
これを8個のバンクに分けて、8KBづつとっかえひっかえできるようになっています。
バンクを指定するために使用するのが、メモリマッピングレジスタで、8個あります。
MPR0からMPR7まであります。
これを使って、2MBまでメモリ空間を拡張しているわけです。

バンク切り替えにはTAM命令を使用します。
AレジにMPRに書き込みたい値を入れておいて、TAM #0-8のどれかを実行することでバンクが切り替わります。

私のエミュレータでは、このTAM命令を実行したタイミングで、8KBx2のメモリコピーによってバンク切り替えを実装しようとしています。
ここで問題となるのが、複数のMPRが同じメモリ領域を指していた場合です。
これはメモリコピーでは対処ができません。
バンク切り替えをポインタの入れ替えで実装している場合は問題になりません。


まあ、64KBしかない物理メモリ空間なのに、複数のMPRに同じ値をいれて、同じメモリをさすようなもったいない使い方はまずしないはずなんですが、そういうことをやっているソフトが全く無い保証はないわけです。


これをどうしようか考えてます。


複数のMPRに同じ値が書き込まれていた場合、つまり同じメモリ領域を指している場合で、ここに書き込みが発生した場合に問題が起きるわけです。
これはかなり稀な使い方だとは思われます。
これは特殊な方法で拾うしかないかなと思います。

まず、メモリマッピングレジスタ(MPR0〜MPR7)を、書き込みと読み込みで2系統に分けます。
これらを、W_MPR0〜W_MPR7、R_MPR0〜R_MPR7という名前で呼ぶことにします。
基本的には、対となる書き込み用と読み込み用では、まったく同じ値が格納されます。
TAM #0を命令を実行したときに、W_MPR0とR_MPR0の両方にAレジスタの値を入れるわけですね。

違ってくるのは、TAM命令を実行したときに、同じ値になっているMPRがすでに存在した場合です。
この場合は、そのメモリ領域に対する書き込みをハンドリングしたいため、W_MPRにはメモリ範囲外となる値を書きこんでおきます。
つまり、読み込みは普通に行えますが、書き込みでは例外を発生させるわけです。
例外を使ってハンドリングし、そのメモリ書き込みを複数のメモリへ反映させます。

かなりきわどい実装ですが、これでなんとか回避できそうです。