Interrupts in 65xx processors

The 65xx family of microprocessors, consisting of the MOS Technology 6502 and its derivatives, the WDC 65C02, WDC 65C802 and WDC 65C816, all handle interrupts in a similar fashion. There are three hardware interrupt signals common to all 65xx processors and one software interrupt, the BRK instruction. The WDC 65C816 adds a fourth hardware interrupt—ABORT, useful for implementing virtual memory architectures—and the COP software interrupt instruction (also present in the 65C802), intended for use in a system with a coprocessor of some type (e.g., a floating point processor).[1][2]

Contents

Interrupt types

65xx interrupt vector locations[2][3]
Interrupt Vector (hexadecimal)
LSB MSB
ABORT FFF8 FFF9
COP[nb 1] FFF4 FFF5
NMI FFFA FFFB
RESET FFFC FFFD
IRQ/BRK FFFE FFFF

The hardware interrupt signals are all active low, and are as follows:[1]

RESET
a reset signal, level-triggered
NMI
a non-maskable interrupt, edge-triggered
IRQ
a maskable interrupt, level-triggered
ABORT
a special-purpose, non-maskable interrupt (65C816 only, see below), level-triggered

The detection of a RESET signal causes the processor to enter a system initialization period of six clock cycles, after which it sets the interrupt disable flag in the status register and loads the program counter with the values stored at the processor initialization vector ($FFFC-$FFFD) before commencing execution.[1]

65C816/65C802 "native mode" interrupt vector locations[2]
Interrupt Vector (hexadecimal)
LSB MSB
ABORT 00FFE8 00FFE9
COP[nb 1] 00FFE4 00FFE5
BRK 00FFE6 00FFE7
NMI 00FFEA 00FFEB
RESET None[nb 2]
IRQ 00FFEE 00FFEF

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:[1][3]

  1. The processor completes the current instruction and updates registers or memory as required before responding to the interrupt.
  2. The program bank register (PBR, the A16-A23 part of the address bus) is pushed onto the stack (65C816/65C802 only when operating in native mode).
  3. The most significant byte (MSB) of the program counter is pushed onto the stack.
  4. The least significant byte (LSB) of the program counter is pushed onto the stack.
  5. The status register is pushed onto the stack.
  6. The interrupt disable flag is set in the status register.
  7. PBR is loaded with $00 (65C816/65C802 only when operating in native mode).
  8. The program counter is loaded from the relevant vector (see tables).

The behavior of the 65C816 when ABORT is asserted differs in some respects from the above description and is separately discussed below.

Note that the processor does not push the accumulator and index registers on to the stack—code in the interrupt handler must perform that task, as well as restore the registers at the termination of interrupt processing, as necessary. Also note that the vector for IRQ is the same as that for BRK in all eight bit 65xx processors, as well as in the 65C802/65C816 when operating in emulation mode. When operating in native mode, the 65C802/65C816 provide separate vectors for IRQ and BRK.[4]

When set, the interrupt disable flag (the I bit in the status register) will disable detection of the IRQ signal, but will have no effect on any other interrupts. Additionally, with the 65(c)02 or the 65C816/65C802 operating in emulation mode, the copy of the status register that is pushed on to the stack will have the B flag set if a BRK was the cause of the interrupt, or cleared if an IRQ was the cause.[nb 3] Hence the interrupt service routine must retrieve a copy of the saved status register from where it was pushed onto the stack and check the status of the B flag in order to distinguish between an IRQ and a BRK.[1][2][4] This requirement is eliminated when operating the 65C802/65C816 in native mode, due to the separate vectors for the two interrupt types.[2]

ABORT interrupt

The 65C816's ABORT input is intended to provide the means to interrupt the processor when a hardware exception is detected, such as a page fault or a memory access violation. Hence the response to an ABORT interrupt is different in behavior than that of IRQ and/or NMI when asserted. Also, achieving correct operation in response to ABORT requires that the interrupt occur at the proper time during the machine cycle, whereas no such requirement exists for IRQ or NMI.

When ABORT is asserted during a valid memory cycle (that is, when the processor has asserted the VDA and/or VPA status outputs), the following sequence of events will occur:[2]

  1. The processor completes the current instruction but does not change the registers or memory in any way—the results of the completed instruction are discarded.
  2. PBR is pushed onto the stack.
  3. The most significant byte (MSB) of the aborted instruction's address is pushed onto the stack.
  4. The least significant byte (LSB) of the aborted instruction's address is pushed onto the stack.
  5. The status register is pushed onto the stack.
  6. The interrupt disable flag is set in the status register.
  7. PBR is loaded with $00.
  8. The program counter is loaded from the ABORT vector (see tables).

As the address pushed to the stack is that of the aborted instruction rather than the contents of the program counter, executing an RTI following an ABORT interrupt will cause the processor to return to the aborted instruction, rather than the next instruction, as would be the case with the other interrupts.

In order for the processor to correctly respond to ABORT, system logic must assert the interrupt as soon as a valid address has been placed on the bus and it has been determined that the address constitutes a page fault or a memory access violation. Hence the logic must not assert ABORT until the processor has asserted the VDA or VPA signals. Also, ABORT must remain asserted until the fall of the phase-two clock and then be immediately released. If these timing constraints are not observed, the ABORT interrupt handler itself may be aborted, causing registers and/or memory to be changed in a possibly-undefined manner.[2]

Interrupt anomalies

