Question on interrupt delay when it interacts with different types of instructions

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

Post Reply
harukiZ
Posts: 1
Joined: Sun Feb 12, 2023 11:06 am

Question on interrupt delay when it interacts with different types of instructions

Post by harukiZ »

Hi, everyone

I am new here and recently tried to learn to implement a NES emulator for insterests.

And I am confused with the correct timing and delay caused by the interrupt interacted with different types of instructions.

I have read posts written by Blargg here:
Since the memory read latches data near the end of a cycle, my conclusion is that /NMI and /IRQ are checked near the middle of second from the last cycle of an instruction. For LDA absolute, this means the third cycle (1: opcode fetch, 2: low byte of address, 3: high byte of address, 4: read, 5: set flags). For NOP, this means the first cycle (1: opcode fetch, 2: dummy fetch, 3: nothing).
viewtopic.php?t=1965
My understanding is that interrupt is only polled at the second-to-last cycle of an instruction;
And for a 2-cycle instruction, the polling is at the end of its first cycle;

Also in consideration of what nesdev writes : both level detector and edge detector will raise the internal signal in the next cycle after they detected the level or edge of coming irq/nmi; which I referred below.

I know maybe I am wrong somewhere, but I think there is a problem on 2-cycle instructions.

I thought of a situation:
Assumed that a 2-cycle instruction CLD is encountered with an IRQ in its first opcode-fetch cycle,
and the interrupt disable flag is cleared,
and assume the irq line becomes active low at the first cycle of CLD (opcode fetch cycle);
then the level-detector should output an internal signal of pending irq during the second CLD cycle;

The question is :
If CLD only polls interrupt at the end of its first cycle, but the internal signal will be raise at the second cycle,
since the polling is before the internal signal raise,
this CLD will let the next instruction to execute before the interrupt sequence to run.
And this also means any other 2-cycle instructions are the same, whether or not it is a CLI.
This is apparently not true.

Code: Select all

   +--------------- if irq arrives at the first cycle, detected by level-detector and
   |    +---------- the internal signal output in the second cycle
   v    v
[cc1][cc2][...]
   ^
   +------ but if interrupt polling only occurs at the first cycle here, 
             it seems that any 2-cycle instruction will delay the irq;
It seems only IRQs comming BEFORE the first fetch cycle of a 2-cycle instruction will timely interrupt this 2-cycle instruction.

Code: Select all

   +--------------- only if irq arrives at one cycle before the first cycle
   |    +---------- the internal signal output in the first cycle
   v    v
[...][cc1][cc2]
   	^
   	+------ then if polling here, the irq can be triggered, and interrupt will not delay;


Then I read something written by GARTHWILSON at forum of 6502.org :
I found that whether the NMI line is doing a short negative pulse or a positive one, as long as the processor can see a high state at one phase-2 falling edge and a low state at the very next phase-2 falling edge, regardless of where those edges are in the progress of an instruction, the NMI is registered and the sequence will begin when the instruction is finished. IOW, it's not just the last ph2 falling edge of an instruction that looks at the NMI input (as I previously thought), but rather every ph2 falling edge.
http://forum.6502.org/viewtopic.php?t=2 ... ng%20edge.
My understanding is that : CPU will detect irq/nmi input at every cycle of an instruction, and will allow one instruction to finish before going to the interrupt sequence;

But this seems cannot explain that the hijack point on BRK is after its 4th cycle : only irq coming before the 4 cycle of BRK can effectively affect the interrupt handler that the BRK really read to PC;

I know my understanding about some above-mentioned concepts may be wrong.
So please let me ask some questions.

By refering to this piece of nesdev:
The IRQ input is connected to a level detector. If a low level is detected on the IRQ input during φ2 of a cycle, an internal signal is raised during φ1 the following cycle, remaining high for that cycle only (or put another way, remaining high as long as the IRQ input is low during the preceding cycle's φ2).
The output from the edge detector and level detector are polled at certain points to detect pending interrupts. For most instructions, this polling happens during the final cycle of the instruction, before the opcode fetch for the next instruction. If the polling operation detects that an interrupt has been asserted, the next "instruction" executed is the interrupt sequence.
My understanding is that :
On each cycle, CPU "DETECT" the IRQ input pin and raises an "INTERNAL SIGNAL" if it becomes active low level.
And then, CPU need to perform an individual "POLLING" operation on the "INTERNAL SIGNAL" outputted by level-detector to finally decide whether to go to the interrupt sequence right after finishing execution of the current instruction.
And this "POLLING" operation is performed only at a certain point per instruciton.

I would like to ask : if I am right about this, or is this "POLLING" operation is just the same concept as "DETECT" or "CHECK" on the IRQ/NMI line ?

Actually, I think about these things for a while, and did not figure anything out.

If the "POLLING" operation is individual, and is performed only at a certain point within an instruction, then it seems will encounter my above-mentioned situation, ie, all 2-cycle instructions will delay interrupt response, which is not true.
But if "POLLING" occurs every cycle, it can not explain the BRK hijack or taken branch delay situtions.

Could someone please illuminate on interrupt interaction. I appreciate all your replys.
Post Reply