mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +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
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -157,7 +157,10 @@ some builtin functions are special and won't exactly follow these rules.
|
||||
**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.
|
||||
*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) { ... }``
|
||||
gets bar in the accumulator A, *subroutine* stores it into parameter variable
|
||||
|
@ -1,8 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
document the @R0 - @R15 register support for normal subroutine parameters (🦶🔫 Footgun warning!)
|
||||
|
||||
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?
|
||||
|
@ -1,12 +1,19 @@
|
||||
%import textio
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
}
|
||||
}
|
||||
|
||||
xyz {
|
||||
uword buffer_ptr = memory("buffers_stack", 8192, 0)
|
||||
|
||||
sub pop() -> ubyte {
|
||||
return buffer_ptr[2]
|
||||
@($2005) = 0
|
||||
txt.print_ub(get_indexed_byte($2000, 5))
|
||||
txt.nl()
|
||||
@($2005) = 123
|
||||
txt.print_ub(get_indexed_byte($2000, 5))
|
||||
txt.nl()
|
||||
|
||||
}
|
||||
|
||||
sub get_indexed_byte(uword pointer @R0, ubyte index @R1) -> ubyte {
|
||||
return @(cx16.r0 + cx16.r1L)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user