Page 1 of 1

Interrupt behavior during an instruction

Posted: Tue Jan 05, 2016 8:55 pm
by BobLoblaw0101
Just to confirm -- What is the behavior of the 6502 when an interrupt occurs in the middle of instruction? Does it handle the interrupt when it occurred, or does it finish the instruction and then perform the interrupt?

For example, if I'm executing an instruction and have 2 cycles left until that instruction completes, what happens when an interrupt occurs? Does the interrupt logic (i.e. saving flags, changing PC) happen after the instruction completes (2 cycles later) or does it occur instantly?

Thanks in advance.

Re: Interrupt behavior during an instruction

Posted: Tue Jan 05, 2016 9:51 pm
by GARTHWILSON
The instruction completes, then the interrupt sequence is started.  See the 6502 interrupts primer.

ABORT on the 65816 is different in that although the instruction completes, registers and memory are left unchanged, so it can be used to flag attempted access to non-existent memory, take care of the problem, and then try the instruction again, if I understand it correctly.  BDD or someone else can fill in the details.

Re: Interrupt behavior during an instruction

Posted: Tue Jan 05, 2016 11:17 pm
by BigDumbDinosaur
BobLoblaw0101 wrote:
Just to confirm -- What is the behavior of the 6502 when an interrupt occurs in the middle of instruction? Does it handle the interrupt when it occurred, or does it finish the instruction and then perform the interrupt?
GARTHWILSON wrote:
The instruction completes, then the interrupt sequence is started. See the interrupts primer.

ABORT on the 65816 is different in that although the instruction completes, registers and memory are left unchanged, so it can be used to flag attempted access to non-existent memory, take care of the problem, and then try the instruction again, if I understand it correctly. BDD or someone else can fill in the details.
As Garth noted, the current instruction is always finished before interrupt processing begins. Also, as he noted, the 65C816's ABORT interrupt causes the MPU to discard the computational result of the current instruction.

Re: Interrupt behavior during an instruction

Posted: Wed Jan 06, 2016 1:25 am
by BobLoblaw0101
Thanks for the information. One more question:

On the 6502, According to https://en.wikipedia.org/wiki/Interrupt ... processors, the following happens:

Code: Select all

The detection of an NMI or IRQ signal, as well as the execution of a BRK instruction, will cause the same overall sequence of events, which are, in order:

The processor completes the current instruction and updates registers or memory as required before responding to the interrupt.
The program bank register (PB, the A16-A23 part of the address bus) is pushed onto the hardware stack (65C816/65C802 only when operating in native mode).
The most significant byte (MSB) of the program counter (PC) is pushed onto the stack.
The least significant byte (LSB) of the program counter is pushed onto the stack.
The status register (SR) is pushed onto the stack.
The interrupt disable flag is set in the status register.
PB is loaded with $00 (65C816/65C802 only when operating in native mode).
PC is loaded from the relevant vector (see tables).
I've been able getting my cycle counts for various instructions on http://www.6502.org/tutorials/6502opcodes.html. This lists the cycle counts per instruction, as well as whether a modifier needs to be added because it passes a page boundary.

For the case of an NMI as described above... Is there a discrete number of cycles it takes to perform the NMI before executing the ISR? I couldn't find it anywhere (and an NMI isn't an actual instruction)

I'm basically going to push PC and SR to the stack, set the interrupt disable flag, and then set PC to the address of the ISR. I'm not sure how many cycles that would take for my emulator.

EDIT:
According to http://wilsonminesco.com/6502interrupts/, am I interpreting it correctly to be 7 cycles?

Re: Interrupt behavior during an instruction

