是否有可能在程序上确定特定指令在 6502 上占用的周期数?

Is it possible to procedurally determine the number of cycles a particular instruction takes on a 6502?

大多数仿真器存储特定指令在查找中花费的周期数 table,然后根据需要添加任何条件周期(例如,当跨越页面边界时)。

我想知道是否有一种方法可以仅根据寻址模式和内存在程序上确定一条指令将花费的周期数 reads/writes。

举个例子,我注意到所有使用立即寻址或相对寻址的指令都需要 2 个周期。

所有零页指令需要 3 个周期,如果就地更改内存,还需要额外的 2 个周期。

所有索引零页指令需要 4 个周期,如果就地更改内存,还需要 2 个周期。

...等等

那么,是否有一些完整记录的程序方法来确定上述指令的周期数?在这样的公式中是否存在会破坏确定性的例外情况?

是的——几乎所有准确的模拟器都是这样编写的*;参见 64doc.txt 等文件。它并不比简单的内存访问计数复杂多少——6502 将在每个周期执行一次内存访问,它通常可以在访问后的剩余周期内获得有意义的结果(即我稍微挥手以避免关于流水线和非流水线的讨论;请参阅文档)。

例如对于 ADC #54,处理器必须 (i) 读取操作码; (ii) 读取操作数。就是两个循环。

对于 ADC (), Y 那是:

  1. 读取操作码
  2. 读取操作数
  3. 从$32读取地址的低字节
  4. 从$33读取地址高字节,地址低字节加Y
  5. 读取自(地址高字节):(地址低字节+Y),因为只有时间执行低字节计算
  6. 哦,等等,如果有进位那么最后的结果是错误的,最好再读一遍。如果没有那就太好了,一切都很好,不要为这个循环而烦恼。

所以它是 5 或 6 个周期。

您始终可以将内存访问更多地模拟为逐步计时的事情,并将实际操作作为正交步骤执行。 read、write or read-modify-write 也很容易使用相同的逻辑:reads 和 write 的时序相同但是最后做不同的内存访问,tead-modify-writes 都是将读取的值写回一个周期一边算出真实的结果,一边写出真实的结果。

*) 因为同时执行所有内存访问,不包括任何多余的内存访问,所以将时间提前一点绝对与真正的硬件完全不同。一旦内存访问是对任何具有独立时间概念的东西——定时器或任何可能产生中断的东西,或者如果机器扫描 RAM 以获取其视频输出,则只是 RAM 本身,它就会让你失望;不要介意它要求您围绕 CLISEI** 等指令添加特殊情况。模拟器不再需要像 1990 年代那样构造。

**) IRQ 状态在每个操作的倒数第二个周期被采样。 CLISEI 在最后一个周期调整位。因此,即使中断挂起,CLI 也不会导致中断,直到 CLI 之后的指令之后。它本身可能是 SEI。因此,当中断挂起时,CLI/SEI 对应该导致在 SEI 执行后跳转到中断处理程序,并设置中断标志。如果您正在模拟 6502 的逐周期行为,这种情况自然会发生,如果您正在逐个操作和时间扭曲,这往往是一个巨大的黑客攻击。或者,更有可能的是,这样的模拟器只是简单地把行为弄错了。