What are uses of the byte after BRK instruction on 6502?How are 6502 and 65C02 JMP(abs) processed internallyHow did the Trap65 work?Was the design of MS-BASIC for 6502 based on MS-BASIC for 8080?Intel 8080 and Altair 8800. 256 I/0 ports, but only 7 free RST (interrupt subroutine) - how it works?DEX: How does a 2-Cycle instruction affect RCL outputs AFTER it completes?6502 branch offset calculationDoes the Intersil 6100 do interrupts differently from other PDP-8s?Why does this 6502 code push a function address onto the stack before calling?SYNC and the 65CE02 instruction timingWhat happened to the SEV instruction on the 6502?
Physical interpretation of gamma matrices
How can you determine the hostname associated with an IP on the network?
Does Airplane Mode allow GPS location to pass through?
Conditional proof demonstration
Authenticate users based on both user role, and requested operation
Good type of bike to get for commuting (thinking of road v touring)
Seen from Europe, why is there a hard separation between Republicans and Democrats in the US?
How can I swallow pills more easily?
My PhD defense is next week and I am having negative thoughts about my work and knowledge. Any advice on how to tackle this?
Manager asked me to reconsider my resignation and he sounded quite convincing, should I listen to him?
Mistakenly agreed with a scammer’s term of use
CEO says not to expect pay increases unless you do something really exceptional. Is this counter-productive?
C - wrapping globals in a struct?
Were there ever 12-, 24-, 48-, etc bit processors?
What was the sound coming from below the feet of the Death Eaters at Malfoy Manor?
Large products with glass doors
Designing Borders with QGIS
What is the difference between chemical equilibrium and dynamic equilibrium?
Wifi near the speed of light
Is a geodesic in the 4d spacetime still a geodesic after projection onto the 3d space?
Is Earth's Surface "In orbit"?
Should I present forged documents in a Penetration Test/Red team engagement?
Perfect pitch on only one instrument?
Who are the strongest non-professional GMs?
What are uses of the byte after BRK instruction on 6502?
How are 6502 and 65C02 JMP(abs) processed internallyHow did the Trap65 work?Was the design of MS-BASIC for 6502 based on MS-BASIC for 8080?Intel 8080 and Altair 8800. 256 I/0 ports, but only 7 free RST (interrupt subroutine) - how it works?DEX: How does a 2-Cycle instruction affect RCL outputs AFTER it completes?6502 branch offset calculationDoes the Intersil 6100 do interrupts differently from other PDP-8s?Why does this 6502 code push a function address onto the stack before calling?SYNC and the 65CE02 instruction timingWhat happened to the SEV instruction on the 6502?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
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 noRTI
, the byte need not be wasted: control would never flow past theBRK
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 theBRK
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 aBRK
and then use the PC pushed on to the stack to find the spare
byte. Wilson Mines gives details on how to do this.
6502 interrupt
|
show 4 more comments
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 noRTI
, the byte need not be wasted: control would never flow past theBRK
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 theBRK
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 aBRK
and then use the PC pushed on to the stack to find the spare
byte. Wilson Mines gives details on how to do this.
6502 interrupt
3
I'd also say it is unintentional, and probably a consequence of the "pipelining" done inside the 6502. One could check the "how" on visual6502.org. I've never seen an example where the byte after the BRK is used, though that doesn't mean there aren't any ... Though I know examples where bytes after a JSR have been used (e.g. in the Apple II Sweet Sixteen interpreter).
– dirkt
Sep 11 at 10:44
1
"Intentional" is a fuzzy thing. If it got that way as a result of transistor count, and someone at MOS noticed it and said "hey, that could actually be useful as a way to get information to the BRK handler, make sure not to change it", is that intentional or not? Several older architectures, before the "stack" concept was well-developed, would use caller-PC-relative data like that, so it's not an unheard-of idea.
– hobbs
Sep 11 at 16:22
@hobbs You could still use that technique to get information to theBRK
handler 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 aNOP
afterBRK
) if you're using a handler that doesn't take parameter data after the instruction.
– Curt J. Sampson
Sep 11 at 16:27
I'm also keeping away from intentional/unintentional but I'll vote for: likely easier. All single-byte 6502 instructions do a redundant fetch of the byte after them both for the usual 6502 marking-time reasons and to unify the one-byte and two-byte instruction execution patterns, so I'll guess that BRK just lets slide an internal modification to the PC that the other one-byte instructions undo.
– Tommy
Sep 11 at 17:42
1
@Tommy: The 6502 determines what address will be accessed on any given cycle before it has received the byte of data from the previous cycle. An instruction like INX requires an internal bus cycle to read the old value from the X register and an internal cycle to write the new value; the read takes place during the dummy operand fetch and the write-back during the next opcode fetch. NOP is just about the only instruction that could realistically execute as one-byte-one-cycle.
– supercat
Sep 12 at 23:56
|
show 4 more comments
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 noRTI
, the byte need not be wasted: control would never flow past theBRK
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 theBRK
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 aBRK
and then use the PC pushed on to the stack to find the spare
byte. Wilson Mines gives details on how to do this.
6502 interrupt
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 noRTI
, the byte need not be wasted: control would never flow past theBRK
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 theBRK
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 aBRK
and then use the PC pushed on to the stack to find the spare
byte. Wilson Mines gives details on how to do this.
6502 interrupt
6502 interrupt
edited Sep 12 at 2:31
Curt J. Sampson
asked Sep 11 at 10:13
Curt J. SampsonCurt J. Sampson
8,95023 silver badges57 bronze badges
8,95023 silver badges57 bronze badges
3
I'd also say it is unintentional, and probably a consequence of the "pipelining" done inside the 6502. One could check the "how" on visual6502.org. I've never seen an example where the byte after the BRK is used, though that doesn't mean there aren't any ... Though I know examples where bytes after a JSR have been used (e.g. in the Apple II Sweet Sixteen interpreter).
– dirkt
Sep 11 at 10:44
1
"Intentional" is a fuzzy thing. If it got that way as a result of transistor count, and someone at MOS noticed it and said "hey, that could actually be useful as a way to get information to the BRK handler, make sure not to change it", is that intentional or not? Several older architectures, before the "stack" concept was well-developed, would use caller-PC-relative data like that, so it's not an unheard-of idea.
– hobbs
Sep 11 at 16:22
@hobbs You could still use that technique to get information to theBRK
handler 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 aNOP
afterBRK
) if you're using a handler that doesn't take parameter data after the instruction.
– Curt J. Sampson
Sep 11 at 16:27
I'm also keeping away from intentional/unintentional but I'll vote for: likely easier. All single-byte 6502 instructions do a redundant fetch of the byte after them both for the usual 6502 marking-time reasons and to unify the one-byte and two-byte instruction execution patterns, so I'll guess that BRK just lets slide an internal modification to the PC that the other one-byte instructions undo.
– Tommy
Sep 11 at 17:42
1
@Tommy: The 6502 determines what address will be accessed on any given cycle before it has received the byte of data from the previous cycle. An instruction like INX requires an internal bus cycle to read the old value from the X register and an internal cycle to write the new value; the read takes place during the dummy operand fetch and the write-back during the next opcode fetch. NOP is just about the only instruction that could realistically execute as one-byte-one-cycle.
– supercat
Sep 12 at 23:56
|
show 4 more comments
3
I'd also say it is unintentional, and probably a consequence of the "pipelining" done inside the 6502. One could check the "how" on visual6502.org. I've never seen an example where the byte after the BRK is used, though that doesn't mean there aren't any ... Though I know examples where bytes after a JSR have been used (e.g. in the Apple II Sweet Sixteen interpreter).
– dirkt
Sep 11 at 10:44
1
"Intentional" is a fuzzy thing. If it got that way as a result of transistor count, and someone at MOS noticed it and said "hey, that could actually be useful as a way to get information to the BRK handler, make sure not to change it", is that intentional or not? Several older architectures, before the "stack" concept was well-developed, would use caller-PC-relative data like that, so it's not an unheard-of idea.
– hobbs
Sep 11 at 16:22
@hobbs You could still use that technique to get information to theBRK
handler 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 aNOP
afterBRK
) if you're using a handler that doesn't take parameter data after the instruction.
– Curt J. Sampson
Sep 11 at 16:27
I'm also keeping away from intentional/unintentional but I'll vote for: likely easier. All single-byte 6502 instructions do a redundant fetch of the byte after them both for the usual 6502 marking-time reasons and to unify the one-byte and two-byte instruction execution patterns, so I'll guess that BRK just lets slide an internal modification to the PC that the other one-byte instructions undo.
– Tommy
Sep 11 at 17:42
1
@Tommy: The 6502 determines what address will be accessed on any given cycle before it has received the byte of data from the previous cycle. An instruction like INX requires an internal bus cycle to read the old value from the X register and an internal cycle to write the new value; the read takes place during the dummy operand fetch and the write-back during the next opcode fetch. NOP is just about the only instruction that could realistically execute as one-byte-one-cycle.
– supercat
Sep 12 at 23:56
3
3
I'd also say it is unintentional, and probably a consequence of the "pipelining" done inside the 6502. One could check the "how" on visual6502.org. I've never seen an example where the byte after the BRK is used, though that doesn't mean there aren't any ... Though I know examples where bytes after a JSR have been used (e.g. in the Apple II Sweet Sixteen interpreter).
– dirkt
Sep 11 at 10:44
I'd also say it is unintentional, and probably a consequence of the "pipelining" done inside the 6502. One could check the "how" on visual6502.org. I've never seen an example where the byte after the BRK is used, though that doesn't mean there aren't any ... Though I know examples where bytes after a JSR have been used (e.g. in the Apple II Sweet Sixteen interpreter).
– dirkt
Sep 11 at 10:44
1
1
"Intentional" is a fuzzy thing. If it got that way as a result of transistor count, and someone at MOS noticed it and said "hey, that could actually be useful as a way to get information to the BRK handler, make sure not to change it", is that intentional or not? Several older architectures, before the "stack" concept was well-developed, would use caller-PC-relative data like that, so it's not an unheard-of idea.
– hobbs
Sep 11 at 16:22
"Intentional" is a fuzzy thing. If it got that way as a result of transistor count, and someone at MOS noticed it and said "hey, that could actually be useful as a way to get information to the BRK handler, make sure not to change it", is that intentional or not? Several older architectures, before the "stack" concept was well-developed, would use caller-PC-relative data like that, so it's not an unheard-of idea.
– hobbs
Sep 11 at 16:22
@hobbs You could still use that technique to get information to the
BRK
handler if the return address were the one right after BRK
, rather than the one after, just as is done with JSR
. 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 a NOP
after BRK
) if you're using a handler that doesn't take parameter data after the instruction.– Curt J. Sampson
Sep 11 at 16:27
@hobbs You could still use that technique to get information to the
BRK
handler if the return address were the one right after BRK
, rather than the one after, just as is done with JSR
. 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 a NOP
after BRK
) if you're using a handler that doesn't take parameter data after the instruction.– Curt J. Sampson
Sep 11 at 16:27
I'm also keeping away from intentional/unintentional but I'll vote for: likely easier. All single-byte 6502 instructions do a redundant fetch of the byte after them both for the usual 6502 marking-time reasons and to unify the one-byte and two-byte instruction execution patterns, so I'll guess that BRK just lets slide an internal modification to the PC that the other one-byte instructions undo.
– Tommy
Sep 11 at 17:42
I'm also keeping away from intentional/unintentional but I'll vote for: likely easier. All single-byte 6502 instructions do a redundant fetch of the byte after them both for the usual 6502 marking-time reasons and to unify the one-byte and two-byte instruction execution patterns, so I'll guess that BRK just lets slide an internal modification to the PC that the other one-byte instructions undo.
– Tommy
Sep 11 at 17:42
1
1
@Tommy: The 6502 determines what address will be accessed on any given cycle before it has received the byte of data from the previous cycle. An instruction like INX requires an internal bus cycle to read the old value from the X register and an internal cycle to write the new value; the read takes place during the dummy operand fetch and the write-back during the next opcode fetch. NOP is just about the only instruction that could realistically execute as one-byte-one-cycle.
– supercat
Sep 12 at 23:56
@Tommy: The 6502 determines what address will be accessed on any given cycle before it has received the byte of data from the previous cycle. An instruction like INX requires an internal bus cycle to read the old value from the X register and an internal cycle to write the new value; the read takes place during the dummy operand fetch and the write-back during the next opcode fetch. NOP is just about the only instruction that could realistically execute as one-byte-one-cycle.
– supercat
Sep 12 at 23:56
|
show 4 more comments
3 Answers
3
active
oldest
votes
On the BBC Micro, the byte after the BRK instruction held the error number, followed by the error message string terminated with 0x0D. CALLing the address of the BRK instruction would cause an error to be raised.
Update with example, as a runnable BBC BASIC program:
10 DIM b% 32
20 ?b%=0: REM BRK
30 ?(b%+1)=42: REM Error number 42
40 $(b%+2)="StackExchange"
50 CALL b%
>RUN
StackExchange at line 50
>PRINT ERR
42
>_
1
Can you describe in a little more detail how this worked? For example, was code after theBRK
and its following argument ever executed, or did that always just terminate the program right there?
– Curt J. Sampson
Sep 11 at 12:27
3
I've given an example of how it would be invoked, as a BASIC program (though, more likely it would be a machine code routine that would do this). As for terminating the program, if ?(b%+1) isn't zero the error is trappable with ON ERROR, with the error number in ERR, the line number in ERL and the text of the error in REPORT$.
– Soruk
Sep 11 at 13:15
So just to confirm, in this code, if there were another line,60 PRINT "Continuing..."
, that would not be executed before you ended up back at the BASIC prompt?
– Curt J. Sampson
Sep 11 at 13:20
2
So this answer doesn't actually answer my real question, though it was very helpful in helping my clarify what I was actually trying ask. (So thanks!) I've rewritten my question to make it clear that I'm looking for examples that do an RTI to the address pushed by theBRK
.
– Curt J. Sampson
Sep 11 at 14:10
3
For fun: bbc.godbolt.org/?loadBasic=https://gist.githubusercontent.com/… will demo this from a gist (gist.github.com/mattgodbolt/9b5932abf238c91cbf36083813e7ce16 )
– Matt G
Sep 11 at 18:50
|
show 6 more comments
The BRK instruction on the MOS 6502 seems to be one of the more ill-documented features of the processor. [...]
Given the lack of documentation about this
It is documented quite well and in depth in the corresponding MCS 6500 Microcomputer Family Programming Manual of January 1976 (and all follow ups). Check page 144 and after for description, reasoning and examples.
(This is mentioned nowhere in those two data sheets.)
Data sheets aren't meant as full documentation, but rather giving an overview.
However, unlike an IRQ interrupting any other 1-byte instruction,
This might be a first misunderstanding. BRK
isn't a 1-byte instruction interrupted by IRQ
, but rather an instruction working like IRQ
. The difference is in cause and effect - here the way the instruction works. With an external interrupt it gets handled before the PC is advanced on the next instruction (technically by inserting a BRK
). With a BRK the instruction gets fetched and processed (over two cycles) before the PC is pushed.
Still this doesn't make it a two byte instruction, it stays a one byte instruction with the workings of advancing PC by two before pushing.
I'm guessing that this was unintentional (though evidence otherwise is welcome!),
I'd say it was quite intentional. With the 6500 being designed as an extremely low cost CPU, it was what could be achieved with a bare minimum in additional circuitry. So instead of setting up a separate vector the IRQ vector was used - in fact, BRK processing is even used to make IRQ/NMI/RES happen.
The increment by two is part of this too, as that's the default behaviour of 6502 instructions, as all take two cycles at least. Single byte instructions need to explicitly disable the increment during the second cycle. Since BRK isn't a normal instruction, intended to be executed in a regular sequence and situation, adding that correction wouldn't make any difference.
BRK was never intended to be more than a debugging aid. A use that never comes up in regular use, thus its rather cumbersome detection and the need to readjust PC as well did not do much harm. In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.
It's all about offering an in-place debugging-aid with the least effort possible.
Similar the use of x'00' as opcode as any (back then) (E)PROM can always be patched to contain all zero in a location, enabling debugging of PROM code. Similar is forcing the data bus to zero, to detect a special case during problem analysis, an easy task, not requiring a lot of hardware.
All of this has to be seen interlinked.
but it does allow you to do something interesting, which is to use the byte after the BRK as a parameter to the IRQ routine.
Yes, that has been done many times. After all, and at first sight, it seems like a really nifty SuperVisor Call type of instruction. Looking closely it does involve quite some address juggling. So much so that more performance-aware developers usually preferred to use JSR
calls instead, as their return address can be used directly with less stack mangling as well (*2).
I'm not terribly interested in examples from embedded systems
Sure, valid point - still, to understand why things have been made the way they are, it's always a good idea to keep in mind that the 6502 wasn't developed with a general purpose computer in mind, but embedded use. The whole point was to make a very cheap CPU and support it with (for that time) quite complex and versatile I/O companion chips integrating several previous separate components into one (e.g. 653x type).
*1 - Or emulating it and advancing the PC to after the whole instruction
*2 - See the ProDOS MLI as main example, but IIRC Woz used it already in 1977 to call Sweet-16 sequences.
2
"BRK isn't a 1-byte instruction interrupted by IRQ, but rather an instruction working like IRQ." No misunderstanding here; this is exactly what I meant. That's why I said "an IRQ interrupting any other 1-byte instruction." Thanks for your explanation of the implementation ofBRK
; I had suspected it was something like this that led to the "spare byte."
– Curt J. Sampson
Sep 11 at 12:25
I've also added footnote ³ to clarify what I mean by "unintentional." In this context, that extra byte appears, from your description, indeed to have been unintentional.
– Curt J. Sampson
Sep 11 at 12:38
Regarding Sweet 16, Woz usedJSR
in the Apple II, presumably becauseBRK
was already used to enter the monitor (IRQ
at$FA86
), but he explicitly suggests in the BYTE article, "You may wish to handle the break instruction as a SWEET16 call, saving two bytes of code each time you transfer into SWEET16 mode."
– Curt J. Sampson
Sep 11 at 13:16
@CurtJ.Sampson Well, having BRK dump into monitor is exactly what it's meant for. When debugging with the monitor, one writes 00 into wherever a stop is needed, hits go and ends up in monitor again when the stop is reached. Now, having BRK to enter some routine (like Sweet16) may save a byte on each call, but wastes a lot of cycles to handle address fetch and return. So it's always up to what specific optimization goal is higher prioritized. In general I'd go for cycles, as memory isn't that limited.
– Raffzahn
Sep 11 at 21:36
1
"In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.” I suspect this is the main reason. You want to be able to add and remove breakpoints on the fly.
– Mark Williams
Sep 15 at 7:29
add a comment
|
The SOS operating system written for the Apple /// used BRK
for operating system calls. The byte following the BRK
holds the OS function number.
Of course, the two bytes after that are also used as inline data, so you can argue that it's not a true example of BRK
with a signature byte. Still, it's an example of "real world" code using inline data after a BRK
.
Regarding the RTI
: looking at this disassembly, page 112 in the PDF, IRQ.RCVR
appears to be the BRK
entry point. It eventually jumps to DISPATCH
on page 118. At the bottom of page 119 it invokes an RTI
instruction.
Good point. Haven't thought of SOS.
– Raffzahn
Sep 12 at 10:47
add a comment
|
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "648"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f12291%2fwhat-are-uses-of-the-byte-after-brk-instruction-on-6502%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
On the BBC Micro, the byte after the BRK instruction held the error number, followed by the error message string terminated with 0x0D. CALLing the address of the BRK instruction would cause an error to be raised.
Update with example, as a runnable BBC BASIC program:
10 DIM b% 32
20 ?b%=0: REM BRK
30 ?(b%+1)=42: REM Error number 42
40 $(b%+2)="StackExchange"
50 CALL b%
>RUN
StackExchange at line 50
>PRINT ERR
42
>_
1
Can you describe in a little more detail how this worked? For example, was code after theBRK
and its following argument ever executed, or did that always just terminate the program right there?
– Curt J. Sampson
Sep 11 at 12:27
3
I've given an example of how it would be invoked, as a BASIC program (though, more likely it would be a machine code routine that would do this). As for terminating the program, if ?(b%+1) isn't zero the error is trappable with ON ERROR, with the error number in ERR, the line number in ERL and the text of the error in REPORT$.
– Soruk
Sep 11 at 13:15
So just to confirm, in this code, if there were another line,60 PRINT "Continuing..."
, that would not be executed before you ended up back at the BASIC prompt?
– Curt J. Sampson
Sep 11 at 13:20
2
So this answer doesn't actually answer my real question, though it was very helpful in helping my clarify what I was actually trying ask. (So thanks!) I've rewritten my question to make it clear that I'm looking for examples that do an RTI to the address pushed by theBRK
.
– Curt J. Sampson
Sep 11 at 14:10
3
For fun: bbc.godbolt.org/?loadBasic=https://gist.githubusercontent.com/… will demo this from a gist (gist.github.com/mattgodbolt/9b5932abf238c91cbf36083813e7ce16 )
– Matt G
Sep 11 at 18:50
|
show 6 more comments
On the BBC Micro, the byte after the BRK instruction held the error number, followed by the error message string terminated with 0x0D. CALLing the address of the BRK instruction would cause an error to be raised.
Update with example, as a runnable BBC BASIC program:
10 DIM b% 32
20 ?b%=0: REM BRK
30 ?(b%+1)=42: REM Error number 42
40 $(b%+2)="StackExchange"
50 CALL b%
>RUN
StackExchange at line 50
>PRINT ERR
42
>_
1
Can you describe in a little more detail how this worked? For example, was code after theBRK
and its following argument ever executed, or did that always just terminate the program right there?
– Curt J. Sampson
Sep 11 at 12:27
3
I've given an example of how it would be invoked, as a BASIC program (though, more likely it would be a machine code routine that would do this). As for terminating the program, if ?(b%+1) isn't zero the error is trappable with ON ERROR, with the error number in ERR, the line number in ERL and the text of the error in REPORT$.
– Soruk
Sep 11 at 13:15
So just to confirm, in this code, if there were another line,60 PRINT "Continuing..."
, that would not be executed before you ended up back at the BASIC prompt?
– Curt J. Sampson
Sep 11 at 13:20
2
So this answer doesn't actually answer my real question, though it was very helpful in helping my clarify what I was actually trying ask. (So thanks!) I've rewritten my question to make it clear that I'm looking for examples that do an RTI to the address pushed by theBRK
.
– Curt J. Sampson
Sep 11 at 14:10
3
For fun: bbc.godbolt.org/?loadBasic=https://gist.githubusercontent.com/… will demo this from a gist (gist.github.com/mattgodbolt/9b5932abf238c91cbf36083813e7ce16 )
– Matt G
Sep 11 at 18:50
|
show 6 more comments
On the BBC Micro, the byte after the BRK instruction held the error number, followed by the error message string terminated with 0x0D. CALLing the address of the BRK instruction would cause an error to be raised.
Update with example, as a runnable BBC BASIC program:
10 DIM b% 32
20 ?b%=0: REM BRK
30 ?(b%+1)=42: REM Error number 42
40 $(b%+2)="StackExchange"
50 CALL b%
>RUN
StackExchange at line 50
>PRINT ERR
42
>_
On the BBC Micro, the byte after the BRK instruction held the error number, followed by the error message string terminated with 0x0D. CALLing the address of the BRK instruction would cause an error to be raised.
Update with example, as a runnable BBC BASIC program:
10 DIM b% 32
20 ?b%=0: REM BRK
30 ?(b%+1)=42: REM Error number 42
40 $(b%+2)="StackExchange"
50 CALL b%
>RUN
StackExchange at line 50
>PRINT ERR
42
>_
edited Sep 11 at 13:12
answered Sep 11 at 11:23
SorukSoruk
4411 silver badge5 bronze badges
4411 silver badge5 bronze badges
1
Can you describe in a little more detail how this worked? For example, was code after theBRK
and its following argument ever executed, or did that always just terminate the program right there?
– Curt J. Sampson
Sep 11 at 12:27
3
I've given an example of how it would be invoked, as a BASIC program (though, more likely it would be a machine code routine that would do this). As for terminating the program, if ?(b%+1) isn't zero the error is trappable with ON ERROR, with the error number in ERR, the line number in ERL and the text of the error in REPORT$.
– Soruk
Sep 11 at 13:15
So just to confirm, in this code, if there were another line,60 PRINT "Continuing..."
, that would not be executed before you ended up back at the BASIC prompt?
– Curt J. Sampson
Sep 11 at 13:20
2
So this answer doesn't actually answer my real question, though it was very helpful in helping my clarify what I was actually trying ask. (So thanks!) I've rewritten my question to make it clear that I'm looking for examples that do an RTI to the address pushed by theBRK
.
– Curt J. Sampson
Sep 11 at 14:10
3
For fun: bbc.godbolt.org/?loadBasic=https://gist.githubusercontent.com/… will demo this from a gist (gist.github.com/mattgodbolt/9b5932abf238c91cbf36083813e7ce16 )
– Matt G
Sep 11 at 18:50
|
show 6 more comments
1
Can you describe in a little more detail how this worked? For example, was code after theBRK
and its following argument ever executed, or did that always just terminate the program right there?
– Curt J. Sampson
Sep 11 at 12:27
3
I've given an example of how it would be invoked, as a BASIC program (though, more likely it would be a machine code routine that would do this). As for terminating the program, if ?(b%+1) isn't zero the error is trappable with ON ERROR, with the error number in ERR, the line number in ERL and the text of the error in REPORT$.
– Soruk
Sep 11 at 13:15
So just to confirm, in this code, if there were another line,60 PRINT "Continuing..."
, that would not be executed before you ended up back at the BASIC prompt?
– Curt J. Sampson
Sep 11 at 13:20
2
So this answer doesn't actually answer my real question, though it was very helpful in helping my clarify what I was actually trying ask. (So thanks!) I've rewritten my question to make it clear that I'm looking for examples that do an RTI to the address pushed by theBRK
.
– Curt J. Sampson
Sep 11 at 14:10
3
For fun: bbc.godbolt.org/?loadBasic=https://gist.githubusercontent.com/… will demo this from a gist (gist.github.com/mattgodbolt/9b5932abf238c91cbf36083813e7ce16 )
– Matt G
Sep 11 at 18:50
1
1
Can you describe in a little more detail how this worked? For example, was code after the
BRK
and its following argument ever executed, or did that always just terminate the program right there?– Curt J. Sampson
Sep 11 at 12:27
Can you describe in a little more detail how this worked? For example, was code after the
BRK
and its following argument ever executed, or did that always just terminate the program right there?– Curt J. Sampson
Sep 11 at 12:27
3
3
I've given an example of how it would be invoked, as a BASIC program (though, more likely it would be a machine code routine that would do this). As for terminating the program, if ?(b%+1) isn't zero the error is trappable with ON ERROR, with the error number in ERR, the line number in ERL and the text of the error in REPORT$.
– Soruk
Sep 11 at 13:15
I've given an example of how it would be invoked, as a BASIC program (though, more likely it would be a machine code routine that would do this). As for terminating the program, if ?(b%+1) isn't zero the error is trappable with ON ERROR, with the error number in ERR, the line number in ERL and the text of the error in REPORT$.
– Soruk
Sep 11 at 13:15
So just to confirm, in this code, if there were another line,
60 PRINT "Continuing..."
, that would not be executed before you ended up back at the BASIC prompt?– Curt J. Sampson
Sep 11 at 13:20
So just to confirm, in this code, if there were another line,
60 PRINT "Continuing..."
, that would not be executed before you ended up back at the BASIC prompt?– Curt J. Sampson
Sep 11 at 13:20
2
2
So this answer doesn't actually answer my real question, though it was very helpful in helping my clarify what I was actually trying ask. (So thanks!) I've rewritten my question to make it clear that I'm looking for examples that do an RTI to the address pushed by the
BRK
.– Curt J. Sampson
Sep 11 at 14:10
So this answer doesn't actually answer my real question, though it was very helpful in helping my clarify what I was actually trying ask. (So thanks!) I've rewritten my question to make it clear that I'm looking for examples that do an RTI to the address pushed by the
BRK
.– Curt J. Sampson
Sep 11 at 14:10
3
3
For fun: bbc.godbolt.org/?loadBasic=https://gist.githubusercontent.com/… will demo this from a gist (gist.github.com/mattgodbolt/9b5932abf238c91cbf36083813e7ce16 )
– Matt G
Sep 11 at 18:50
For fun: bbc.godbolt.org/?loadBasic=https://gist.githubusercontent.com/… will demo this from a gist (gist.github.com/mattgodbolt/9b5932abf238c91cbf36083813e7ce16 )
– Matt G
Sep 11 at 18:50
|
show 6 more comments
The BRK instruction on the MOS 6502 seems to be one of the more ill-documented features of the processor. [...]
Given the lack of documentation about this
It is documented quite well and in depth in the corresponding MCS 6500 Microcomputer Family Programming Manual of January 1976 (and all follow ups). Check page 144 and after for description, reasoning and examples.
(This is mentioned nowhere in those two data sheets.)
Data sheets aren't meant as full documentation, but rather giving an overview.
However, unlike an IRQ interrupting any other 1-byte instruction,
This might be a first misunderstanding. BRK
isn't a 1-byte instruction interrupted by IRQ
, but rather an instruction working like IRQ
. The difference is in cause and effect - here the way the instruction works. With an external interrupt it gets handled before the PC is advanced on the next instruction (technically by inserting a BRK
). With a BRK the instruction gets fetched and processed (over two cycles) before the PC is pushed.
Still this doesn't make it a two byte instruction, it stays a one byte instruction with the workings of advancing PC by two before pushing.
I'm guessing that this was unintentional (though evidence otherwise is welcome!),
I'd say it was quite intentional. With the 6500 being designed as an extremely low cost CPU, it was what could be achieved with a bare minimum in additional circuitry. So instead of setting up a separate vector the IRQ vector was used - in fact, BRK processing is even used to make IRQ/NMI/RES happen.
The increment by two is part of this too, as that's the default behaviour of 6502 instructions, as all take two cycles at least. Single byte instructions need to explicitly disable the increment during the second cycle. Since BRK isn't a normal instruction, intended to be executed in a regular sequence and situation, adding that correction wouldn't make any difference.
BRK was never intended to be more than a debugging aid. A use that never comes up in regular use, thus its rather cumbersome detection and the need to readjust PC as well did not do much harm. In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.
It's all about offering an in-place debugging-aid with the least effort possible.
Similar the use of x'00' as opcode as any (back then) (E)PROM can always be patched to contain all zero in a location, enabling debugging of PROM code. Similar is forcing the data bus to zero, to detect a special case during problem analysis, an easy task, not requiring a lot of hardware.
All of this has to be seen interlinked.
but it does allow you to do something interesting, which is to use the byte after the BRK as a parameter to the IRQ routine.
Yes, that has been done many times. After all, and at first sight, it seems like a really nifty SuperVisor Call type of instruction. Looking closely it does involve quite some address juggling. So much so that more performance-aware developers usually preferred to use JSR
calls instead, as their return address can be used directly with less stack mangling as well (*2).
I'm not terribly interested in examples from embedded systems
Sure, valid point - still, to understand why things have been made the way they are, it's always a good idea to keep in mind that the 6502 wasn't developed with a general purpose computer in mind, but embedded use. The whole point was to make a very cheap CPU and support it with (for that time) quite complex and versatile I/O companion chips integrating several previous separate components into one (e.g. 653x type).
*1 - Or emulating it and advancing the PC to after the whole instruction
*2 - See the ProDOS MLI as main example, but IIRC Woz used it already in 1977 to call Sweet-16 sequences.
2
"BRK isn't a 1-byte instruction interrupted by IRQ, but rather an instruction working like IRQ." No misunderstanding here; this is exactly what I meant. That's why I said "an IRQ interrupting any other 1-byte instruction." Thanks for your explanation of the implementation ofBRK
; I had suspected it was something like this that led to the "spare byte."
– Curt J. Sampson
Sep 11 at 12:25
I've also added footnote ³ to clarify what I mean by "unintentional." In this context, that extra byte appears, from your description, indeed to have been unintentional.
– Curt J. Sampson
Sep 11 at 12:38
Regarding Sweet 16, Woz usedJSR
in the Apple II, presumably becauseBRK
was already used to enter the monitor (IRQ
at$FA86
), but he explicitly suggests in the BYTE article, "You may wish to handle the break instruction as a SWEET16 call, saving two bytes of code each time you transfer into SWEET16 mode."
– Curt J. Sampson
Sep 11 at 13:16
@CurtJ.Sampson Well, having BRK dump into monitor is exactly what it's meant for. When debugging with the monitor, one writes 00 into wherever a stop is needed, hits go and ends up in monitor again when the stop is reached. Now, having BRK to enter some routine (like Sweet16) may save a byte on each call, but wastes a lot of cycles to handle address fetch and return. So it's always up to what specific optimization goal is higher prioritized. In general I'd go for cycles, as memory isn't that limited.
– Raffzahn
Sep 11 at 21:36
1
"In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.” I suspect this is the main reason. You want to be able to add and remove breakpoints on the fly.
– Mark Williams
Sep 15 at 7:29
add a comment
|
The BRK instruction on the MOS 6502 seems to be one of the more ill-documented features of the processor. [...]
Given the lack of documentation about this
It is documented quite well and in depth in the corresponding MCS 6500 Microcomputer Family Programming Manual of January 1976 (and all follow ups). Check page 144 and after for description, reasoning and examples.
(This is mentioned nowhere in those two data sheets.)
Data sheets aren't meant as full documentation, but rather giving an overview.
However, unlike an IRQ interrupting any other 1-byte instruction,
This might be a first misunderstanding. BRK
isn't a 1-byte instruction interrupted by IRQ
, but rather an instruction working like IRQ
. The difference is in cause and effect - here the way the instruction works. With an external interrupt it gets handled before the PC is advanced on the next instruction (technically by inserting a BRK
). With a BRK the instruction gets fetched and processed (over two cycles) before the PC is pushed.
Still this doesn't make it a two byte instruction, it stays a one byte instruction with the workings of advancing PC by two before pushing.
I'm guessing that this was unintentional (though evidence otherwise is welcome!),
I'd say it was quite intentional. With the 6500 being designed as an extremely low cost CPU, it was what could be achieved with a bare minimum in additional circuitry. So instead of setting up a separate vector the IRQ vector was used - in fact, BRK processing is even used to make IRQ/NMI/RES happen.
The increment by two is part of this too, as that's the default behaviour of 6502 instructions, as all take two cycles at least. Single byte instructions need to explicitly disable the increment during the second cycle. Since BRK isn't a normal instruction, intended to be executed in a regular sequence and situation, adding that correction wouldn't make any difference.
BRK was never intended to be more than a debugging aid. A use that never comes up in regular use, thus its rather cumbersome detection and the need to readjust PC as well did not do much harm. In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.
It's all about offering an in-place debugging-aid with the least effort possible.
Similar the use of x'00' as opcode as any (back then) (E)PROM can always be patched to contain all zero in a location, enabling debugging of PROM code. Similar is forcing the data bus to zero, to detect a special case during problem analysis, an easy task, not requiring a lot of hardware.
All of this has to be seen interlinked.
but it does allow you to do something interesting, which is to use the byte after the BRK as a parameter to the IRQ routine.
Yes, that has been done many times. After all, and at first sight, it seems like a really nifty SuperVisor Call type of instruction. Looking closely it does involve quite some address juggling. So much so that more performance-aware developers usually preferred to use JSR
calls instead, as their return address can be used directly with less stack mangling as well (*2).
I'm not terribly interested in examples from embedded systems
Sure, valid point - still, to understand why things have been made the way they are, it's always a good idea to keep in mind that the 6502 wasn't developed with a general purpose computer in mind, but embedded use. The whole point was to make a very cheap CPU and support it with (for that time) quite complex and versatile I/O companion chips integrating several previous separate components into one (e.g. 653x type).
*1 - Or emulating it and advancing the PC to after the whole instruction
*2 - See the ProDOS MLI as main example, but IIRC Woz used it already in 1977 to call Sweet-16 sequences.
2
"BRK isn't a 1-byte instruction interrupted by IRQ, but rather an instruction working like IRQ." No misunderstanding here; this is exactly what I meant. That's why I said "an IRQ interrupting any other 1-byte instruction." Thanks for your explanation of the implementation ofBRK
; I had suspected it was something like this that led to the "spare byte."
– Curt J. Sampson
Sep 11 at 12:25
I've also added footnote ³ to clarify what I mean by "unintentional." In this context, that extra byte appears, from your description, indeed to have been unintentional.
– Curt J. Sampson
Sep 11 at 12:38
Regarding Sweet 16, Woz usedJSR
in the Apple II, presumably becauseBRK
was already used to enter the monitor (IRQ
at$FA86
), but he explicitly suggests in the BYTE article, "You may wish to handle the break instruction as a SWEET16 call, saving two bytes of code each time you transfer into SWEET16 mode."
– Curt J. Sampson
Sep 11 at 13:16
@CurtJ.Sampson Well, having BRK dump into monitor is exactly what it's meant for. When debugging with the monitor, one writes 00 into wherever a stop is needed, hits go and ends up in monitor again when the stop is reached. Now, having BRK to enter some routine (like Sweet16) may save a byte on each call, but wastes a lot of cycles to handle address fetch and return. So it's always up to what specific optimization goal is higher prioritized. In general I'd go for cycles, as memory isn't that limited.
– Raffzahn
Sep 11 at 21:36
1
"In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.” I suspect this is the main reason. You want to be able to add and remove breakpoints on the fly.
– Mark Williams
Sep 15 at 7:29
add a comment
|
The BRK instruction on the MOS 6502 seems to be one of the more ill-documented features of the processor. [...]
Given the lack of documentation about this
It is documented quite well and in depth in the corresponding MCS 6500 Microcomputer Family Programming Manual of January 1976 (and all follow ups). Check page 144 and after for description, reasoning and examples.
(This is mentioned nowhere in those two data sheets.)
Data sheets aren't meant as full documentation, but rather giving an overview.
However, unlike an IRQ interrupting any other 1-byte instruction,
This might be a first misunderstanding. BRK
isn't a 1-byte instruction interrupted by IRQ
, but rather an instruction working like IRQ
. The difference is in cause and effect - here the way the instruction works. With an external interrupt it gets handled before the PC is advanced on the next instruction (technically by inserting a BRK
). With a BRK the instruction gets fetched and processed (over two cycles) before the PC is pushed.
Still this doesn't make it a two byte instruction, it stays a one byte instruction with the workings of advancing PC by two before pushing.
I'm guessing that this was unintentional (though evidence otherwise is welcome!),
I'd say it was quite intentional. With the 6500 being designed as an extremely low cost CPU, it was what could be achieved with a bare minimum in additional circuitry. So instead of setting up a separate vector the IRQ vector was used - in fact, BRK processing is even used to make IRQ/NMI/RES happen.
The increment by two is part of this too, as that's the default behaviour of 6502 instructions, as all take two cycles at least. Single byte instructions need to explicitly disable the increment during the second cycle. Since BRK isn't a normal instruction, intended to be executed in a regular sequence and situation, adding that correction wouldn't make any difference.
BRK was never intended to be more than a debugging aid. A use that never comes up in regular use, thus its rather cumbersome detection and the need to readjust PC as well did not do much harm. In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.
It's all about offering an in-place debugging-aid with the least effort possible.
Similar the use of x'00' as opcode as any (back then) (E)PROM can always be patched to contain all zero in a location, enabling debugging of PROM code. Similar is forcing the data bus to zero, to detect a special case during problem analysis, an easy task, not requiring a lot of hardware.
All of this has to be seen interlinked.
but it does allow you to do something interesting, which is to use the byte after the BRK as a parameter to the IRQ routine.
Yes, that has been done many times. After all, and at first sight, it seems like a really nifty SuperVisor Call type of instruction. Looking closely it does involve quite some address juggling. So much so that more performance-aware developers usually preferred to use JSR
calls instead, as their return address can be used directly with less stack mangling as well (*2).
I'm not terribly interested in examples from embedded systems
Sure, valid point - still, to understand why things have been made the way they are, it's always a good idea to keep in mind that the 6502 wasn't developed with a general purpose computer in mind, but embedded use. The whole point was to make a very cheap CPU and support it with (for that time) quite complex and versatile I/O companion chips integrating several previous separate components into one (e.g. 653x type).
*1 - Or emulating it and advancing the PC to after the whole instruction
*2 - See the ProDOS MLI as main example, but IIRC Woz used it already in 1977 to call Sweet-16 sequences.
The BRK instruction on the MOS 6502 seems to be one of the more ill-documented features of the processor. [...]
Given the lack of documentation about this
It is documented quite well and in depth in the corresponding MCS 6500 Microcomputer Family Programming Manual of January 1976 (and all follow ups). Check page 144 and after for description, reasoning and examples.
(This is mentioned nowhere in those two data sheets.)
Data sheets aren't meant as full documentation, but rather giving an overview.
However, unlike an IRQ interrupting any other 1-byte instruction,
This might be a first misunderstanding. BRK
isn't a 1-byte instruction interrupted by IRQ
, but rather an instruction working like IRQ
. The difference is in cause and effect - here the way the instruction works. With an external interrupt it gets handled before the PC is advanced on the next instruction (technically by inserting a BRK
). With a BRK the instruction gets fetched and processed (over two cycles) before the PC is pushed.
Still this doesn't make it a two byte instruction, it stays a one byte instruction with the workings of advancing PC by two before pushing.
I'm guessing that this was unintentional (though evidence otherwise is welcome!),
I'd say it was quite intentional. With the 6500 being designed as an extremely low cost CPU, it was what could be achieved with a bare minimum in additional circuitry. So instead of setting up a separate vector the IRQ vector was used - in fact, BRK processing is even used to make IRQ/NMI/RES happen.
The increment by two is part of this too, as that's the default behaviour of 6502 instructions, as all take two cycles at least. Single byte instructions need to explicitly disable the increment during the second cycle. Since BRK isn't a normal instruction, intended to be executed in a regular sequence and situation, adding that correction wouldn't make any difference.
BRK was never intended to be more than a debugging aid. A use that never comes up in regular use, thus its rather cumbersome detection and the need to readjust PC as well did not do much harm. In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.
It's all about offering an in-place debugging-aid with the least effort possible.
Similar the use of x'00' as opcode as any (back then) (E)PROM can always be patched to contain all zero in a location, enabling debugging of PROM code. Similar is forcing the data bus to zero, to detect a special case during problem analysis, an easy task, not requiring a lot of hardware.
All of this has to be seen interlinked.
but it does allow you to do something interesting, which is to use the byte after the BRK as a parameter to the IRQ routine.
Yes, that has been done many times. After all, and at first sight, it seems like a really nifty SuperVisor Call type of instruction. Looking closely it does involve quite some address juggling. So much so that more performance-aware developers usually preferred to use JSR
calls instead, as their return address can be used directly with less stack mangling as well (*2).
I'm not terribly interested in examples from embedded systems
Sure, valid point - still, to understand why things have been made the way they are, it's always a good idea to keep in mind that the 6502 wasn't developed with a general purpose computer in mind, but embedded use. The whole point was to make a very cheap CPU and support it with (for that time) quite complex and versatile I/O companion chips integrating several previous separate components into one (e.g. 653x type).
*1 - Or emulating it and advancing the PC to after the whole instruction
*2 - See the ProDOS MLI as main example, but IIRC Woz used it already in 1977 to call Sweet-16 sequences.
edited Sep 13 at 9:02
answered Sep 11 at 11:16
RaffzahnRaffzahn
75.8k9 gold badges190 silver badges316 bronze badges
75.8k9 gold badges190 silver badges316 bronze badges
2
"BRK isn't a 1-byte instruction interrupted by IRQ, but rather an instruction working like IRQ." No misunderstanding here; this is exactly what I meant. That's why I said "an IRQ interrupting any other 1-byte instruction." Thanks for your explanation of the implementation ofBRK
; I had suspected it was something like this that led to the "spare byte."
– Curt J. Sampson
Sep 11 at 12:25
I've also added footnote ³ to clarify what I mean by "unintentional." In this context, that extra byte appears, from your description, indeed to have been unintentional.
– Curt J. Sampson
Sep 11 at 12:38
Regarding Sweet 16, Woz usedJSR
in the Apple II, presumably becauseBRK
was already used to enter the monitor (IRQ
at$FA86
), but he explicitly suggests in the BYTE article, "You may wish to handle the break instruction as a SWEET16 call, saving two bytes of code each time you transfer into SWEET16 mode."
– Curt J. Sampson
Sep 11 at 13:16
@CurtJ.Sampson Well, having BRK dump into monitor is exactly what it's meant for. When debugging with the monitor, one writes 00 into wherever a stop is needed, hits go and ends up in monitor again when the stop is reached. Now, having BRK to enter some routine (like Sweet16) may save a byte on each call, but wastes a lot of cycles to handle address fetch and return. So it's always up to what specific optimization goal is higher prioritized. In general I'd go for cycles, as memory isn't that limited.
– Raffzahn
Sep 11 at 21:36
1
"In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.” I suspect this is the main reason. You want to be able to add and remove breakpoints on the fly.
– Mark Williams
Sep 15 at 7:29
add a comment
|
2
"BRK isn't a 1-byte instruction interrupted by IRQ, but rather an instruction working like IRQ." No misunderstanding here; this is exactly what I meant. That's why I said "an IRQ interrupting any other 1-byte instruction." Thanks for your explanation of the implementation ofBRK
; I had suspected it was something like this that led to the "spare byte."
– Curt J. Sampson
Sep 11 at 12:25
I've also added footnote ³ to clarify what I mean by "unintentional." In this context, that extra byte appears, from your description, indeed to have been unintentional.
– Curt J. Sampson
Sep 11 at 12:38
Regarding Sweet 16, Woz usedJSR
in the Apple II, presumably becauseBRK
was already used to enter the monitor (IRQ
at$FA86
), but he explicitly suggests in the BYTE article, "You may wish to handle the break instruction as a SWEET16 call, saving two bytes of code each time you transfer into SWEET16 mode."
– Curt J. Sampson
Sep 11 at 13:16
@CurtJ.Sampson Well, having BRK dump into monitor is exactly what it's meant for. When debugging with the monitor, one writes 00 into wherever a stop is needed, hits go and ends up in monitor again when the stop is reached. Now, having BRK to enter some routine (like Sweet16) may save a byte on each call, but wastes a lot of cycles to handle address fetch and return. So it's always up to what specific optimization goal is higher prioritized. In general I'd go for cycles, as memory isn't that limited.
– Raffzahn
Sep 11 at 21:36
1
"In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.” I suspect this is the main reason. You want to be able to add and remove breakpoints on the fly.
– Mark Williams
Sep 15 at 7:29
2
2
"BRK isn't a 1-byte instruction interrupted by IRQ, but rather an instruction working like IRQ." No misunderstanding here; this is exactly what I meant. That's why I said "an IRQ interrupting any other 1-byte instruction." Thanks for your explanation of the implementation of
BRK
; I had suspected it was something like this that led to the "spare byte."– Curt J. Sampson
Sep 11 at 12:25
"BRK isn't a 1-byte instruction interrupted by IRQ, but rather an instruction working like IRQ." No misunderstanding here; this is exactly what I meant. That's why I said "an IRQ interrupting any other 1-byte instruction." Thanks for your explanation of the implementation of
BRK
; I had suspected it was something like this that led to the "spare byte."– Curt J. Sampson
Sep 11 at 12:25
I've also added footnote ³ to clarify what I mean by "unintentional." In this context, that extra byte appears, from your description, indeed to have been unintentional.
– Curt J. Sampson
Sep 11 at 12:38
I've also added footnote ³ to clarify what I mean by "unintentional." In this context, that extra byte appears, from your description, indeed to have been unintentional.
– Curt J. Sampson
Sep 11 at 12:38
Regarding Sweet 16, Woz used
JSR
in the Apple II, presumably because BRK
was already used to enter the monitor (IRQ
at $FA86
), but he explicitly suggests in the BYTE article, "You may wish to handle the break instruction as a SWEET16 call, saving two bytes of code each time you transfer into SWEET16 mode."– Curt J. Sampson
Sep 11 at 13:16
Regarding Sweet 16, Woz used
JSR
in the Apple II, presumably because BRK
was already used to enter the monitor (IRQ
at $FA86
), but he explicitly suggests in the BYTE article, "You may wish to handle the break instruction as a SWEET16 call, saving two bytes of code each time you transfer into SWEET16 mode."– Curt J. Sampson
Sep 11 at 13:16
@CurtJ.Sampson Well, having BRK dump into monitor is exactly what it's meant for. When debugging with the monitor, one writes 00 into wherever a stop is needed, hits go and ends up in monitor again when the stop is reached. Now, having BRK to enter some routine (like Sweet16) may save a byte on each call, but wastes a lot of cycles to handle address fetch and return. So it's always up to what specific optimization goal is higher prioritized. In general I'd go for cycles, as memory isn't that limited.
– Raffzahn
Sep 11 at 21:36
@CurtJ.Sampson Well, having BRK dump into monitor is exactly what it's meant for. When debugging with the monitor, one writes 00 into wherever a stop is needed, hits go and ends up in monitor again when the stop is reached. Now, having BRK to enter some routine (like Sweet16) may save a byte on each call, but wastes a lot of cycles to handle address fetch and return. So it's always up to what specific optimization goal is higher prioritized. In general I'd go for cycles, as memory isn't that limited.
– Raffzahn
Sep 11 at 21:36
1
1
"In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.” I suspect this is the main reason. You want to be able to add and remove breakpoints on the fly.
– Mark Williams
Sep 15 at 7:29
"In fact, being a debugging tool, readjusting the PC to the original instruction address and replacing the instruction overwritten (*1) had to be done anyway.” I suspect this is the main reason. You want to be able to add and remove breakpoints on the fly.
– Mark Williams
Sep 15 at 7:29
add a comment
|
The SOS operating system written for the Apple /// used BRK
for operating system calls. The byte following the BRK
holds the OS function number.
Of course, the two bytes after that are also used as inline data, so you can argue that it's not a true example of BRK
with a signature byte. Still, it's an example of "real world" code using inline data after a BRK
.
Regarding the RTI
: looking at this disassembly, page 112 in the PDF, IRQ.RCVR
appears to be the BRK
entry point. It eventually jumps to DISPATCH
on page 118. At the bottom of page 119 it invokes an RTI
instruction.
Good point. Haven't thought of SOS.
– Raffzahn
Sep 12 at 10:47
add a comment
|
The SOS operating system written for the Apple /// used BRK
for operating system calls. The byte following the BRK
holds the OS function number.
Of course, the two bytes after that are also used as inline data, so you can argue that it's not a true example of BRK
with a signature byte. Still, it's an example of "real world" code using inline data after a BRK
.
Regarding the RTI
: looking at this disassembly, page 112 in the PDF, IRQ.RCVR
appears to be the BRK
entry point. It eventually jumps to DISPATCH
on page 118. At the bottom of page 119 it invokes an RTI
instruction.
Good point. Haven't thought of SOS.
– Raffzahn
Sep 12 at 10:47
add a comment
|
The SOS operating system written for the Apple /// used BRK
for operating system calls. The byte following the BRK
holds the OS function number.
Of course, the two bytes after that are also used as inline data, so you can argue that it's not a true example of BRK
with a signature byte. Still, it's an example of "real world" code using inline data after a BRK
.
Regarding the RTI
: looking at this disassembly, page 112 in the PDF, IRQ.RCVR
appears to be the BRK
entry point. It eventually jumps to DISPATCH
on page 118. At the bottom of page 119 it invokes an RTI
instruction.
The SOS operating system written for the Apple /// used BRK
for operating system calls. The byte following the BRK
holds the OS function number.
Of course, the two bytes after that are also used as inline data, so you can argue that it's not a true example of BRK
with a signature byte. Still, it's an example of "real world" code using inline data after a BRK
.
Regarding the RTI
: looking at this disassembly, page 112 in the PDF, IRQ.RCVR
appears to be the BRK
entry point. It eventually jumps to DISPATCH
on page 118. At the bottom of page 119 it invokes an RTI
instruction.
edited Sep 11 at 19:44
answered Sep 11 at 19:36
faddenfadden
4,5371 gold badge15 silver badges52 bronze badges
4,5371 gold badge15 silver badges52 bronze badges
Good point. Haven't thought of SOS.
– Raffzahn
Sep 12 at 10:47
add a comment
|
Good point. Haven't thought of SOS.
– Raffzahn
Sep 12 at 10:47
Good point. Haven't thought of SOS.
– Raffzahn
Sep 12 at 10:47
Good point. Haven't thought of SOS.
– Raffzahn
Sep 12 at 10:47
add a comment
|
Thanks for contributing an answer to Retrocomputing Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f12291%2fwhat-are-uses-of-the-byte-after-brk-instruction-on-6502%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
I'd also say it is unintentional, and probably a consequence of the "pipelining" done inside the 6502. One could check the "how" on visual6502.org. I've never seen an example where the byte after the BRK is used, though that doesn't mean there aren't any ... Though I know examples where bytes after a JSR have been used (e.g. in the Apple II Sweet Sixteen interpreter).
– dirkt
Sep 11 at 10:44
1
"Intentional" is a fuzzy thing. If it got that way as a result of transistor count, and someone at MOS noticed it and said "hey, that could actually be useful as a way to get information to the BRK handler, make sure not to change it", is that intentional or not? Several older architectures, before the "stack" concept was well-developed, would use caller-PC-relative data like that, so it's not an unheard-of idea.
– hobbs
Sep 11 at 16:22
@hobbs You could still use that technique to get information to the
BRK
handler 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 aNOP
afterBRK
) if you're using a handler that doesn't take parameter data after the instruction.– Curt J. Sampson
Sep 11 at 16:27
I'm also keeping away from intentional/unintentional but I'll vote for: likely easier. All single-byte 6502 instructions do a redundant fetch of the byte after them both for the usual 6502 marking-time reasons and to unify the one-byte and two-byte instruction execution patterns, so I'll guess that BRK just lets slide an internal modification to the PC that the other one-byte instructions undo.
– Tommy
Sep 11 at 17:42
1
@Tommy: The 6502 determines what address will be accessed on any given cycle before it has received the byte of data from the previous cycle. An instruction like INX requires an internal bus cycle to read the old value from the X register and an internal cycle to write the new value; the read takes place during the dummy operand fetch and the write-back during the next opcode fetch. NOP is just about the only instruction that could realistically execute as one-byte-one-cycle.
– supercat
Sep 12 at 23:56