Posted: Wed Jan 06, 2016 3:10 am
by Dr Jefyll
BobLoblaw0101 wrote:
(and an NMI isn't an actual instruction) [...]

According to http://wilsonminesco.com/6502interrupts/, am I interpreting it correctly to be 7 cycles?
It's a matter of definition, I suppose. I'd say NMI is an instruction -- and, like its cousin, BRK, it takes 7 cycles to execute. But NMI is unusual in that it's an instruction not stored in memory -- it occupies zero bytes! :)

Re: Interrupt behavior during an instruction

Posted: Wed Jan 06, 2016 3:25 am
by GARTHWILSON
but yes, the NMI interrupt sequence takes 7 cycles on the 65(c)02, exactly, always, after completion of the currently executing instruction.  The next cycle after that reads the first op code in your ISR.  It's quite efficient.  IIRC, the greatest number of interrupts per second I've done on my 5MHz 65c02 workbench computer was about 125,000.

Re: Interrupt behavior during an instruction

Posted: Wed Jan 06, 2016 3:43 am
by BigDumbDinosaur
Dr Jefyll wrote:
BobLoblaw0101 wrote:
(and an NMI isn't an actual instruction) [...]

According to http://wilsonminesco.com/6502interrupts/, am I interpreting it correctly to be 7 cycles?
It's a matter of definition, I suppose. I'd say NMI is an instruction -- and, like its cousin, BRK, it takes 7 cycles to execute. But NMI is unusual in that it's an instruction not stored in memory -- it occupies zero bytes! :)
By the same measure, an IRQ would not be an instruction in the literal sense.

With the 65C816 in native mode, eight cycles are consumed in responding to any interrupt, the extra cycle accounting for the pushing of PB to the stack.

Re: Interrupt behavior during an instruction

Posted: Wed Jan 31, 2024 10:57 pm
by lightbeing
I'm not sure I fully understood a specific mechanism in the interrupt behaviour. Can anyone help me.

Page 131 of the MCS 6500 programming manual dated January 1976 indicates that during cycle 1 of an IRQ, the processor finishes the previous operation.

I also read this here https://www.pagetable.com/?p=410 "If there is an IRQ pending and the current instruction has just finished, the interrupt logic in the 6502 forces the instruction register (“IR”) to “0”, so instead of executing the next instruction, the PLA will decode the instruction with the opcode 0x00 – which is BRK!".

Let's imagine an interrupt occurs while the processor is executing a series of NOP's, which take 2 cycles each.

Does this mean that in this case, finishing the previous operation can take either 1 or 2 cycles?

Re: Interrupt behavior during an instruction

Posted: Thu Feb 01, 2024 3:37 am
by GARTHWILSON
lightbeing, I have not tested the exact thing you're asking about, but tested similar things on the 65816, and I think what you'll find, if you (or anyone else) test it, is that the normal minor pipelining will act normally.  For example, if the last step of an instruction is to put the result back in the accumulator, that can happen while the next op code is being fetched, whereas if the last step is to store something in memory, that cannot be done in the same cycle when the next opcode is being fetched; but if the bus is not busy, the processor will fetch the op code of the next instruction during the first cycle of the interrupt sequence, but then discard it.  Whether or not it takes another cycle is almost irrelevant, because you don't know which cycle an instruction's execution will be in when the interrupt hits.  Interrupts are by definition asynchronous.

Re: Interrupt behavior during an instruction

Posted: Thu Feb 01, 2024 8:51 am
by BigEd
lightbeing wrote:
I'm not sure I fully understood a specific mechanism in the interrupt behaviour. Can anyone help me.

Page 131 of the MCS 6500 programming manual dated January 1976 indicates that during cycle 1 of an IRQ, the processor finishes the previous operation.

I also read this here https://www.pagetable.com/?p=410 "If there is an IRQ pending and the current instruction has just finished, the interrupt logic in the 6502 forces the instruction register (“IR”) to “0”, so instead of executing the next instruction, the PLA will decode the instruction with the opcode 0x00 – which is BRK!".

Let's imagine an interrupt occurs while the processor is executing a series of NOP's, which take 2 cycles each.

Does this mean that in this case, finishing the previous operation can take either 1 or 2 cycles?
I think there's a tension in every description of interrupt handling, between being simple enough to explain and being detailed enough to be precisely correct. It's rare indeed to see a description which is absolutely correct, because the cycle-by-cycle behaviour is, as it turns out, rather subtle.

That programming manual - link here to the exact page - has a table which counts off the cycles of the interrupt sequence, starting from the SYNC cycle which is the fetch of the instruction following the last one to complete.

Garth is right in saying that even during that SYNC cycle there are (potentially) internal operations which finish off the actions of that last instruction. But there's no way to see that from the outside, either in hardware or in software. We only see that by looking at the insides of the chip, for example with visual6502. It's interesting because without understanding this, the cycle counts of the instructions don't quite make complete sense.

Michael (aka the pagetable author) is of course also right. The SYNC cycle of the first instruction not to be executed proceeds as normal, as far as the chip's external signals tell us, but on the inside the instruction fetched is replaced with 00. There's no way to see this from the outside.

The program manual is right, in that the cycle after the SYNC is another read, but uniquely it is a read from the same address as the SYNC. This only happens in the case of an interrupt. However, I don't think I would have labelled this as Fetch, because it's not a SYNC cycle. I might have labelled it as Internal Operation.

If you count the IRQ from the cycle in which it is asserted - which is not what the manual is doing - then you will see a variable number of cycles before the next SYNC, which will happen on schedule.

And, to answer your question, yes, if executing a steam of NOPs and getting an asynchronous IRQ, the 6502 will take N or N+1 cycles from the SYNC of the final NOP to the fetch of the interrupt vector. Because the deterministic count starts from the next SYNC, which belongs to the first NOP which won't be executed.

One of the most remarkable threads here is
A taken branch delays interrupt handling by one instruction
which starts from an observation on a real system, and is interrupted(!) by the arrival of visual6502, which allows us to make full explorations of internal behaviour.

Hope this helps.