Z80内存刷新寄存器
我再次提出另一个无害的 Z80 问题:-)我的模拟器核心当前的结构方式是,每次从内存中获取操作码字节时,我都会递增内存刷新寄存器的低 7 位 - 这意味着对于多字节指令,例如与那些开始 DD 或 FD 的指令一样,我将寄存器递增两次 - 或者在 RLC (IX+d) 等指令的实例中递增三次(正如它所布局的那样)操作码1-操作码2-d-操作码3)。
这是正确的吗?我不确定 - Z80 手册对此有点不清楚,因为它说 CPDR(双字节指令)将其递增两次,但是“内存刷新寄存器”部分仅说它在每次指令获取后递增。我注意到 J80(我检查过的模拟器,因为我对此不确定)仅在指令的第一个操作码字节之后递增。
哪个是正确的?我想这在任何情况下都不是很重要,但很高兴知道:-)非常感谢。
问候, 菲尔·波特
Me again with another innocuous Z80 question :-) The way my emulator core is currently structured, I am incrementing the lower 7 bits of the memory refresh register every time an opcode byte is fetched from memory - this means for multi-byte instructions, such as those that begin DD or FD, I am incrementing the register twice - or in the instance of an instruction such as RLC (IX+d) three times (as it is laid out opcode1-opcode2-d-opcode3).
Is this correct? I am unsure - the Z80 manual is a little unclear on this, as it says that CPDR (a two byte instruction) increments it twice, however the 'Memory Refresh Register' section merely says it increments after each instruction fetch. I have noticed that J80 (an emulator I checked as I'm not sure about this) only increments after the first opcode byte of an instruction.
Which is correct? I guess it is not hugely important in any case, but it would be nice to know :-) Many thanks.
Regards,
Phil Potter
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Zilog 时序图可以解答您的问题。
刷新发生在所有 M1(操作码获取)周期的 T3 和 T4 期间。
对于单操作码指令,每条指令刷新一次。对于单前缀指令(使用 M1 周期读取前缀),每条指令刷新两次。
对于那些奇怪的 DD-CB-disp-opcode 和 FD-CB-disp-opcode 类型指令(很奇怪,因为位移字节出现在最终操作码之前而不是之后),刷新次数为至少 3 个(对于两个前缀和最终操作码),但我不确定位移字节是否作为 M1 周期(这将触发另一次刷新)或正常内存读取周期(无刷新)的一部分读取。我倾向于相信位移字节是在这些指令的 M1 周期中读取的,但我不确定。我向肖恩·杨询问了此事;他也不确定。有谁确切知道吗?
更新:
我回答了我自己关于那些奇怪的 DD-CB-disp-opcode 和 FD-CB-disp-opcode 指令的问题。如果您检查 Zilog 的文档以获取这些类型的指令,例如
RLC (IX+d),您会注意到该指令需要 6 个 M 周期和 23 个 T 周期,细分为:(4,4,3,5,4,3)。
我们知道前两个 M 周期是 M1 周期,用于获取 DD 和 CB 前缀(每个周期 4 个 T 周期)。下一个M周期读取位移字节d。但该 M 周期仅使用 3 个 T 周期,而不是 4 个,因此它不可能是 M1 周期;相反,这是一个正常的内存读取周期。
以下是 RLC (IX+d) 指令的 6 个 M 周期的细分:
(RLC 计算与 M 周期 5 和 6 重叠。)
这些类型指令的独特之处在于它们唯一具有非连续 M1 周期(上述 M 周期 1、2 和 4)的 Z80 指令。他们也是最慢的!
保罗
The Zilog timing diagrams hold the answer to your question.
A refresh occurs during T3 and T4 of all M1 (opcode fetch) cycles.
In the case of single-opcode instructions, that's one refresh per instruction. For single-prefix instructions (prefixes are read using M1 cycles) that's two refreshes per instruction.
For those weird DD-CB-disp-opcode and FD-CB-disp-opcode type instructions (weird because the displacement byte comes before the final opcode rather than after it), the number of refreshes is at least 3 (for the two prefixes and final opcode), but I'm not sure if the displacement byte is read as part of an M1 cycle (which would trigger another refresh) or a normal memory read cycle (no refresh). I'm inclined to believe the displacement byte is read in an M1 cycle for these instructions, but I'm not sure. I asked Sean Young about this; he wasn't sure either. Does anyone know for certain?
UPDATE:
I answered my own question re those weird DD-CB-disp-opcode and FD-CB-disp-opcode instructions. If you check Zilog's documentation for these type instruction, such as
RLC (IX+d), you'll note that the instruction requires 6 M-cycles and 23 T-cycles broken down as: (4,4,3,5,4,3).
We know the first two M-cycles are M1 cycles to fetch the DD and CB prefixes (4 T-cycles each). The next M-cycle reads the displacement byte d. But that M-cycle uses only 3 T-cycles, not 4, so it can't be an M1 cycle; instead it's a normal Memory Read cycle.
Here's the breakdown of the RLC (IX+d) instruction's six M-cycles:
(The RLC calculation overlaps M-cycles 5 and 6.)
These type instructions are unique in that they're the only Z80 instructions that have non-contiguous M1 cycles (M-cycles 1, 2 and 4 above). They're also the slowest!
Paul
Sean Young 的 Z80 未记录功能有不同的故事。一次用于无前缀,两次用于单个前缀,两次用于双前缀(仅限 DDCB),一次用于无操作前缀。
当然,块指令每次运行时都会影响 R(并且它们运行 BC 次)。
Sean Young's Z80 Undocumented Features has a different story. Once for unprefixed, twice for a single prefix, also twice for a double prefix (DDCB only), and once for no-op prefix.
Block instructions of course affect R every time they run (and they run BC times).
我现在看到了一些评论,这些奇怪的 DDCB 和 FDCB 指令仅将 R 寄存器递增两次。
我一直假设(以及我实现 Z80 仿真器的方式)R 寄存器在每个 M1 周期结束时实现。
回顾一下,这些奇怪的 DDCB 和 FDCB 指令有四个字节长:
DD CB disp opcode
FD CB disp opcode
很明显,这两个前缀操作码是使用 M1 周期读取的,导致 R 寄存器在每个周期结束时递增。
同样清楚的是,CB 前缀后面的位移字节是通过正常的读取周期读取的,因此 R 寄存器在该周期结束时不会递增。
剩下最后的操作码。如果通过 M1 周期读取,则 R 寄存器在周期结束时递增,导致总共 3 个增量,或者 Z80 特殊情况在该 M1 周期中不递增 R 寄存器。
还有另一种可能。如果最终操作码是由正常的读取周期(如其前面的位移字节)而不是 M1 周期读取的,会怎样?当然,这也会导致 R 寄存器对于这些指令仅递增两次,并且不需要 Z80 例外,在每个 M1 周期结束时不递增 R 寄存器。
就 Z80 的内部状态而言,这可能也更有意义。一旦它切换到正常读取周期来读取指令的附加字节(在本例中为 CB 前缀后面的位移字节),它就不会切换回 M1 周期,直到开始下一条指令。
任何人都可以在真实的 Z80 硬件上对此进行测试,以确认遵循这些 DDCB 或 FDCB 指令之一的 R 寄存器的值吗?
I've seen a couple of comments now that these weird DDCB and FDCB instructions only increment the R register twice.
It's always been my assumption (and the way I implemented my Z80 emulator) that the R register is implemented at the end of every M1 cycle.
To recap, these weird DDCB and FDCB instructions are four bytes long:
DD CB disp opcode
FD CB disp opcode
It's clear that the two prefix opcodes are read using M1 cycles, causing the R register to be incremented at the end of each of those cycles.
It's also clear that the displacement byte that follows the CB prefix is read by a normal Read cycle, so the R register is not incremented at the end of that cycle.
That leaves the final opcode. If it's read by an M1 cycle, then either the R register is incremented at the end of the cycle, resulting in a total of 3 increments, or the Z80 special cases this M1 cycle and doesn't increment the R register.
There's another possibility. What if the final opcode is read by a normal Read cycle, like the displacement byte that preceded it, and not by an M1 cycle? That of course would also cause the R register to be incremented only twice for these instructions, and wouldn't require the Z80 to make an exception of not incrementing the R register at the end of every M1 cycle.
This might also make better sense in terms of the Z80's internal state. Once it switches to normal Read cycles to read an instruction's additional bytes (in this case the displacement byte following the CB prefix), it never switches back to M1 cycles until it starts the next instruction.
Can anyone test this on real Z80 hardware, to confirm the value of R register following one of these DDCB or FDCB instructions?
我可以在网上找到的所有参考文献都说 R 每条指令都会递增一次,无论其长度如何。
All references I can find online say that R is incremented once per instruction irrespective of its length.