In the NMOS 6502, the simultaneous assertion of a hardware interrupt line and execution of BRK was not accounted for in the design—the BRK instruction will be ignored in such a case. Also, the status of the decimal mode flag in the processor status register is unchanged following an interrupt of any kind. This behaviour can potentially result in a difficult to locate bug in the interrupt handler if decimal mode happens to be enabled at the time of an interrupt. These anomalies were corrected in all CMOS versions of the processor.[2]

Using BRK and COP

As previously noted, BRK and COP are software interrupts and, as such, may be used in a variety of ways to implement system functions.

A historical use of BRK has been to assist in patching PROMs when bugs were discovered in a system's firmware. A typical technique often used during firmware development was to arrange for the BRK vector to point to an unprogrammed "patch area" in the PROM. In the event a bug was discovered, patching would be accomplished by "blowing" all of the fuses at the address where the faulty instruction was located, thus changing the instruction's opcode to $00. Upon executing the resulting BRK, the MPU would be redirected to the patch area, into which suitable patch code would be written. Often, the patch area code started by "sniffing the stack" to determine the address at which the bug was encountered, potentially allowing for the presence of more than one patch in the PROM. The use of BRK for PROM patching diminished once EPROMs and EEPROMs became commonly available.

Another use of BRK in software development is as a debugging aid in conjunction with a machine language monitor. By overwriting an opcode with BRK ($00) and directing the BRK hardware vector to the entry point of the monitor, one can cause a program to halt at any desired point, allowing the monitor to take control. At that time, one may examine memory, view the processor's register values, patch code, etc. Debugging, as advocated by Kuckes and Thompson, can be facilitated by liberally sprinkling one's code with NOP instructions (opcode EA) that can be replaced by BRK instructions without altering the actual behaviour of the program being debugged.[5][6][7]

A characteristic of the BRK and COP instructions is that the processor treats either as a two byte instruction: the opcode itself and the following byte, which is referred to as the "signature."[2] Upon execution of BRK or COP, the processor will add two to the program counter prior to pushing it to the stack. Hence when RTI (ReTurn from Interrupt) is executed, the interrupted program will continue at the address immediately following the signature. If BRK is used as a debugging device, the program counter may have to be adjusted to point to the signature in order for execution to resume where expected. Alternatively, a NOP may be inserted as a signature "placeholder," in which case no program counter adjustment will be required.

The fact that BRK and COP double-increment the program counter before pushing it to the stack facilitates the technique of treating them as supervisor call instructions, as found on some mainframe computers. The usual procedure is to treat the signature as an operating system service index. The operating system BRK or COP handler would retrieve the value of the program counter pushed to the stack, decrement it and read from the resulting memory location to get the signature.[8][9] After converting the signature to a zero-based index, a simple lookup table can be consulted to load the program counter with the address of the proper service routine. Upon completion of the service routine, the RTI instruction would be used to return control to the program that made the operating system call. Note that the signature for BRK may be any value, whereas the signature for COP should be limited to the range $00-$7F.[2]

The use of BRK and/or COP to request an operating system service means user applications do not have to know the entry address of each operating system function, only the correct signature byte to invoke the desired operation. Hence relocation of the operating system in memory will not break compatibility with existing user applications. Also, as executing BRK or COP always vectors the processor to the same address, simple code may be used to preserve the registers on the stack prior to turning control over to the requested service. However, this programming model will result in somewhat slower execution as compared to calling a service as a subroutine. Also, interrupt requests will have been disabled by executing BRK or COP. requiring that the operating system re-enable them.

Footnotes

  1. ^ a b The COP instruction is available in both operating modes.[2]
  2. ^ The 65C816/65C802 has no interrupt vector for the RESET signal in native mode, as a reset always reverts the processor to emulation mode.[2]
  3. ^ The value of the B flag in the status register itself has no meaning. The flag is only set or cleared by the processor when the status register is pushed onto the stack in response to an interrupt.[2]

References

  1. ^ a b c d e J. S. Anderson (1994). Microprocessor Technology. Butterworth-Heinemann. pp. 143–144. ISBN 0750618396. 
  2. ^ a b c d e f g h i j k l m David Eyes and Ron Lichty (1992-04-28) (PDF). Programming the 65816. The Western Design Center, Inc.. http://westerndesigncenter.com./wdc/datasheets/Programmanual.pdf. 
  3. ^ a b "Basic Architecture". 6502. 2002-01-02. http://www.obelisk.demon.co.uk./6502/architecture.html. 
  4. ^ a b Leo J. Scanlon (1980). 6502 Software Design. H. W. Sams. pp. 172–173. ISBN 0672216566. 
  5. ^ Ronald J. Tocci and Lester P. Laskowski (1979). Microprocessors and Microcomputers: Hardware and Software. Prentice-Hall. p. 379. ISBN 0135813220. 
  6. ^ Lance A. Leventhal (1986). 6502 Assembly Language Programming. Osborne/McGraw-Hill. ISBN 007881216X. 
  7. ^ Arthur F. Kuckes and B. G. Thompson (1987). Apple II in the Laboratory. UP Archive. p. 93. ISBN 0521321980. 
  8. ^ Harrod, Dennette A. (October 1980). "6502 Gets Microprogrammable Instructions". BYTE (McGraw Hill) 5 (10): pp 282–285. ISSN 00360-5280. http://www.wiz-worx.com/resume/byte8010.htm. 
  9. ^ Richard R. Smardzewski (1984). Microprocessor Programming and Applications for Scientists and Engineers. Elsevier. p. 125. ISBN 0444424075. 

Further reading