GaBuZoMeu wrote:
I would setup the IRQ vector to point to a "JMP IRQservice" instruction somewhere in RAM. (Perhaps after checking whether it was an IRQ or a BRK.) This instruction ($4C XX YY) could be placed in a fixed location in RAM during the initial setup after reset. The address $YYXX provided after reset is the address of the BIOS service routine.
If your application wants to change that, it could overwrite XX YY with a new target address. (You may either save the original value somewhere or perhaps changing the BIOS setup in a way that there is a small subroutine that initializes this JMP to its default direction.)
The BIOS_ISR may even written in a way that it calls another RAM based JMP (say "JMP IRQservice_exit") that is setup to point to a RTI instruction. Then you have the choice of processing interrupts before and/or after BIOS.
See my comments below to BDD.
BigDumbDinosaur wrote:
Alarm Siren wrote:
As best as I can tell, this isn't possible natively, but I thought someone might have an idea...
Just my curmudgeonly opinion, but it seems to me like a convoluted way to go about it. In my POC BIOS, I just have the ISR handler jump through a page 1 vector, which normally points back to the continuation of the ISR. If I want to add something to the ISR I just point the vector to it, with the "wedged" add-on saving the original vector and jumping to it when done. If my wedge is
replacing the BIOS' ISR it has the necessary code at the end to restore the MPU state and return to the foreground routine.
That is definitely the simplest method and one I have considered, but I rejected it because it requires the user programmer have an understanding of the internal operation of the IRQ handler in order to properly handle the various different circumstances. Also, if a naughty programmer didn't save the original IRQ vector but instead hard-coded it "because it never changes" and then I did change it.... my method doesn't allow the programmer to make that mistake and because its treated like a standard subroutine call within the ISR, doesn't require any special knowledge of the internal workings of the ISR.
Basically, I'm trying to make my BIOS API inherently backwards-compatible by not relying on any specific addresses, and insofar as is possible, make it resistant to programmers doing naughty things.
BigDumbDinosaur wrote:
As a rule, I never use subroutine calls in an ISR.
Why not? I know there will be a small performance hit from using JSR/RTS over JMP (a) JMP, but based on my reading of the datasheet, looking at 12 cycles vs 8 cycles respectively, which is hardly the end of the world...
leepivonka wrote:
You can "jsr abs" to a "jmp (abs)".
Something like:
etc
JSR ?ToBiosIrqHandler ; JSR (biosIrqHandler)
etc
JSR ?ToBiosIrqHandler ; JSR (biosIrqHandler)
etc
RTI
?ToBiosIrqHandler: JMP (biosIrqHandler)
Thank you, I hadn't considered that possibility but of course it provides the required functionality and is dead simple.
GARTHWILSON wrote:
If it's only in one place, and in RAM, it would work well to use self-modifying code, where the variable holding the address to JSR to is the JSR instruction's own operand. That eliminates the need for variable space elsewhere too, including in precious ZP space.
Unfortunately the whole BIOS IRQ routine is in the BIOS ROM, so this isn't an option.
[quuote="GARTHWILSON"]Whether you do it this way or not, make sure an interrupt can't hit between the writing of the two address bytes, since then you'll jump to an invalid address.[/quote]
A very good point. In the case of my API design, I'll make a note. Either you should SEI/CLI around that bit or you could BBR the relevant bits of my IRQ Control register. I think I prefer the latter in that is doesn't prevent the IRQ from firing immediately for vanilla functionality, but will also not cause the incomplete address to be dereferenced.
GARTHWILSON wrote:
My 6502 stacks treatise has a chapter on synthesizing instructions with RTS, RTI, and JSR, at
http://wilsonminesco.com/stacks/RTSsynth.html .
Your website is a literal treasure trove, sir! I've most recently been having a good long read through your Stacks Treatise. Admittedly I've implemented it a bit differently to your method (I didn't like the idea of putting it in ZP as that space is precious), but I have got a software stack now for parameter passing.
Thank you all for your kind assistance, as always.
----
For my P.S. where
Code:
BBS0 biosIrqMode, ?HandlerPrologue
is for some reason (as best as I can tell a bug in the assembler) rejected due to an "invalid addressing mode" on biosIrqMode,
would you say the following code is equivalent?
Code:
db $85
db <biosIrqMode
db ?HandlerPrologue-$
If it is I'll stick that in a macro and use it instead of the native BBS0 opcode that is apparently broken.
_________________
Want to design a PCB for your project? I strongly recommend
KiCad. Its free, its multiplatform, and its easy to learn!
Also, I maintain KiCad libraries of
Retro Computing and
Arduino components you might find useful.