JSR Indirect Address

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: JSR Indirect Address

Post 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.
dwight
Posts: 213
Joined: 08 Jun 2004

Re: JSR Indirect Address

Post 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
User avatar
8bit-Dude
Posts: 13
Joined: 03 Oct 2017

Re: JSR Indirect Address

Post 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
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: JSR Indirect Address

Post 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
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: JSR Indirect Address

Post by BigEd »

(Don't forget to adjust those addresses by 1!)
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: JSR Indirect Address

Post by Chromatix »

Or, having set up the address in RAM, just make indirectEntry be a simple JMP (target).
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: JSR Indirect Address

Post 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). :)
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: JSR Indirect Address

Post by BigEd »

Oh, I like that!
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: JSR Indirect Address

Post 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.)
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
kakemoms
Posts: 349
Joined: 02 Mar 2016

Re: JSR Indirect Address

Post 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.
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: JSR Indirect Address

Post 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.
kakemoms
Posts: 349
Joined: 02 Mar 2016

Re: JSR Indirect Address

Post 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
Post Reply