From 32c1c1922494c9268aab6fc0bd3d6eaf91f8df40 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 20 Jan 2023 03:10:41 +0100 Subject: [PATCH] tweak sys.wait() routines on various targets add warning to docs about FP usage in IRQ --- compiler/res/prog8lib/c128/syslib.p8 | 33 +++++++++++++++++++++------- compiler/res/prog8lib/c64/syslib.p8 | 33 +++++++++++++++++++++------- compiler/res/prog8lib/cx16/syslib.p8 | 28 ++++++++++++++++------- compiler/test/TestCallgraph.kt | 2 +- docs/source/libraries.rst | 6 +++-- docs/source/targetsystem.rst | 8 +++++++ 6 files changed, 83 insertions(+), 27 deletions(-) diff --git a/compiler/res/prog8lib/c128/syslib.p8 b/compiler/res/prog8lib/c128/syslib.p8 index 33e947b8a..dea66ec72 100644 --- a/compiler/res/prog8lib/c128/syslib.p8 +++ b/compiler/res/prog8lib/c128/syslib.p8 @@ -561,15 +561,32 @@ sys { }} } - sub wait(uword jiffies) { - ; --- wait approximately the given number of jiffies (1/60th seconds) + asmsub wait(uword jiffies @AY) { + ; --- wait approximately the given number of jiffies (1/60th seconds) (N or N+1) ; note: the system irq handler has to be active for this to work as it depends on the system jiffy clock - repeat jiffies { - ubyte jiff = lsb(c64.RDTIM16()) - while jiff==lsb(c64.RDTIM16()) { - ; wait until 1 jiffy has passed - } - } + %asm {{ + stx P8ZP_SCRATCH_B1 + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + +_loop lda P8ZP_SCRATCH_W1 + ora P8ZP_SCRATCH_W1+1 + bne + + ldx P8ZP_SCRATCH_B1 + rts + ++ lda c64.TIME_LO + sta P8ZP_SCRATCH_B1 +- lda c64.TIME_LO + cmp P8ZP_SCRATCH_B1 + beq - + + lda P8ZP_SCRATCH_W1 + bne + + dec P8ZP_SCRATCH_W1+1 ++ dec P8ZP_SCRATCH_W1 + jmp _loop + }} } asmsub waitvsync() clobbers(A) { diff --git a/compiler/res/prog8lib/c64/syslib.p8 b/compiler/res/prog8lib/c64/syslib.p8 index 871a4a84b..f6b9ffcda 100644 --- a/compiler/res/prog8lib/c64/syslib.p8 +++ b/compiler/res/prog8lib/c64/syslib.p8 @@ -527,15 +527,32 @@ sys { }} } - sub wait(uword jiffies) { - ; --- wait approximately the given number of jiffies (1/60th seconds) + asmsub wait(uword jiffies @AY) { + ; --- wait approximately the given number of jiffies (1/60th seconds) (N or N+1) ; note: the system irq handler has to be active for this to work as it depends on the system jiffy clock - repeat jiffies { - ubyte jiff = lsb(c64.RDTIM16()) - while jiff==lsb(c64.RDTIM16()) { - ; wait until 1 jiffy has passed - } - } + %asm {{ + stx P8ZP_SCRATCH_B1 + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + +_loop lda P8ZP_SCRATCH_W1 + ora P8ZP_SCRATCH_W1+1 + bne + + ldx P8ZP_SCRATCH_B1 + rts + ++ lda c64.TIME_LO + sta P8ZP_SCRATCH_B1 +- lda c64.TIME_LO + cmp P8ZP_SCRATCH_B1 + beq - + + lda P8ZP_SCRATCH_W1 + bne + + dec P8ZP_SCRATCH_W1+1 ++ dec P8ZP_SCRATCH_W1 + jmp _loop + }} } asmsub waitvsync() clobbers(A) { diff --git a/compiler/res/prog8lib/cx16/syslib.p8 b/compiler/res/prog8lib/cx16/syslib.p8 index 45d165df2..e18ccabeb 100644 --- a/compiler/res/prog8lib/cx16/syslib.p8 +++ b/compiler/res/prog8lib/cx16/syslib.p8 @@ -908,17 +908,29 @@ sys { asmsub wait(uword jiffies @AY) { ; --- wait approximately the given number of jiffies (1/60th seconds) (N or N+1) - ; note: regular system vsync irq handler must be running, and no nother irqs + ; note: the system irq handler has to be active for this to work as it depends on the system jiffy clock %asm {{ -- wai ; wait for irq (assume it was vsync) - cmp #0 + phx + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + +_loop lda P8ZP_SCRATCH_W1 + ora P8ZP_SCRATCH_W1+1 bne + - dey -+ dec a - bne - - cpy #0 - bne - + plx rts + ++ jsr c64.RDTIM + sta P8ZP_SCRATCH_B1 +- jsr c64.RDTIM + cmp P8ZP_SCRATCH_B1 + beq - + + lda P8ZP_SCRATCH_W1 + bne + + dec P8ZP_SCRATCH_W1+1 ++ dec P8ZP_SCRATCH_W1 + bra _loop }} } diff --git a/compiler/test/TestCallgraph.kt b/compiler/test/TestCallgraph.kt index fd1275c6e..d6b949f6b 100644 --- a/compiler/test/TestCallgraph.kt +++ b/compiler/test/TestCallgraph.kt @@ -112,7 +112,7 @@ class TestCallgraph: FunSpec({ """ val result = compileText(C64Target(), false, sourcecode)!! val graph = CallGraph(result.program) - graph.allIdentifiers.size shouldBeGreaterThanOrEqual 9 + graph.allIdentifiers.size shouldBeGreaterThanOrEqual 5 val empties = graph.allIdentifiers.keys.filter { it.nameInSource==listOf("empty") } empties.size shouldBe 3 empties[0].position.line shouldBe 4 diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 026d9ede1..fd3d6ffcd 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -91,13 +91,15 @@ sys (part of syslib) ``wait(uword jiffies)`` wait approximately the given number of jiffies (1/60th seconds) - note: the system irq handler has to be active for this to work as it depends on the system jiffy clock + Note: the regular system irq handler has run for this to work as it depends on the system jiffy clock. + If this is is not possible (for instance because your program is running its own irq handler logic *and* no longer calls + the kernal's handler routine), you'll have to write your own wait routine instead. ``waitvsync()`` busy wait till the next vsync has occurred (approximately), without depending on custom irq handling. can be used to avoid screen flicker/tearing when updating screen contents. note: a more accurate way to wait for vsync is to set up a vsync irq handler instead. - note for cx16: the system irq handler has to be active for this to work (this is not required on c64) + note for cx16: the regular system irq handler has to run for this to work (this is not required on C64 and C128) ``waitrastborder()`` (c64/c128 targets only) busy wait till the raster position has reached the bottom screen border (approximately) diff --git a/docs/source/targetsystem.rst b/docs/source/targetsystem.rst index 448a1fae3..d4d3a9deb 100644 --- a/docs/source/targetsystem.rst +++ b/docs/source/targetsystem.rst @@ -165,3 +165,11 @@ The Commander X16 provides two additional routines that should be used *in your ; ... do your work that uses vera here... cx16.pop_vera_context() +.. caution:: + It is advised to not use floating point calculations inside IRQ handler routines. + Beside them being very slow, there are intricate requirements such as having the + correct ROM bank enabled to be able to successfully call them (and making sure the correct + ROM bank is reset at the end of the handler), and the possibility + of corrupting variables and floating point calculations that are being executed + in the interrupted main program. These memory locations should be backed up + and restored at the end of the handler, further increasing its execution time...