mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 08:29:25 +00:00
callfar() now accepts a variable as address, so it can be used to indirect JSR to a subroutine whose address is not fixed. ('goto' already could indirect JMP to a variable address.)
This commit is contained in:
parent
4bc65e9ef7
commit
f690f58bd4
@ -139,20 +139,19 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
throw AssemblyError("callfar only works on cx16 target at this time")
|
||||
|
||||
val bank = fcall.args[0].constValue(program)?.number?.toInt()
|
||||
val address = fcall.args[1].constValue(program)?.number?.toInt()
|
||||
if(bank==null || address==null)
|
||||
throw AssemblyError("callfar (jsrfar) requires constant arguments")
|
||||
|
||||
if(address !in 0xa000..0xbfff)
|
||||
throw AssemblyError("callfar done on address outside of cx16 banked ram")
|
||||
if(bank==0)
|
||||
throw AssemblyError("callfar done on bank 0 which is reserved for the kernal")
|
||||
|
||||
val address = fcall.args[1].constValue(program)?.number?.toInt() ?: 0
|
||||
val argAddrArg = fcall.args[2]
|
||||
if(bank==null)
|
||||
throw AssemblyError("callfar (jsrfar) bank has to be a constant")
|
||||
if(fcall.args[1].constValue(program) == null) {
|
||||
assignAsmGen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.AY, false)
|
||||
asmgen.out(" sta (+)+0 | sty (+)+1 ; store jsrfar address word")
|
||||
}
|
||||
|
||||
if(argAddrArg.constValue(program)?.number == 0.0) {
|
||||
asmgen.out("""
|
||||
jsr cx16.jsrfar
|
||||
.word ${address.toHex()}
|
||||
+ .word ${address.toHex()}
|
||||
.byte ${bank.toHex()}""")
|
||||
} else {
|
||||
when(argAddrArg) {
|
||||
@ -162,7 +161,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
asmgen.out("""
|
||||
lda ${asmgen.asmVariableName(argAddrArg.identifier)}
|
||||
jsr cx16.jsrfar
|
||||
.word ${address.toHex()}
|
||||
+ .word ${address.toHex()}
|
||||
.byte ${bank.toHex()}
|
||||
sta ${asmgen.asmVariableName(argAddrArg.identifier)}""")
|
||||
}
|
||||
@ -170,7 +169,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
asmgen.out("""
|
||||
lda ${argAddrArg.number.toHex()}
|
||||
jsr cx16.jsrfar
|
||||
.word ${address.toHex()}
|
||||
+ .word ${address.toHex()}
|
||||
.byte ${bank.toHex()}
|
||||
sta ${argAddrArg.number.toHex()}""")
|
||||
}
|
||||
|
@ -899,14 +899,17 @@ memory(name, size, alignment)
|
||||
|
||||
callfar(bank, address, argumentaddress) ; NOTE: specific to cx16 target for now
|
||||
Calls an assembly routine in another ram-bank on the CommanderX16 (using the ``jsrfar`` routine)
|
||||
The banked RAM is located in the address range $A000-$BFFF (8 kilobyte).
|
||||
Notice that bank $00 is used by the Kernal and should not be used by user code.
|
||||
The banked RAM is located in the address range $A000-$BFFF (8 kilobyte), but you can specify
|
||||
any address in system ram (why this can be useful is explained at the end of this paragraph)
|
||||
The third argument can be used to designate the memory address
|
||||
of an argument for the routine; it will be loaded into the A register and will
|
||||
receive the result value returned by the routine in the A register. If you leave this at zero,
|
||||
no argument passing will be done.
|
||||
If the routine requires different arguments or return values, ``callfar`` cannot be used
|
||||
and you'll have to set up a call to ``jsrfar`` yourself to process this.
|
||||
Note: the address can be a variable or other expression, which allows you to use ``callfar`` with bank 0 to do an indirect JSR to a subroutine
|
||||
whose address can vary (jump table, etc. ``goto`` can do an indirect JMP to a variable address): ``callfar(0, &routine, &argument)``
|
||||
This is not very efficient though, so maybe you should write a small piece of inline assembly for this instead.
|
||||
|
||||
callrom(bank, address, argumentaddress) ; NOTE: specific to cx16 target for now
|
||||
Calls an assembly routine in another rom-bank on the CommanderX16
|
||||
|
@ -753,14 +753,14 @@ You can still ``break`` out of such a loop if you want though.
|
||||
Conditional Execution and Jumps
|
||||
-------------------------------
|
||||
|
||||
Unconditional jump
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Unconditional jump: goto
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To jump to another part of the program, you use a ``goto`` statement with an addres or the name
|
||||
of a label or subroutine::
|
||||
|
||||
goto $c000 ; address
|
||||
goto name ; label or subroutine
|
||||
goto $c000 ; address
|
||||
goto name ; label or subroutine
|
||||
|
||||
uword address = $4000
|
||||
goto address ; jump via address variable
|
||||
@ -770,6 +770,8 @@ to another piece of code that eventually returns).
|
||||
|
||||
If you jump to an address variable (uword), it is doing an 'indirect' jump: the jump will be done
|
||||
to the address that's currently in the variable.
|
||||
Note: to do an indirect *JSR* to a routine with a varying address, you can use the ``callfar`` builtin function
|
||||
(which is not very efficient) or you have to write a small piece of inline assembly.
|
||||
|
||||
|
||||
Conditional execution
|
||||
|
@ -1,12 +1,15 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
byte tx = 1
|
||||
uword @shared zzzz= $2000 + (tx as ubyte)
|
||||
txt.print_uwhex(zzzz,true)
|
||||
ubyte derp=2
|
||||
callfar(0, &func, 0)
|
||||
continue:
|
||||
txt.print("main again.")
|
||||
}
|
||||
|
||||
sub func() {
|
||||
txt.print("func.")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user