Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete the support for NMOS/CMOS Z80 differences #35

Open
kosarev opened this issue Sep 3, 2021 · 2 comments
Open

Complete the support for NMOS/CMOS Z80 differences #35

kosarev opened this issue Sep 3, 2021 · 2 comments

Comments

@kosarev
Copy link
Owner

kosarev commented Sep 3, 2021

https://sinclair.wiki.zxnet.co.uk/wiki/Z80#Differences_between_NMOS_and_CMOS_Z80s says:

LD A,I and LD A,R bug
The NMOS Z80s suffer a problem whereby LD A,I and LD A,R record the state of IFF2 after it has been reset if an interrupt is delivered during that instruction. This behaviour, along with workarounds for this for use in interrupt handlers are documented in the Z80 Family Questions and Answers section of the Zilog Product Specifications Databook, and is useful for detecting the model of Z80 in use, so as to determine whether the CPU (assuming it is a genuine NMOS or CMOS Z80) provides an 'OUT (C),0' instruction (NMOS), or 'OUT (C),255' instead (CMOS).
http://z80.info/zip/ZilogProductSpecsDatabook129-143.pdf
(OCRed version: https://archive.org/stream/Zilog-Z80familyDataBook1989OCR/Zilog-Z80familyDataBook1989OCR_djvu.txt)

From the Q&A clause mentioned:

Q: I don't seem to get the correct state of the interrupts when using the LD A, I and LD A, R instructions to read the state of IFF2. Why is this? How can I get around this?
A: On CMOS Z80 CPU, we've fixed this problem. On NMOS Z80 CPU, in certain narrowly defined circumstances, theZ80CPU interrupt enable latch, IFF2, does not necessarily reflect the true interrupt status. The two instructions LD A, R and LD A, I copy the state of interrupt enable latch (IFF2) into the parity flag and modifies the accumulator contents (See table 7.0.1 in the Z80 CPU technical manual for details). Thus, it is possible to determine whether interrupts are enabled or disabled at the time that the instruction is executed. This facility is necessary to save the complete state of the machine. However, if an interrupt is accepted by the CPU during the execution of the instruction -- implying that the interrupts must be enabled -- the P/V flag is cleared. This incorrectly asserts that interrupts were disabled at the time the instruction was executed.

Related to #27.

@simonowen
Copy link
Collaborator

I wasn't aware of the difference in LD A,I / LD A,R behaviour in that case. I'll have to see if I can write a program to detect it, though the always-on RAM contention in the SAM Coupé makes it difficult to do single-cycle adjustments for this particular test.

Perhaps it could be implemented using a new handler that returns whether an interrupt is due in the next N cycles? Those instructions could then check ahead to see if they should change the result in the NMOS case. We need to know exactly when IFF2 is sampled within the instruction though.

@kosarev
Copy link
Owner Author

kosarev commented Sep 4, 2021

I understand we currently implement the CMOS behaviour. For NMOS, yes, we may need to change the way we initiate interrupts by letting the emulator know when ~INT is going to become active.

We need to know exactly when IFF2 is sampled within the instruction though.

If I remember it correctly that ~INT is being sampled during the last tick of instruction, then this suggests that we should get its value as it is at that last tick?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants