| |
Hypnosis
Registered: Mar 2015 Posts: 36 |
Cycles to get into IRQ routine
How many cycles does it take from an IRQ trigger to the start of the IRQ routine, assuming the CPU finished the instruction when it triggers? It should be around 6-9 cycles but I'm not sure how many. |
|
... 53 posts hidden. Click here to view all posts.... |
| |
Flavioweb
Registered: Nov 2011 Posts: 463 |
Quoting Oswaldlast cycle of bne will check for irq condition, if bne finished then cpu jmps to irq, or why not ?
If branch isn't taken, last cycle is the second, if branch is taken, last cycle is the third (or the fourth if the page boundary is crossed)...
maybe that's the "problem" ... |
| |
MagerValp
Registered: Dec 2001 Posts: 1074 |
Quoting Oswaldthis still doesnt seem to make sence. last cycle of bne will check forr irq condition, if bne finished then cpu jmps to irq, or why not ?
Branches are special. Normally IRQs are evaluated before the last cycle, which for an untaken branch is the second cycle. When branches are extended to three cycles as they are taken, or four cycles when taken across a page boundary, the IRQ evaluation at the second cycle still triggers the IRQ.
I wonder if this is true also for other instructions that are extended on page crossing, such as LDA $FFFF,X. |
| |
Oswald
Registered: Apr 2002 Posts: 5086 |
okay, so IRQ is triggered, but not taken until BNE ends? or IRQ is taken at 2 cycle of a 4 cycle BNE, then how does the CPU find its way back to the middle of the BNE ? I dont think this latter one happens.
what exactly happens when an IRQ is evaluated ? I still dont get it how irq could be delayed to happen after the next instruction after the BNE, if it happens during a BNE. |
| |
Flavioweb
Registered: Nov 2011 Posts: 463 |
I suppose that BNE "decides" to execute next op during his second cycles, but as copyfault stated, additional cycles are "added" later... so cpu execute added operations then execute next op, like if irq is triggered on second as last cycle of bne. |
| |
lft
Registered: Jul 2007 Posts: 369 |
I think the key is to ask: Why is the interrupt inhibited during the second tentative opcode fetch, but not during the first?
That is, on a 4-cycle branch, we're performing two speculative opcode fetches before the third (correct) fetch. It appears that the first speculative fetch can be replaced with a BRK/IRQ (so the interrupt immediately follows a 2-cycle branch-not-taken). The third fetch can also be replaced (so the interrupt immediately follows a 4-cycle branch with page crossing). But the second is inhibited.
I think the answer has to do with how the PC register is updated. It can be incremented in a single cycle, or it can be loaded through the ALU in one or two cycles depending on whether there is a carry. The interrupt mechanism needs to push PC to the stack.
During a normal fetch, the PC reflects the value that needs to be pushed, so if the fetch is replaced with a BRK, we can presumably also inhibit the normal increment, and write the PC to the stack.
During the first tentative fetch, the PC also reflects the value that needs to be pushed if the branch is not taken---which we know at this point.
But during the second tentative fetch, the PC could be wrong. We have already written the PC LSB, so there's no way to go back; we have to do the carry-adjust (if ALU reports a carry). Thus, we cannot at this point push the PC to the stack. Actually, we could, but we'd have to take the carry signal from the ALU into consideration. I think, quite simply, that the design team were cutting corners here, and saving silicon by leaving out that special case.
So it boils down to this: We cannot divert an opcode fetch that follows a 3-cycle branch-taken, because we don't know yet whether this is a 4-cycle branch. And thus we could potentially be pushing an invalid return address.
But what about an infinite branch-to-self? Surely it can be interrupted? Has anybody investigated? |
| |
MagerValp
Registered: Dec 2001 Posts: 1074 |
What? No, the branch doesn't get split in two. Evaluation, that is whether an IRQ should be acted on, is separate from triggering. They don't happen at the same time. Roughly speaking IRQs and NMIs just force the CPU to execute a BRK instruction instead of the next opcode. The point is that IRQ evaluation happens one cycle earlier than what most programmers and emulator writers expect, and in the case of branch instructions even earlier in some cases. |
| |
lft
Registered: Jul 2007 Posts: 369 |
@MagerValp: I'm not sure if that was a response to my post, but here's what's confusing: Consider a 4-cycle branch. After fetching the branch opcode and the branch offset, there are three cycles in which the next opcode is fetched. The first two are thrown away. Of these three cycles, it appears that the first and the third can be diverted to interrupt handling (BRK). So there's a conspicuous gap in the middle, which cannot be explained simply by saying that the evaluation happens at some specific time. |
| |
MagerValp
Registered: Dec 2001 Posts: 1074 |
Quoting lftBut what about an infinite branch-to-self? Surely it can be interrupted? Has anybody investigated?
Of course. If I'm reading the 6502.org thread correctly the only gotcha is that if the IRQ is activated during cycle 3 of a taken branch it'll loop one more time before the IRQ handler is triggered, compared to an IRQ activating during other cycles.
Is there perhaps a test program in the VICE repo for this? |
| |
lft
Registered: Jul 2007 Posts: 369 |
This nesdev page is also interesting:
Quote:The branch instructions have more subtle interrupt polling behavior. Interrupts are always polled before the second CPU cycle (the operand fetch). Additionally, for taken branches that cross a page boundary, interrupts are polled before the PCH fixup cycle
This confirms the observed behaviour, but it doesn't explain the design rationale. My post is an attempt at that. |
| |
MagerValp
Registered: Dec 2001 Posts: 1074 |
Quoting lft@MagerValp: I'm not sure if that was a response to my post
No, that was a response to Oswald, your post happened while I was writing :) |
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 - Next |