BRK/IRQ/NMI
BRK/IRQ/NMI
Hi, I'm looking for an answer to the following question. I *think* I know what the answer is but I haven't been able to find it anywhere conclusively.
When the 6502 is in the midst of a 7-cycle sequence for a BRK or IRQ and an NMI occurs, does the NMI 7-cycle sequence start immediately, or does the first 7-cycle sequence complete *then* the NMI 7-cycle sequence commences?
I am fairly sure they're executed one after the other, not on top of each other, as the scenario would lead to unbounded stack growth if it kept happening.
Also, at which cycle in the 7-cycle sequence is the I-flag set? I had assumed it was after (or during) the cycle where the processor status is pushed, because the processor status contains the "old" value of I so that RTI will revert it.
Thanks!
When the 6502 is in the midst of a 7-cycle sequence for a BRK or IRQ and an NMI occurs, does the NMI 7-cycle sequence start immediately, or does the first 7-cycle sequence complete *then* the NMI 7-cycle sequence commences?
I am fairly sure they're executed one after the other, not on top of each other, as the scenario would lead to unbounded stack growth if it kept happening.
Also, at which cycle in the 7-cycle sequence is the I-flag set? I had assumed it was after (or during) the cycle where the processor status is pushed, because the processor status contains the "old" value of I so that RTI will revert it.
Thanks!
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Welcome.
I'm not sure exactly what you're asking, but any given instruction finishes before the interrupt sequence is started. The interrupt sequence is itself like an instruction. Even if IRQ hit and its interrupt sequence starts and an NMI hits during that sequence, the IRQ's sequence will complete before the NMI sequence starts.
The interrupt sequence does push the status that existed at the end of the last instruction which was just finished before the interrupt sequence started, including the I bit, then sets it, so there's no point in starting an ISR with SEI, and you wouldn't want to end an ISR with CLI. (RTI retrieves the old status.) You could have CLI inside the ISR if it's kind of a longish one and you want quick higher-priority things to be able to interrupt a lower-priority ISR.
You can find my article on interrupts here. Enjoy the outdated cartoons.
I'm not sure exactly what you're asking, but any given instruction finishes before the interrupt sequence is started. The interrupt sequence is itself like an instruction. Even if IRQ hit and its interrupt sequence starts and an NMI hits during that sequence, the IRQ's sequence will complete before the NMI sequence starts.
The interrupt sequence does push the status that existed at the end of the last instruction which was just finished before the interrupt sequence started, including the I bit, then sets it, so there's no point in starting an ISR with SEI, and you wouldn't want to end an ISR with CLI. (RTI retrieves the old status.) You could have CLI inside the ISR if it's kind of a longish one and you want quick higher-priority things to be able to interrupt a lower-priority ISR.
You can find my article on interrupts here. Enjoy the outdated cartoons.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
GARTHWILSON wrote:
Welcome.
GARTHWILSON wrote:
I'm not sure exactly what you're asking, but any given instruction finishes before the interrupt sequence is started. The interrupt sequence is itself like an instruction. Even if IRQ hit and its interrupt sequence starts and an NMI hits during that sequence, the IRQ's sequence will complete before the NMI sequence starts.
Thus it would logically follow that the 7-cycle sequence is itself "uninterruptable".
GARTHWILSON wrote:
The interrupt sequence does push the status that existed at the end of the last instruction which was just finished before the interrupt sequence started, including the I bit, then sets it, so there's no point in starting an ISR with SEI, and you wouldn't want to end an ISR with CLI. (RTI retrieves the old status.) You could have CLI inside the ISR if it's kind of a longish one and you want quick higher-priority things to be able to interrupt a lower-priority ISR.
You can find my article on interrupts here. Enjoy the outdated cartoons.
You can find my article on interrupts here. Enjoy the outdated cartoons.
Perhaps a different way to phrase the question...
If I'm in the 7-cycle preamble for an IRQ and NMI has asserted before I get to the vector fetch cycles, which vector gets fetched in the *current 7-cycle preamble? IRQ, right? Then as soon as I'm done with the IRQ 7-cycle preamble I start the NMI 7-cycle preamble? Right?
EDIT: Addition...
From the cited webpage above:
"We should mention here that one of the NMOS 6502 bugs is that if an NMI hits during a BRK instruction, the BRK interrupt will not get executed. "
What I'm really trying to do is figure out exactly what this means.
Does "during a BRK instruction" mean all 7-cycles of it? What happens if I'm on the 7th cycle -- I've just fetched and created a PC to go to my BRK handler, so that will be where my NMI handler RTI's to, right?
If I'm in the 7-cycle preamble for an IRQ and NMI has asserted before I get to the vector fetch cycles, which vector gets fetched in the *current 7-cycle preamble? IRQ, right? Then as soon as I'm done with the IRQ 7-cycle preamble I start the NMI 7-cycle preamble? Right?
EDIT: Addition...
From the cited webpage above:
"We should mention here that one of the NMOS 6502 bugs is that if an NMI hits during a BRK instruction, the BRK interrupt will not get executed. "
What I'm really trying to do is figure out exactly what this means.
Does "during a BRK instruction" mean all 7-cycles of it? What happens if I'm on the 7th cycle -- I've just fetched and created a PC to go to my BRK handler, so that will be where my NMI handler RTI's to, right?
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
cpow wrote:
Perhaps a different way to phrase the question...
If I'm in the 7-cycle preamble for an IRQ and NMI has asserted before I get to the vector fetch cycles, which vector gets fetched in the *current 7-cycle preamble? IRQ, right? Then as soon as I'm done with the IRQ 7-cycle preamble I start the NMI 7-cycle preamble? Right?
If I'm in the 7-cycle preamble for an IRQ and NMI has asserted before I get to the vector fetch cycles, which vector gets fetched in the *current 7-cycle preamble? IRQ, right? Then as soon as I'm done with the IRQ 7-cycle preamble I start the NMI 7-cycle preamble? Right?
Quote:
EDIT: Addition...
From the cited webpage above:
"We should mention here that one of the NMOS 6502 bugs is that if an NMI hits during a BRK instruction, the BRK interrupt will not get executed. "
What I'm really trying to do is figure out exactly what this means.
Does "during a BRK instruction" mean all 7-cycles of it? What happens if I'm on the 7th cycle -- I've just fetched and created a PC to go to my BRK handler, so that will be where my NMI handler RTI's to, right?
From the cited webpage above:
"We should mention here that one of the NMOS 6502 bugs is that if an NMI hits during a BRK instruction, the BRK interrupt will not get executed. "
What I'm really trying to do is figure out exactly what this means.
Does "during a BRK instruction" mean all 7-cycles of it? What happens if I'm on the 7th cycle -- I've just fetched and created a PC to go to my BRK handler, so that will be where my NMI handler RTI's to, right?
UPDATE: BRK/IRQ/NMI -- NMI does overlap
I simulated an NMI occurring during the 7-cycle IRQ preamble...it does overlap.
http://visual6502.org/JSSim/expert.html ... re=nmi,irq
http://visual6502.org/JSSim/expert.html ... re=nmi,irq
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Uh, where did this word "preamble" come from? Does the manufacturer of another processor family use it? The data books from 6502 manufacturers Western Design Center, Rockwell, California Micro Devices, GTE, Synertek, and Commodore all call it "interrupt sequence." After the end of the interrupt sequence, execution picks up in the "interrupt service routine," or "interrupt handler."
GARTHWILSON wrote:
Uh, where did this word "preamble" come from? Does the manufacturer of another processor family use it? The data books from 6502 manufacturers Western Design Center, Rockwell, California Micro Devices, GTE, Synertek, and Commodore all call it "interrupt sequence." After the end of the interrupt sequence, execution picks up in the "interrupt service routine," or "interrupt handler."
Hi cpow
That's a really interesting result: you fired an NMI in the middle of the 7-cycle interrupt sequence as it was handling an IRQ, and it fetched the NMI vectors.
Of course this is a slightly unusual situation, because you'd already brought IRQ high again (inactive) whereas IRQ normally remains low until the requesting device services it.
And indeed, if I patch in an RTI with "&a=20&d=40" the machine has no 'recollection' of the IRQ which was usurped - it continues with the main program. (You had a short handler in place too but your main program was long enough to overwrite it...)
If I instead keep IRQ active throughout by removing the '&irq1=22' we still see the IRQ being usurped by the late NMI, but when the RTI completes we start a second interrupt sequence and this time we vector through FFFE as expected. So, your interesting observation still stands, even with a normal use of IRQ. (One might have expected the first instruction of the IRQ handler to be interrupted by the NMI)
BTW, I hope you've seen the photo(*) which shows that the 2A03 contains a literal copy of an nmos 6502 in one corner - a completely different design style from the rest of the chip!
Cheers
Ed
(*)1600px chip photo here - by Christian Sattler, released into the public domain.
That's a really interesting result: you fired an NMI in the middle of the 7-cycle interrupt sequence as it was handling an IRQ, and it fetched the NMI vectors.
Of course this is a slightly unusual situation, because you'd already brought IRQ high again (inactive) whereas IRQ normally remains low until the requesting device services it.
And indeed, if I patch in an RTI with "&a=20&d=40" the machine has no 'recollection' of the IRQ which was usurped - it continues with the main program. (You had a short handler in place too but your main program was long enough to overwrite it...)
If I instead keep IRQ active throughout by removing the '&irq1=22' we still see the IRQ being usurped by the late NMI, but when the RTI completes we start a second interrupt sequence and this time we vector through FFFE as expected. So, your interesting observation still stands, even with a normal use of IRQ. (One might have expected the first instruction of the IRQ handler to be interrupted by the NMI)
BTW, I hope you've seen the photo(*) which shows that the 2A03 contains a literal copy of an nmos 6502 in one corner - a completely different design style from the rest of the chip!
Cheers
Ed
(*)1600px chip photo here - by Christian Sattler, released into the public domain.
BigEd wrote:
Hi cpow
That's a really interesting result: you fired an NMI in the middle of the 7-cycle interrupt sequence as it was handling an IRQ, and it fetched the NMI vectors.
That's a really interesting result: you fired an NMI in the middle of the 7-cycle interrupt sequence as it was handling an IRQ, and it fetched the NMI vectors.
http://visual6502.org/JSSim/expert.html ... re=nmi,irq
This shows an NMI that fires during the fetch cycles of the IRQ sequence being completely ignored. Of course, I seem to remember reading somewhere that NMI must be low for two cycles to be recognized...this would explain why. But it also helped me to understand why the NES test ROM I was trying to emulate doesn't service an NMI right after the IRQ sequence if the NMI fires in the fetch cycles of the IRQ sequence.
BigEd wrote:
Of course this is a slightly unusual situation, because you'd already brought IRQ high again (inactive) whereas IRQ normally remains low until the requesting device services it.
And indeed, if I patch in an RTI with "&a=20&d=40" the machine has no 'recollection' of the IRQ which was usurped - it continues with the main program. (You had a short handler in place too but your main program was long enough to overwrite it...)
And indeed, if I patch in an RTI with "&a=20&d=40" the machine has no 'recollection' of the IRQ which was usurped - it continues with the main program. (You had a short handler in place too but your main program was long enough to overwrite it...)
BigEd wrote:
BTW, I hope you've seen the photo(*) which shows that the 2A03 contains a literal copy of an nmos 6502 in one corner - a completely different design style from the rest of the chip!
The Visual6502 is such a fascinating useful tool...someday I'm sure we'll have Visual<YourFavoriteChip> where we can all marvel at the skills of our ancestors.
BigEd wrote:
One might have expected the first instruction of the IRQ handler to be interrupted by the NMI
Although I'm surprised by this, so far I haven't noticed any contradiction of the "interrupt as an instruction" theory. Comments are welcome; here's a rehash!
The interrupt sequence (instruction) commences with either an NMI, IRQ, RST or the fetching of a BRK opcode, but its exact outcome is determined as the sequence progresses. For example, the value pushed to stack as the BRK bit in the Processor Status Register is read from the interrupt logic during T4, simultaneously as P is pushed.(see note) And now we know (thanks to cpow's experiment, April 8 post) that another decision is deferred: namely, the choice of which interrupt vector to fetch. Evidently that's determined rather late -- but still in time for T5, when the low-order byte of the vector must be fetched either from $FFFA or $FFFE.
I'm becoming more and more impressed with the nuances of the $00 instruction/circumstance -- surely one of the 65xx's most interesting (pseudo-) OpCodes. Nice work, cpow! And thanks, Big Ed, for clarifying. BTW, my hunch is that a RST partway into the sequence would usurp even the NMI, but that may not be the case. If you try it, let me know!
-- Jeff
Note: I'm not suggesting the state of this bit changes during the sequence; merely pointing out (as the schematic shows) that it is sampled later, rather than as the sequence commences.
Big Ed wrote:
Of course this is a slightly unusual situation, because you'd already brought IRQ high again (inactive) whereas IRQ normally remains low until the requesting device services it.
Interesting indeed: playing around with the timing, we seem to need 3 cycles of NMI to be sure of catching it.
As you may have spotted, we do now have a visual6800, and we hope to have a visual4004 next. The visual2A03 may yet come, but I'm not sure how it stands in priority compared to say the z80 or the rca1802. But, capturing the polygons is the hardest part, so if you can rustle those up, we can do the rest!
As you may have spotted, we do now have a visual6800, and we hope to have a visual4004 next. The visual2A03 may yet come, but I'm not sure how it stands in priority compared to say the z80 or the rca1802. But, capturing the polygons is the hardest part, so if you can rustle those up, we can do the rest!
Visual2A03 by Quietust
cpow wrote:
I'm hoping someday we'll have a Visual2A03. =]
Re: BRK/IRQ/NMI
Sorry about reviving an old tread, but I am trying to get my head around this interrupt. The reason is that I am implementing a MMU than needs to catch interrupt instances so that proper handling can happen.
One thing I am having a problem with is what happens when two interrupt instances happen at once. In the interrupt tutorial, it states that "you might want to re-enable interrupts (using CLI) in the ISR as soon as the most urgent part of one interrupt's servicing is finished". Apparently this is so that another interrupt can be entered before the first one is finished.
I always assumed that one interrupt had to finish with a RTI before the next could be executed. Or am I missing something? And two sequential IRQ interrupts must certainly be executed in series (with RTI between)?
Edit: I put in a sequence of $EA (NOP) in the NMI interrupt example in one of the above posts. At RTI the next (IRQ) interrupt executes, but if I put in a CLI before the RTI, the next interrupt executes two instructions (4 cycles) after the CLI but before a RTI. So it looks like two interrupts can nest and the second one executed inside the first one (e.g. when NMI and IRQ happens at the same time).
One thing I am having a problem with is what happens when two interrupt instances happen at once. In the interrupt tutorial, it states that "you might want to re-enable interrupts (using CLI) in the ISR as soon as the most urgent part of one interrupt's servicing is finished". Apparently this is so that another interrupt can be entered before the first one is finished.
I always assumed that one interrupt had to finish with a RTI before the next could be executed. Or am I missing something? And two sequential IRQ interrupts must certainly be executed in series (with RTI between)?
Edit: I put in a sequence of $EA (NOP) in the NMI interrupt example in one of the above posts. At RTI the next (IRQ) interrupt executes, but if I put in a CLI before the RTI, the next interrupt executes two instructions (4 cycles) after the CLI but before a RTI. So it looks like two interrupts can nest and the second one executed inside the first one (e.g. when NMI and IRQ happens at the same time).