6

空き時間に、6502 CPU 用の非常に単純な C++ エミュレーターを書き始めています。私はこの CPU のアセンブリ コードをたくさん書き留めていたので、すべてのオペコード、アドレッシング モード、その他のものは大したことではありません。

6502 には 56 の異なる命令と 13 のアドレッシング モードがあり、合計 151 の異なるオペコードを提供します。私にとって速度は問題ではないので、巨大な switch-case ステートメントを記述して同じコードを何度も繰り返す代わりに (異なるオペコードは異なるアドレッシング モードを使用して同じ命令を参照できます)、実際の命令コードをアドレッシング モードのコード: このソリューションは、13 個のアドレッシング モード関数と 56 個の命令関数を繰り返すだけでよいため、非常に優れていることがわかりました。

ここでアドレッシングモード機能:

// Addressing modes
uint16_t Addr_ACC(); // ACCUMULATOR
uint16_t Addr_IMM(); // IMMEDIATE
uint16_t Addr_ABS(); // ABSOLUTE
uint16_t Addr_ZER(); // ZERO PAGE
uint16_t Addr_ZEX(); // INDEXED-X ZERO PAGE
uint16_t Addr_ZEY(); // INDEXED-Y ZERO PAGE
uint16_t Addr_ABX(); // INDEXED-X ABSOLUTE
uint16_t Addr_ABY(); // INDEXED-Y ABSOLUTE
uint16_t Addr_IMP(); // IMPLIED
uint16_t Addr_REL(); // RELATIVE
uint16_t Addr_INX(); // INDEXED-X INDIRECT
uint16_t Addr_INY(); // INDEXED-Y INDIRECT
uint16_t Addr_ABI(); // ABSOLUTE INDIRECT

それらはすべて、オペランド/結果を読み書きするために命令によって使用される実際のメモリアドレス(16ビット)を返します

命令関数のプロトタイプは次のとおりです。

void Op_ADC(uint16_t addr);
void Op_AND(uint16_t addr);
void Op_ASL(uint16_t addr);
    ...

16 ビット アドレスを取得し、独自の操作を実行し、ステータス フラグやレジスタを更新し、結果 (存在する場合) を同じメモリ アドレスにコミットします。

そのコード フレームワークを考えると、メモリ アドレスの代わりに A 内部レジスタの実際の値を返す唯一のモードである ACCUMULATOR アドレッシング モードを使用するのが難しいことがわかりました。uin16_t 戻り値の型を使用して A の値を返し、そのようなアドレス指定モードのブール値フラグを追加することもできますが、それは非常に醜い解決策だと思います。

命令関数は、アドレッシング モードに完全に依存しない必要があります。

4

1 に答える 1

4

Sharp6502 (C# で記述された私の 6502 エミュレーション エンジン) では、内部レジスタと外部メモリの両方をファースト クラス オブジェクトとして扱います。したがって、メモリ アクセスとレジスタ アクセスは、どちらも基本的にはインデックスに従って MemoryManager を介して参照されるため、機能レベルでは同一です。

アドレスモードの区別は、エミュレーション中の命令のビットパターンをフィルタリングし、非常に単純な計算を実行して、MemoryManager に渡すインデックスを決定するだけの問題です。基本的なメカニズムは、すべての命令で同じです。

于 2013-11-24T09:53:16.247 に答える