Code: Select all
.macro indirectJsr address
lda #>(*+12)
pha
lda #<(*+9)
pha
lda address+1
pha
lda address
pha
rts
.endmacroModerator: Moderators
Code: Select all
.macro indirectJsr address
lda #>(*+12)
pha
lda #<(*+9)
pha
lda address+1
pha
lda address
pha
rts
.endmacroCode: Select all
TableOfPlaces:
.dw DesiredAddressA - 1, DesiredAddressB - 1
LDY navigator
LDA TableOfPlaces + 1, Y
PHA
LDA TableOfPlaces, Y
PHA
RTS
Code: Select all
; bytes,cycles
; (my cycle count migiht be off. I'm doing this from memory
; and I'm rusty)
.macro indirectJsr address
lda #>(*+12) ; 2,2
pha ; 1,3
lda #<(*+9) ; 2,2
pha ; 1,3
lda address+1 ; 3,4
pha ; 1,3
lda address ; 3,4
pha ; 1,3
rts ; 1, 6
.endmacro
; total: 15 bytes
; 30 cycles
; AND your 'address' has to be -1 the actual address you want to jump to
; (ugh)
Code: Select all
; this is pseudo code
; my ca65 macros (or whatever) is rusty
.macro IndirectJSR address
jmp phoneylabel_jsr ; 3,3
phoneylabel_jmp:
jmp (address) ; 3,5
phoneylabel_jsr:
jsr phoneylabel_jmp ; 3,6
; total: 9 bytes
; 14 cycles
Code: Select all
lda address+1
pha
lda address
pha
rtsCode: Select all
jmp (address)Code: Select all
Address0 .dsb 2
Address1 .dsb 2
Address2 .dsb 2
Address3 .dsb 2
(...)
CallAddress0:
jmp (Address0)
CallAddress1:
jmp (Address1)
CallAddress2:
jmp (Address2)
CallAddress3:
jmp (Address3)Code: Select all
.macro indirectJsr address
jmp *+6
jmp (address)
jsr *-3
.endmacroCode: Select all
jmp :++
: jmp (address)
: jsr :--
I don't think it's necessarily crap, but it's also not such the big find that we sometimes make it to be. It is 1 cycle slower than the indirect JMP way if the JMP uses ZP to hold the address, but it is 1 cycle faster if the JMP doesn't use ZP. Also, there are cases when we don't want to create a new variable just for a certain purpose, and we'd rather use the stack instead. But I admit that there are few advantages, when any, in using the JSR trick instead of an indirect jump.Disch wrote:I never liked the "push your address then RTS it" crap. It always seemed absurd to me.
Code: Select all
....
jsr IndirectJSR
....
IndirectJSR:
jmp ($XXXX)
Disch's solution is a macro which is to be used "in place", so if you want to return to the correct location later you have to skip the indirect jump.Celius wrote:Except I'm not sure why there's a JMP to the JSR, which is after the JMP ($XXXX).
Which is the solution I presented. With 3 or 4 fake "address registers" I have never had to worry about this again.Why not just have one universal "IndirectJSR" routine that you use and never have to define again? I suppose if you're using different values for $XXXX, then yes, you'd want more than one routine
In this case, yes. Usually macros do need more space, but they are supposed to be faster, because there is no calling and returning, but in this particular case using macros is indeed a bit slower, so I really don't see a reason to use them in this case.It seems the macro makes things easier to program, but performance goes down a little, and it takes up more space, it seems
So you're writing the function pointer to a global variable in RAM. You almost hit on the one advantage of using the stack for jump table calls vs. a temporary location in allocated memory (zero page or BSS): you can use jump tables in both your main thread and your interrupt handler without them stepping on each other.tokumaru wrote:I have a few temp locations in ZP that I use as scratchpad memory [for] indirect jumps to some of the temp locations