Page 1 of 2
brk flag useless?
Posted: Wed Aug 14, 2013 2:53 pm
by Gadersd
I just took a look at every 6502 instruction and noticed non of them used the brk flag, not even the branch and set flag instructions. Does the brk flag do anything at all?
Re: brk flag useless?
Posted: Wed Aug 14, 2013 3:22 pm
by nyef
Yes. It's used by an interrupt handler to look at the flags saved on the stack and determine if it was called because of a software interrupt (BRK instruction) or a hardware interrupt (IRQ). Note that some (all?) versions of the 6502 can combine IRQ and BRK processing if the timing comes out correctly, so one call to the interrupt handler could be from both a BRK and an IRQ.
So, it's useful, but only in the context of the flags stored on the stack when starting an interrupt handler.
-- Alastair Bridgewater
Re: brk flag useless?
Posted: Wed Aug 14, 2013 5:49 pm
by BigEd
Indeed, so it's (often) read by PLA in an interrupt handler. You can't read the 'break flag' because there is no flag in that sense: there's a slot in the saved P state which is stuffed as needed when an interrupt or break happens, but there's no bit to be read in P. If you PHP and PLA you'll always see 1. Even if you push 0 and PLP it'll still be 1. See
http://www.visual6502.org/JSSim/expert. ... a&steps=44 for example.
Re: brk flag useless?
Posted: Thu Aug 15, 2013 6:04 am
by BigDumbDinosaur
I just took a look at every 6502 instruction and noticed non of them used the brk flag, not even the branch and set flag instructions. Does the brk flag do anything at all?
As Ed noted, the B bit in the status register (SR) is meaningful only in the copy of SR that is pushed at the time of an IRQ (hardware interrupt request) or software interrupt (BRK). The B bit is important because the 6502 and 65C02 vector both IRQ and BRK through the same address ($FFFE-$FFFF). Therefore, the IRQ/BRK handler has to determine what it is processing, usually via code similar to the following:
Code: Select all
pha ;save accumulator
txa
pha ;save .X
tya
pha ;save .Y
tsx ;current stack pointer
lda $0104,x ;get stack copy of SR
and #%00010000 ;mask for B bit
bne is_brk ;is a BRK
;
beq is_irq ;is an IRQ
The above sequence isn't required with the 65C816 when operating in native mode, as it has separate IRQ and BRK vectors. Also, the 65C02 has instructions to push the X and Y registers to the stack without using the accumulator as an intermediary, a feature that improves performance when the system is flooded with interrupts.
For more information, may I suggest giving Garth Wilson's interrupt primer a good read? He covers most everything needed to start using interrupts in your programs, and includes code examples of common tasks that benefit from interrupt processing. You'll also get a kick out of his vintage cartoons. 
Speaking of interrupt primers, I have been intermittently working on an interrupt article specific to the 65C816 in native mode. It will build on Garth's work and I'm hoping to soon have it posted for everyone's reading "pleasure."
Re: brk flag useless?
Posted: Thu Aug 15, 2013 6:15 am
by BigEd
Might be worth noting how Acorn's OS on the Beeb does this - they use a global to save A which means no need to dip into the stack:
Code: Select all
** MAIN IRQ Entry point **
;ON ENTRY STACK contains STATUS REGISTER,PCH,PCL ;
DC1C STA &FC ;save A
DC1E PLA ;get back status (flags)
DC1F PHA ;and save again
DC20 AND #&10 ;check if BRK flag set
DC22 BNE &DC27 ;if so goto DC27
DC24 JMP (&0204) ;else JMP (IRQ1V)
See
http://mdfs.net/Docs/Comp/BBC/OS1-20/DC1C
Cheers
Ed
Re: brk flag useless?
Posted: Thu Aug 15, 2013 6:28 am
by Arlet
Similarly on the Atom:
Code: Select all
FFB2 85 FF STA #FF Save accumulator
FFB4 68 PLA Get status
FFB5 48 PHA Re-save status
FFB6 29 10 AND @#10 Is it IRQ or BRK ?
FFB8 D0 06 BNE #FFC0 ..it's BRK - deal with it
FFBA A5 FF LDA #FF Restore accumulator
FFBC 48 PHA Save accumulator onto stack
FFBD 6C 04 02 JMP (#204) ..before jumping to IRQVEC
Re: brk flag useless?
Posted: Thu Aug 15, 2013 4:47 pm
by BigDumbDinosaur
The only problem with storing .A into RAM is the ISR is not reentrant. Otherwise, it does eliminate most of the stack acrobatics.
Re: brk flag useless?
Posted: Thu Aug 15, 2013 5:55 pm
by BigEd
Fair point about re-entrancy!
Re: brk flag useless?
Posted: Thu Aug 15, 2013 6:18 pm
by rwiker
The only problem with storing .A into RAM is the ISR is not reentrant. Otherwise, it does eliminate most of the stack acrobatics.
I'm not sure that is much of a shortcoming... I'd expect A to be restored and if necessary pushed on the stack before interrupts are re-enabled, and that the BRK instruction would not be used in interrupt handlers.
Re: brk flag useless?
Posted: Thu Aug 15, 2013 7:00 pm
by BigDumbDinosaur
The only problem with storing .A into RAM is the ISR is not reentrant. Otherwise, it does eliminate most of the stack acrobatics.
I'm not sure that is much of a shortcoming... I'd expect A to be restored and if necessary pushed on the stack before interrupts are re-enabled, and that the BRK instruction would not be used in interrupt handlers.
Huh? We're talking about determining if the ISR is processing a hardware or software interrupt. I didn't say anything about using BRK inside an ISR (that would be somewhat bizarre, although certainly possible). The only way to make the interrupt type distinction in the 65(c)02 is by loading .A with the SR copy that was pushed to the stack and masking for the B bit. Aside from distinguishing between IRQ and BRK, almost any non-trivial IRQ handler will end up using .A for something else (distinguishing interrupt events in a 65C22, for example), which means .A has to be preserved on the stack (not RAM) if reentrancy is desired.
Now, you may well argue that the scenario of nested interrupts won't occur in your system because you won't re-enable IRQs inside your IRQ handler, and therefore reentrancy will be unnecessary. Fine. What do you plan to do if an NMI occurs while the MPU is executing IRQ handler code? That's a nested interrupt, and as NMIs can't be masked and have priority over IRQs, execution of your IRQ handler will be suspended while the NMI is serviced. Unless your NMI handler is reentrant your system will probably go belly-up when the NMI handler exits.
Re: brk flag useless?
Posted: Thu Aug 15, 2013 7:06 pm
by BigEd
Hi BDD surely it's a valid point that A can be restored from ZP within a few instructions, and so long as that happens before CLI, all is well.
Ed
Re: brk flag useless?
Posted: Thu Aug 15, 2013 7:30 pm
by Arlet
Huh? We're talking about determining if the ISR is processing a hardware or software interrupt. I didn't say anything about using BRK inside an ISR (that would be somewhat bizarre, although certainly possible). The only way to make the interrupt type distinction in the 65(c)02 is by loading .A with the SR copy that was pushed to the stack and masking for the B bit. Aside from distinguishing between IRQ and BRK, almost any non-trivial IRQ handler will end up using .A for something else (distinguishing interrupt events in a 65C22, for example), which means .A has to be preserved on the stack (not RAM) if reentrancy is desired.
The Atom code does a quick check for BRK by saving A in ZP. Since IRQ is not enabled, that's perfectly safe. If the BRK code does not need to be reentrant, it's also safe to leave A in the ZP location while handling the BRK. Only when the code has decided it's dealing with an IRQ, and this particular type of IRQ is reentrant, the A is read from the ZP location, and pushed on the stack (like the Atom code does). What rwiker was referring to is the fact that this fails when you do a BRK inside the IRQ while the ZP location still holds A. But if you're careful enough not to do that, all is well.
What do you plan to do if an NMI occurs while the MPU is executing IRQ handler code? That's a nested interrupt, and as NMIs can't be masked and have priority over IRQs, execution of your IRQ handler will be suspended while the NMI is serviced. Unless your NMI handler is reentrant your system will probably go belly-up when the NMI handler exits.
The NMI handler doesn't have to check for BRK, so it can just do PHA, and everything will work fine.
Re: brk flag useless?
Posted: Thu Aug 15, 2013 8:03 pm
by nyef
The NMI handler doesn't have to check for BRK, so it can just do PHA, and everything will work fine.
I think that this is the bug that I'm remembering: A badly-timed coincidence of BRK and NMI can cause the NMI handler to be entered with the BRK flag stored on the stack just as would normally happen with BRK and the IRQ handler. The catch being that the NMI handler is then left "holding the bag", as it were, for dealing with the BRK as well. I'm not sure if this applies to the more recent CMOS chips, just the original NMOS chips, or maybe all chips, but it's the sort of thing that could cause once-in-a-blue-moon missed BRK processing.
Or my memory could be massively faulty right about now and I'm making the whole thing up, or it applies to an entirely separate CPU family or something.
Re: brk flag useless?
Posted: Thu Aug 15, 2013 8:12 pm
by BigEd
It's a good point: there are some subtleties. There's a writeup at
http://visual6502.org/wiki/index.php?ti ... _and_B_bit
Cheers
Ed
Re: brk flag useless?
Posted: Fri Aug 16, 2013 1:05 am
by ElEctric_EyE
Permit me to express my opinion and thereby also reveal my ignorance on interrupts: I dislike interrupts. I've never used them. They seem to have been made for slow machines.
However the level of detail being paid attention here recently in this discussion is very interesting regarding NMI and IRQ(hardware trigger or software BRK opcode). I've never wrote software to take these things into account, so some of the shared code is appreciated.
A fast enough 6502 doesn't need interrupts does it? It should have sufficient time to poll all flags/inputs within the system.