mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
document the @R0 - @R15 register support for normal subroutine parameters
This commit is contained in:
parent
f603c543d3
commit
58f696d00a
@ -987,6 +987,27 @@ Subroutines can be defined in a Block, but also nested inside another subroutine
|
|||||||
There are three different types of subroutines: regular subroutines (the one above), assembly-only, and
|
There are three different types of subroutines: regular subroutines (the one above), assembly-only, and
|
||||||
external subroutines. These last two are described in detail below.
|
external subroutines. These last two are described in detail below.
|
||||||
|
|
||||||
|
Reusing *virtual registers* R0-R15 for parameters
|
||||||
|
*************************************************
|
||||||
|
.. sidebar::
|
||||||
|
🦶🔫 Footgun warning
|
||||||
|
|
||||||
|
when using this the program can clobber the contents of R0-R15 when doing other operations that also
|
||||||
|
use these registers, or when calling other routines because Prog8 doesn't have a callstack.
|
||||||
|
Be very aware of what you are doing, the compiler can't guarantee correct values by itself anymore.
|
||||||
|
|
||||||
|
Normally, every subroutine parameter will get its own local variable in the subroutine where the argument value
|
||||||
|
will be stored when the subroutine is called. In certain situations, this may lead to many variables being allocated.
|
||||||
|
You *can* instruct the compiler to not allocate a new variable, but instead to reuse one of the *virtual registers* R0-R15
|
||||||
|
(accessible in the code as ``cx16.r0`` - ``cx16.r15``) for the parameter. This is done by adding a ``@Rx`` tag
|
||||||
|
to the parameter. This can only be done for byte and word types.
|
||||||
|
Note: the R0-R15 *virtual registers* are described in more detail below for the Assembly subroutines.
|
||||||
|
Here's an example that reuses the R0 and the R1L (lower byte of R1) virtual registers for the paremeters::
|
||||||
|
|
||||||
|
sub get_indexed_byte(uword pointer @R0, ubyte index @R1) -> ubyte {
|
||||||
|
return @(cx16.r0 + cx16.r1L)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Assembly-Subroutines
|
Assembly-Subroutines
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -157,7 +157,10 @@ some builtin functions are special and won't exactly follow these rules.
|
|||||||
**Some arguments will be passed in registers:**
|
**Some arguments will be passed in registers:**
|
||||||
For single byte and word arguments, the values are simply loaded in cpu registers by the caller before calling the subroutine.
|
For single byte and word arguments, the values are simply loaded in cpu registers by the caller before calling the subroutine.
|
||||||
*The subroutine itself will take care of putting the values into the parameter variables.* This saves on code size because
|
*The subroutine itself will take care of putting the values into the parameter variables.* This saves on code size because
|
||||||
otherwise all callers would have to store the values in those variables themselves. The rules for this are as follows:
|
otherwise all callers would have to store the values in those variables themselves.
|
||||||
|
Note that his convention is also still used for subroutines that specify parameters to be put into
|
||||||
|
one of the *virtual registers* R0-R15, as those are in the end just variables too.
|
||||||
|
The rules are as follows:
|
||||||
|
|
||||||
Single byte parameter: ``sub foo(ubyte bar) { ... }``
|
Single byte parameter: ``sub foo(ubyte bar) { ... }``
|
||||||
gets bar in the accumulator A, *subroutine* stores it into parameter variable
|
gets bar in the accumulator A, *subroutine* stores it into parameter variable
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
document the @R0 - @R15 register support for normal subroutine parameters (🦶🔫 Footgun warning!)
|
|
||||||
|
|
||||||
make a compiler switch to disable footgun warnings
|
make a compiler switch to disable footgun warnings
|
||||||
|
|
||||||
what to do with bankof(): keep it? add another syntax like \`value or ^value to get the bank byte?
|
what to do with bankof(): keep it? add another syntax like \`value or ^value to get the bank byte?
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
|
%import textio
|
||||||
|
%option no_sysinit
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
}
|
@($2005) = 0
|
||||||
}
|
txt.print_ub(get_indexed_byte($2000, 5))
|
||||||
|
txt.nl()
|
||||||
xyz {
|
@($2005) = 123
|
||||||
uword buffer_ptr = memory("buffers_stack", 8192, 0)
|
txt.print_ub(get_indexed_byte($2000, 5))
|
||||||
|
txt.nl()
|
||||||
sub pop() -> ubyte {
|
|
||||||
return buffer_ptr[2]
|
}
|
||||||
|
|
||||||
|
sub get_indexed_byte(uword pointer @R0, ubyte index @R1) -> ubyte {
|
||||||
|
return @(cx16.r0 + cx16.r1L)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user