The BRK instruction on the MOS 6502 seems to be one of the more
ill-documented features of the processor. The 1976 preliminary data
sheet from MOS indicates that it's a 1-byte instruction using
the "implied" addressing mode (i.e., it has no operands), as does the
the 1980 CSG data sheet.¹ (Edit: the MCS6500 Microcomputer
Family Programminng Manual does describe the details and
intention of the BRK instruction in §9.11 pp. 144-146.)
However, unlike an IRQ interrupting any other 1-byte instruction, the
program counter pushed on to the stack when a BRK is executed does
not point to the byte immediately after the opcode but instead to the
second byte after the opcode. (This is mentioned nowhere in those
two data sheets.²)
Given the lack of documentation about this, I'm guessing that this was
unintentional³ (though evidence otherwise is welcome!), because it
wastes the byte after the BRK if the interrupt handler does an RTI
to the address pushed by the BRK after handling it. (If there was no
RTI, the byte need not be wasted: control would never flow past the
BRK and so another routine could have an entry point immediately
after it. This was the case on, e.g., the Apple II, where a BRK would
stop whatever program was executing and enter the monitor.⁴)
I'm looking for examples in "real-world" code (as opposed to
demonstration or example code) of how this "spare byte" was used in
systems with IRQ routines that did an RTI to return to the address
pushed by the BRK instruction.⁵ This could be use by the IRQ routine
itself (as a parameter, or similar, e.g. as Woz sugested in his
November 1977 BYTE article on Sweet 16) or something else.
Ideally the examples would be from widely distributed software for 6502-based general purpose computers. Again, I'm not too interested in demo code that shows how it could be used in a theoretical real-world program. But if you feel you have an example that has something useful to offer beyond the limited technical details of how to implement this, feel free post an answer about it.
¹Both have a note "See Fig. 1" beside the instruction in the instruction set/opcde table, but none of the figures in either document are numbered, and none seem to be relevant. I welcome clarification of this.
²The ignored byte after the BRK is kind of implied by the cycle
breakdown of the BRK instruction on page A-11 of the 1976 MCS6500
Microcomputer Family Hardware Manual, where after the T0
cycle reads the opcode the subsequent T1 cycle puts on the address bus
"PC + 1 (PC on hardware interrupt)" before pushing the PC on to the
stack in T2 and T3. But documenting it as a one-byte instruction or
opcode with no operands, despite the byte after it being skipped,
persists even today in the 2018 WDC W65C02S data sheet.
This post on forum.6502.org does say, "WDC
describes BRK as '...a 2 byte instruction. The NMOS and CMOS devices
simply skips [sic] the second byte (i.e. doesn’t care about the second
byte) by incrementing the program counter twice.'" However, it doesn't
give a source for that quote.
³By "unintentional" I mean that having that unused byte after the
BRK instruction was not a design goal. In this context, "we've got
an unused byte there but it isn't a problem and that lets us save
transistors (or whatever) elsewhere" does not count as
"intentional."
⁴See the IRQ routine at $FA86 in the BIOS listing on page 81
(PDF page 84) of the Apple II Reference Manual.
⁵An IRQ routine could use bit 4 of the program status register
value pushed on to the stack to determine it had been invoked by a
BRK and then use the PC pushed on to the stack to find the spare
byte. Wilson Mines gives details on how to do this.
BRKhandler if the return address were the one right afterBRK, rather than the one after, just as is done withJSR. And that seems to me simpler because you don't have to remember to skip a byte before starting your next instruction (e.g., by always putting aNOPafterBRK) if you're using a handler that doesn't take parameter data after the instruction. – cjs Sep 11 '19 at 16:27BRKis likeINTinstruction of x86. The following byte is number of software interrupt (or can be used for this purpose). – i486 Sep 13 '19 at 10:58INT3instruction (0xCC), which is a single-byte instruction that uses a fixed vector (asBRKdoes), rather than theINT nninstruction (0xCD nn) which routes to one of 256 different vectors, which the 6502 cannot do. Note that you can replace any instruction byte with anINT3orBRK, but you cannot do so withINT; you must replace the byte after the instruction with your vector number as well. – cjs Sep 13 '19 at 11:50JSR. – cjs Sep 13 '19 at 13:41