Page 3 of 3

Re: JSR Indirect Address

Posted: Wed Aug 16, 2017 8:05 am
by BigEd
How much an ISR should do is of course application dependent. If the application is real time control, and if the response time is very tight relative to the clock speed, then every instruction is going to have to count. But this is not the only situation!

In Acorn's MOS, IRQ is relatively pedestrian - for good engineering reasons it indirects through RAM. On the other hand, NMI is absolutely minimal, because it is used solely for interacting with the floppy controller, which is very much a real time subsystem.

Re: JSR Indirect Address

Posted: Wed Aug 16, 2017 2:59 pm
by dwight
Rules are made to be broken. There is always the exception.
As for copying a frame buffer, this is where hardware should
replace program. A DMA transfer would have been the right
way, in general.
It sounds as though there wasn't much else to do anyway.
It is just that over the years I've seen cases where too much processing
was done in the interrupts.
I saw one that they read an A/D, offset the value ( dangerous to do without care )
and multiplied by a ratio. All in the interrupt.
If there are more than one critical operation to handle, one needs to look
carefully at how it will handle multiple events. This is hard to do while locked
in an interrupt.
Dwight

Re: JSR Indirect Address

Posted: Sat Dec 15, 2018 2:43 pm
by 8bit-Dude
Not sure if it is helpful, but to change JSR addresses I just edit the address bytes.
This is an example used to dynamically specify the JSR address of a SID file...

Code: Select all

playMusic:
		; set address 
		sta initSID+1
		stx initSID+2
initSID:
		; init code (Dummy address)
		jsr $0000

Re: JSR Indirect Address

Posted: Sat Dec 15, 2018 3:19 pm
by Chromatix
That's a valid technique if you can tolerate self-modifying code. It disqualifies that code from running from ROM. A more universal technique, which is one byte shorter but slightly slower:

Code: Select all

    JSR indirectEntry
    ; Returns to here
[...]
indirectEntry:
    PHX    ; push subroutine address on stack
    PHA
    RTS    ; indirect jump

Re: JSR Indirect Address

Posted: Sat Dec 15, 2018 3:25 pm
by BigEd
(Don't forget to adjust those addresses by 1!)

Re: JSR Indirect Address

Posted: Sat Dec 15, 2018 3:28 pm
by Chromatix
Or, having set up the address in RAM, just make indirectEntry be a simple JMP (target).

Re: JSR Indirect Address

Posted: Sat Dec 15, 2018 4:22 pm
by Dr Jefyll
BigEd wrote:
(Don't forget to adjust those addresses by 1!)
Right.

Or, if you find adjusting the address to be inconvenient -- and you have a byte to spare -- use PHP RTI to conclude the sequence (instead of RTS). :)

Re: JSR Indirect Address

Posted: Sat Dec 15, 2018 4:24 pm
by BigEd
Oh, I like that!

Re: JSR Indirect Address

Posted: Sat Dec 15, 2018 4:51 pm
by Dr Jefyll
Happy to entertain you. :) Here's a related trick which could in some cases be an attractive way of returning altered flags to a bios caller, without relying on stack gymnastics. In this thread (whose context is 65816), ...
I wrote:
Let's say a bios routine needs to return a yes-no message, either "a" or "b," to the caller. For message "a" the routine exits using RTI, and a one-byte instruction located right after the BRK in the calling code will get executed. But for message "b" the bios routine would exit using PLP followed by RTL [RTS, for 6502], which results in the one-byte instruction following the BRK getting skipped. So, for example, by using CLC or SEC as the conditionally-executed instruction after the BRK you can cause the "message" to end up in the carry flag! :D (Carry would have to be in a known state beforehand.)

Re: JSR Indirect Address

Posted: Sun Dec 23, 2018 6:43 pm
by kakemoms
Hmm. I have used this subroutine in the past to get indirect JSR:

Code: Select all

*=$2000

defm ijsr ; addr
        jsr injsr
        jmp (/1)
endm

injsr
        pla
        tax
        pla
        tay
        txa
        clc
        adc #3  ; check overflow
        tya
        adc #0  ; add msb
        pha
        txa
        adc #3  ; add lsb
        pha     ;jmp return address
        tya
        pha
        txa
        pha     ;restore return address
        rts

*=$2100
        ijsr $2200
        rts

*=$2200
        byte 0,$30

*=$3000
        lda #5  ; do something
        rts     ; return
Its slow, but the macro reuses the code, so it only requires 6 bytes per indirect JSR after the first one.

Re: JSR Indirect Address

Posted: Sun Dec 23, 2018 6:53 pm
by Chromatix
It looks like you're duplicating and modifying a copy of the return address on the stack, using NMOS instructions only (CMOS has direct PLX/Y). That *will* be slow, especially compared to the six bytes *total* required for a JSR to a simple indirect-jump trampoline.

Re: JSR Indirect Address

Posted: Mon Dec 24, 2018 3:36 am
by kakemoms
Yes I use a 6502, but it works on a 65C02 as well. Its fairly easy to get 65c02-only code:

Code: Select all

injsr
        plx
        ply
        txa
        clc
        adc #3  ; check overflow
        tya
        adc #0  ; add msb
        pha
        txa
        adc #3  ; add lsb
        pha     ;jmp return address
        phy
        phx     ;restore return address
        rts
Slightly faster...

If you simply want a fast method, just use the direct modification of the JSR instruction:

Code: Select all

defm ijsr ; addr
        lda /1
        sta @jta+1
        lda /1+1
        sta @jta+2
@jta    jsr $ffff
endm