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 内部寄存器的实际值而不是内存地址的模式。我可以使用 uin16_t 返回类型返回 A 的值,并为这种寻址模式添加一个布尔标志,但我发现它是一个非常丑陋的解决方案。

指令功能应该完全与寻址模式无关。

4

1 回答 1

4

在 Sharp6502(我用 C# 编写的 6502 仿真引擎)中,我将内部寄存器和外部存储器都视为一流的对象 - MemoryManager 类为外部存储器实例化一个对象,为内部寄存器实例化另一个对象,映射到不同的数字范围。因此,内存访问和寄存器访问在功能级别上是相同的,因为它们都是通过 MemoryManager 根据基本上是索引的方式引用的。

地址模式区分只是过滤仿真指令的位模式并执行非常简单的计算以确定要传递给 MemoryManager 的索引的问题——这可能是隐含的,或者需要一个或两个额外的字节,但是每条指令的底层机制都是相同的。

于 2013-11-24T09:53:16.247 回答