mirror of
https://github.com/irmen/prog8.git
synced 2025-04-15 08:39:19 +00:00
update docs about call convention for multi-value results (first is in A or AY, then R15...R0)
added sprites+coroutines+defer part to benchmark program
This commit is contained in:
parent
bc550a4549
commit
fb1e89d9ef
@ -12,7 +12,7 @@ circles {
|
||||
|
||||
sub draw(bool use_kernal, uword max_time) -> uword {
|
||||
if use_kernal
|
||||
void cx16.set_screen_mode(128)
|
||||
cx16.set_screen_mode(128)
|
||||
else
|
||||
gfx_lores.graphics_mode()
|
||||
|
||||
@ -33,7 +33,7 @@ circles {
|
||||
}
|
||||
|
||||
if use_kernal
|
||||
void cx16.set_screen_mode(3)
|
||||
cx16.set_screen_mode(3)
|
||||
else {
|
||||
gfx_lores.text_mode()
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
%import b_queens
|
||||
%import b_textelite
|
||||
%import b_maze
|
||||
%import b_sprites
|
||||
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
@ -29,7 +30,7 @@ main {
|
||||
sub start() {
|
||||
ubyte benchmark_number
|
||||
|
||||
void cx16.set_screen_mode(3)
|
||||
cx16.set_screen_mode(3)
|
||||
txt.color2(1, 6)
|
||||
txt.clear_screen()
|
||||
|
||||
@ -74,10 +75,14 @@ main {
|
||||
benchmark_score[benchmark_number] = textelite.bench(120)
|
||||
benchmark_number++
|
||||
|
||||
announce_benchmark("sprites-coroutines-defer")
|
||||
benchmark_score[benchmark_number] = animsprites.benchmark(300)
|
||||
benchmark_number++
|
||||
|
||||
benchmark_names[benchmark_number] = 0
|
||||
benchmark_score[benchmark_number] = 0
|
||||
|
||||
void cx16.set_screen_mode(3)
|
||||
cx16.set_screen_mode(3)
|
||||
txt.uppercase()
|
||||
txt.color2(1, 6)
|
||||
uword final_score
|
||||
@ -99,7 +104,7 @@ main {
|
||||
|
||||
sub announce_benchmark(str name) {
|
||||
benchmark_names[benchmark_number] = name
|
||||
void cx16.set_screen_mode(3)
|
||||
cx16.set_screen_mode(3)
|
||||
txt.uppercase()
|
||||
txt.color2(1, 6)
|
||||
txt.clear_screen()
|
||||
|
@ -635,7 +635,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
// return value(s)
|
||||
val returnRegSpecs = if(fcall.void) emptyList() else {
|
||||
// TODO: for current implemenation of the call convention in case of multiple return values,
|
||||
// a list of Ir virtual registers to hold the results is NOT correct (they're loaded into AY + R15..R0 instead!)
|
||||
// So we use an empty list to avoid confusion here. This may change in a future version.
|
||||
val returnRegSpecs = if(fcall.void || callTarget.returns.size>1) emptyList() else {
|
||||
callTarget.returns.map {
|
||||
val returnIrType = irType(it)
|
||||
FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.next(returnIrType), null)
|
||||
|
@ -33,6 +33,7 @@
|
||||
; - call killall() to kill all tasks.
|
||||
; - IMPORTANT: if you add the same subroutine multiple times, IT CANNOT DEPEND ON ANY LOCAL VARIABLES OR R0-R15 TO KEEP STATE. NOT EVEN REPEAT LOOP COUNTERS.
|
||||
; Those are all shared in the different tasks! You HAVE to use a mechanism around the userdata value (pointer?) to keep separate state elsewhere!
|
||||
; - IMPORTANT: ``defer`` cannot be used inside a coroutine that is reused for multiple tasks!!!
|
||||
|
||||
coroutines {
|
||||
%option ignore_unused
|
||||
|
@ -1170,9 +1170,9 @@ So for instance::
|
||||
|
||||
asmsub multisub() -> uword @AY, bool @Pc, ubyte @X { ... }
|
||||
|
||||
.. sidebar:: usage of cx16.r0-cx16.r15
|
||||
.. sidebar:: register usage
|
||||
|
||||
Subroutines with multiple return values use the "virtual registers" to return those.
|
||||
Subroutines with multiple return values use cpu registers A, Y, and the R0-R15 "virtual registers" to return those.
|
||||
Using those virtual registers during the calculation of the values in the return statement should be avoided.
|
||||
Otherwise you risk overwriting an earlier return value in the sequence.
|
||||
|
||||
|
@ -155,8 +155,9 @@ Regular subroutines
|
||||
|
||||
- for an ``asmsub`` or ``extsub`` the subroutine's signature specifies the output registers that contain the values explicitly,
|
||||
just as for a single return value.
|
||||
- for regular subroutines, the compiler will use the "virtual registers" cx16.r0-cx16.r15, from r15 down to r0, for the
|
||||
result values left to right. This may change in a future compiler version.
|
||||
- for regular subroutines, the compiler will return the first of the return values via the cpu register ``A``` (or ``A + Y``` if it's a word value),
|
||||
just like for subroutines that only return a single value.
|
||||
The remainder of the return values are returned via the "virtual registers" cx16.r16-cx16.r0 (using R15 first and counting down to R0).
|
||||
|
||||
|
||||
**Builtin functions can be different:**
|
||||
|
@ -1,10 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- IR: call main.two():r4.w,r5.w the registers mentioned after the call are wrong/unused in case of multi-value returns. Better to clear this to avoid confusion? (they ARE correct for single value returns!)
|
||||
|
||||
- update docs about call convention for multi-value results (first is in A or AY, then R15...R0)
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user