NMOS6502 エミュレーターを複数のクラスにリファクタリングしている最中です。関数ジャンプ テーブルを定義する「オブジェクト指向」の方法があるかどうか疑問に思っていました。基本的に、CPU オブジェクトへの参照を持つ「CStackInstHandler」や「CArithmeticInstHandler」など、関連する CPU 操作のグループを分類するために個別の命令クラスを定義しました。各命令クラスは、抽象命令クラスから派生します。各派生命令クラスには、cpu オブジェクトのパブリック インターフェイスを使用して cpu の状態を変更する一連の関数があります。
uint8_t opcode = _memory->readMem(_cpu->getProgramCounter());
AInstructionHandler* _handler = _cpu->getInstHandler(opcode);
_handler->setCpu(&cpu);
_handler->setMemory(&memory);
_handler->execute(opcode);
問題は、実行時に、命令ハンドラーとそのハンドラーに定義された適切なメンバー関数をオペコードを使用して決定する必要があることです。
したがって、オペコードはメモリから読み取られ、CPU はテーブルを使用してオペコードを命令ハンドラー タイプにマップし、命令ハンドラーは同じオペコードを使用して正しい関数を選択します。各命令は、「実行」機能をオーバーライドします。例:
void CBranchInstHandler::execute() {
switch(_opcode) {
case 0x90:
this->BCC();
break;
case 0xb0:
this->BCS();
break;
case 0xf0:
this->BEQ();
break;
case 0x30:
this->BMI();
break;
case 0xd0:
this->BNE();
break;
case 0x10:
this->BPL();
break;
default:
break;
}
}
void CBranchInstHandler::BCC() {
uint16_t address = this->getAddress();
if(!_cpu->isCarry()) {
uint16_t pc = _cpu->getPC();
pc += address;
_cpu->setPC(pc);
}
}
/*more instruction specific functions...*/
最終的に 2 つのルックアップが発生しますが、そのうちの 1 つは冗長です。1 つはハンドラーを選択し、もう 1 つはハンドラー関数を選択します。これはこのタスクを達成するための間違った方法のように感じますが、非メンバー関数のグループに委譲するだけではない代替手段については確信が持てません。
誰かがこの問題について洞察を持っているかどうか疑問に思っています。基本的には、クラスをより小さなバイト (cpu クラスと命令クラスにリファクタリングされた命令メンバー関数を持つ cpu クラス) にリファクタリングしたいということですが、すべてのコンポーネントが非常に相互に関連しているため、同じことを繰り返す必要があります。冗長性が導入されます。
非オブジェクト指向の解決策は、これらの命令を cpu 参照を受け入れる非メンバー関数にすることです。次に、関数ジャンプ テーブルが定義され、命令が検索され、オペコードによってインデックス付けされて実行されます。
これは、オブジェクトでは実際には実用的ではないようです。すべての命令を静的にすることもできますが、これはポイントを逃しているようです。
接線的に関連する問題であっても、洞察や情報は非常に役立ちます。
ありがとう。