mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 01:49:22 +00:00
documented the romsub bank additions
This commit is contained in:
parent
0fc9aa6b2d
commit
cb47e2c149
@ -72,6 +72,7 @@ What does Prog8 provide?
|
||||
- inline assembly allows you to have full control when every cycle or byte matters
|
||||
- supports the sixteen 'virtual' 16-bit registers R0 - R15 from the Commander X16 (also available on other targets)
|
||||
- encode strings and characters into petscii or screencodes or even other encodings
|
||||
- Automatic ROM/RAM bank switching on certain compiler targets when calling routines in other banks
|
||||
|
||||
*Rapid edit-compile-run-debug cycle:*
|
||||
|
||||
|
@ -104,6 +104,7 @@ Features
|
||||
- Easy and highly efficient integration with external subroutines and ROM routines on the target systems.
|
||||
- Strings can contain escaped characters but also many symbols directly if they have a PETSCII equivalent, such as "♠♥♣♦π▚●○╳". Characters like ^, _, \\, {, } and | are also accepted and converted to the closest PETSCII equivalents.
|
||||
- Encode strings and characters into petscii or screencodes or even other encodings, as desired (C64/Cx16)
|
||||
- Automatic ROM/RAM bank switching on certain compiler targets when calling routines in other banks
|
||||
- Identifiers can contain Unicode Letters, so ``knäckebröd``, ``приблизительно``, ``見せしめ`` and ``π`` are all valid identifiers.
|
||||
- Advanced code optimizations to make the resulting program smaller and faster
|
||||
- Programs can be restarted after exiting (i.e. run them multiple times without having to reload everything), due to automatic variable (re)initializations.
|
||||
|
@ -805,7 +805,8 @@ Subroutines are parts of the code that can be repeatedly invoked using a subrout
|
||||
Their definition, using the ``sub`` statement, includes the specification of the required parameters and return value.
|
||||
Subroutines can be defined in a Block, but also nested inside another subroutine. Everything is scoped accordingly.
|
||||
With ``asmsub`` you can define a low-level subroutine that is implemented directly in assembly and takes parameters
|
||||
directly in registers.
|
||||
directly in registers. Finally with ``romsub`` you can define an external subroutine that's implemented outside
|
||||
of the program (for instance, a ROM routine, or a routine in a library loaded elsewhere in RAM).
|
||||
|
||||
Trivial ``asmsub`` routines can be tagged as ``inline`` to tell the compiler to copy their code
|
||||
in-place to the locations where the subroutine is called, rather than inserting an actual call and return to the
|
||||
|
@ -781,10 +781,10 @@ The parameters is a (possibly empty) comma separated list of "<datatype> <parame
|
||||
The return type has to be specified if the subroutine returns a value.
|
||||
|
||||
|
||||
Assembly / ROM subroutines
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
External subroutines
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
External subroutines implemented in ROM are usually defined by compiler library files, with the following syntax::
|
||||
External subroutines are usually defined by compiler library files, with the following syntax::
|
||||
|
||||
romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) clobbers()
|
||||
-> bool @Pc, ubyte @ A, ubyte @ X, ubyte @ Y
|
||||
@ -793,9 +793,14 @@ This defines the ``LOAD`` subroutine at memory address $FFD5, taking arguments i
|
||||
and returning stuff in several registers as well. The ``clobbers`` clause is used to signify to the compiler
|
||||
what CPU registers are clobbered by the call instead of being unchanged or returning a meaningful result value.
|
||||
|
||||
**Banks:** it is possible to declare a non-standard ROM or RAM bank that the routine is living in, with ``@rombank`` or ``@rambank`` like this:
|
||||
``romsub @rombank 10 $C09F = audio_init()`` to define a routine at $C09F in ROM bank 10.
|
||||
See :ref:`banking` for more information.
|
||||
|
||||
.. note::
|
||||
Unlike what it's name may suggest, ``romsub`` can also define an external subroutine elsewhere in normal RAM.
|
||||
It's just that you explicitly define the memory address where it is located and it doesn't matter if that is in ROM or in RAM.
|
||||
``romsub`` is most often used to define ROM subroutines. But contrary to what the name may suggest,
|
||||
it can also define an external subroutine elsewhere in normal RAM. It simply states the address
|
||||
and signature of the subroutine; it doesn't care if the routine is in ROM or RAM address space.
|
||||
|
||||
User-written subroutines in the program source code itself, implemented purely in assembly and which have an assembly calling convention (i.e.
|
||||
the parameters are strictly passed via cpu registers), are defined with ``asmsub`` like this::
|
||||
|
@ -25,6 +25,44 @@ It is possible to relocate the BSS section using a compiler option
|
||||
so that more system ram is available for the program code itself.
|
||||
|
||||
|
||||
.. _banking:
|
||||
|
||||
ROM/RAM bank selection
|
||||
----------------------
|
||||
|
||||
On certain systems prog8 provides support for managing the ROM or RAM banks that are active.
|
||||
For example, on the Commander X16, you can use ``cx16.getrombank()`` to get the active ROM bank,
|
||||
and ``cx16.rombank(10)`` to make rom bank 10 active. Likewise, ``cx16.getrambank()`` to get the active RAM bank,
|
||||
and ``cx16.rambank(10)`` to make ram bank 10 active. This is explicit manual banking control.
|
||||
|
||||
However, Prog8 also provides something more sophisticated than this, when dealing with banked subroutines:
|
||||
|
||||
External subroutines defined with ``romsub`` can have a non-standard ROM or RAM bank specified as well.
|
||||
The compiler will then transparently change a call to this routine so that the correct bank is activated
|
||||
automatically before the normal jump to the subroutine (and switched back on return). The programmer doesn't
|
||||
have to bother anymore with setting/resetting the banks manually, or having the program crash because
|
||||
the routine is called in the wrong bank! You define such a routine by adding ``@rombank <bank>`` or ``@rambank <bank>``
|
||||
to the romsub subroutine definition. This specifies the bank number where the subroutine is located in::
|
||||
|
||||
romsub @rombank 10 $C09F = audio_init()
|
||||
|
||||
When you then call this routine in your program as usual, the compiler will no longer generate a simple JSR instruction to the
|
||||
routine. Instead it will generate a piece of code that automatically switches the ROM or RAM bank to the
|
||||
correct value, does the call, and switches the bank back. The exact code will be different for different
|
||||
compilation targets, and not all targets even have banking or support this. As an example,
|
||||
on the Commander X16, prog8 will use the JSRFAR kernal routine for this. On the Commodore 128, a similar call exists.
|
||||
Other compilation targets don't have banking or prog8 doesn't yet support automatic bank selection on them.
|
||||
|
||||
Notice that the symbol for this routine in the assembly source code will still be defined as usual.
|
||||
The bank number is not translated into assembly (only as a comment)::
|
||||
|
||||
p8s_audio_init = $c09f ; @rombank 10
|
||||
|
||||
.. caution::
|
||||
Calls with automatic bank switching like this are not safe to use from IRQ handlers. Don't use them there.
|
||||
Instead change banks in a controlled manual way (or not at all).
|
||||
|
||||
|
||||
.. _symbol-prefixing:
|
||||
|
||||
Symbol prefixing in generated Assembly code
|
||||
|
@ -1,14 +1,17 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
add docs for @rombank @rambank on romsubs. Add promo in docs that prog8 does automatic bank switching when calling such a romsub (on cx16 and c128)
|
||||
consolidate @rombank and @rambank into just @bank
|
||||
|
||||
rename 'romsub' to 'extsub' ?
|
||||
add example for cx16 that compiles and loads libraries in different ram banks and calls romsub from rom and ram banks automatically
|
||||
|
||||
for releasenotes: gfx2.width and gfx2.height got renamed as gfx_lores.WIDTH/HEIGHT or gfx_hires4.WIDTH/HEIGTH constants. Screen mode routines also renamed.
|
||||
|
||||
regenerate symbol dump files
|
||||
add support for banked romsubs on the C64 as well (banks basic/kernal rom in/out)
|
||||
|
||||
rename 'romsub' to 'extsub' ? keep romsub as alias?
|
||||
|
||||
regenerate symbol dump files
|
||||
|
||||
Improve register load order in subroutine call args assignments:
|
||||
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
|
||||
|
@ -3,27 +3,11 @@
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
romsub @rombank 10 $C09F = audio_init()
|
||||
romsub @rambank 22 $A000 = hiram_routine()
|
||||
|
||||
sub start() {
|
||||
block1.sub1()
|
||||
block1.sub2()
|
||||
audio_init()
|
||||
hiram_routine()
|
||||
}
|
||||
}
|
||||
|
||||
block1 {
|
||||
%option merge
|
||||
|
||||
sub sub1() {
|
||||
txt.print("sub1")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
block1 {
|
||||
%option merge
|
||||
|
||||
sub sub2() {
|
||||
txt.print("sub2")
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user