C / C ++中的6502仿真器:如何将寻址模式代码与实际指令代码分开

时间:2013-11-23 15:38:24

标签: c++ assembly emulation addressing-mode 6502

在业余时间我开始为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位地址,执行自己的操作,更新状态标志和/或寄存器,并在同一存储器地址上提交结果(如果有的话)。

鉴于代码框架我发现很难使用ACCUMULATOR寻址模式,这是唯一一个返回A内部寄存器的实际值而不是内存地址的模式。我可以使用uin16_t返回类型返回A的值,并为这种寻址模式添加一个布尔标志,但我发现它是一个非常难看的解决方案。

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

1 个答案:

答案 0 :(得分:3)

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

地址模式区分只是在仿真下过滤指令的位模式并执行非常简单的计算来确定要传递给MemoryManager的索引 - 这可能是暗示的,或者需要进一步的一两个字节,但每个指令的底层机制都是相同的。