| |
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 Copyfaultif the irq happens on the first cycle of a branch, it will be processed after the second cycle of the branch; but if an irq happens during the second cycle of a branch, processing is delayed until the end of the opcode following the branch instruction.
So, with this code
LOOP
INC $FFFF,X
DEX
BNE LOOP
if an irq happens durng second cycle of BNE, and branch is taken, 2(BNE)+7(INC)=9 cycles are executed before irq and, as a "borderline case of the corner cases", if BNE cross page boundary, 3+7=10 cycles are executed.
I'm wrong?
(Ok... i know we all need to avoid boundary cross... and probably no one use a INC $FFFF,X... but it's just to see if my thoughts are correct.) |
| |
Oswald
Registered: Apr 2002 Posts: 5086 |
"if irq is triggered on first cycle of BNE, then BNE + INC are executed before CPU starts irq sequence..."
this 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 ? |
| |
Copyfault
Registered: Dec 2001 Posts: 474 |
@Flavio: I remember there was a different behaviour when that branch was pagecrossing.
No pagecrossing, branch taken, irq on 2nd branch cycle (marked with <>):
next op.....cycles
BNE (taken) [R=1st branch cycle]<R=2nd branch cycle>[R=add.cycle]
INC abs,X [R=1st INC cycle][2][3][4][5][6][7]
<irq processing starts here>
Same with pagecrossing:
next op.....cycles
BNE (taken) [R=1st branch cycle]<R=2nd branch cycle>[R=add.cycle for branch taken][R=add.cycle for pagecrossing]
<irq processing starts here>
There was this explanation with socalled "opcode fetch cycles" that do not allow irq acknowledging and that an irq is not processed before it was acknowledged. Having a pagecrossing situation, the first additional branch cycle belongs to those opcode fetch cycles whereas the next additional cycle for the page crossing does not; thus, it results in less jitter. |
| |
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. |
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 - Next |