boolean variables can now also be memory-mapped (including boolean arrays)

This commit is contained in:
Irmen de Jong 2024-12-11 18:08:26 +01:00
parent f8aaa2d13c
commit 3675d7961b
9 changed files with 29 additions and 22 deletions

View File

@ -238,7 +238,7 @@ class StMemVar(name: String,
StNode(name, StNodeType.MEMVAR, astNode) {
init{
require(!dt.isBool && !dt.isBoolArray)
require(!dt.isString)
if(dt.isStringly && !dt.isWord)
requireNotNull(length)
}

View File

@ -172,7 +172,7 @@ class PtConstant(name: String, override val type: DataType, val value: Double, p
class PtMemMapped(name: String, override val type: DataType, val address: UInt, val arraySize: UInt?, position: Position) : PtNamedNode(name, position), IPtVariable {
init {
require(!type.isBool && !type.isBoolArray)
require(!type.isString)
}
}

View File

@ -726,8 +726,8 @@ internal class AstChecker(private val program: Program,
if(decl.datatype.isLong && decl.type!=VarDeclType.CONST)
errors.err("cannot use long type for variables; only for constants", decl.position)
if(decl.type==VarDeclType.MEMORY) {
if (decl.datatype.isBool || decl.datatype.isBoolArray)
errors.err("variables mapped in memory should be numeric", decl.position)
if (decl.datatype.isString)
errors.err("strings cannot be memory-mapped", decl.position)
}
fun err(msg: String) = errors.err(msg, decl.position)

View File

@ -944,7 +944,7 @@ It's way too much to include here, you have to study the
`syslib source code <https://github.com/irmen/prog8/tree/master/compiler/res/prog8lib/cx16/syslib.p8>`_
to see what is there.
On the other targets, it only contains the definition of the 16 memory mapped virtual registers
On the other targets, it only contains the definition of the 16 memory-mapped virtual registers
(cx16.r0 - cx16.r15) and the following utility routines:
``save_virtual_registers()``

View File

@ -40,7 +40,7 @@ RAM, ROM, I/O
#. what part(s) of the address space is RAM? What parts of the RAM can be used by user programs?
#. what is the usual starting memory address of programs?
#. what part(s) of the address space is ROM?
#. what part(s) of the address space is memory mapped I/O registers?
#. what part(s) of the address space is memory-mapped I/O registers?
#. is there a block of "high ram" available (ram that is not the main ram used to load programs in) that could be used for variables?
#. is there a banking system? How does it work (how do you select Ram/Rom banks)? How is the default bank configuration set?
Note that prog8 itself has no notion of banking, but this knowledge may be required for proper system initialization.

View File

@ -948,7 +948,8 @@ address of: ``&``
Sometimes the compiler silently inserts this operator to make it easier for instance
to pass strings or arrays as subroutine call arguments.
This operator can also be used as a prefix to a variable's data type keyword to indicate that
it is a memory mapped variable (for instance: ``&ubyte screencolor = $d021``)
it is a memory-mapped variable (for instance: ``&ubyte screencolor = $d021``). This is explained
in the :ref:`variables` chapter.
ternary:
Prog8 doesn't have a ternary operator to choose one of two values (``x? y : z`` in many other languages)
@ -1055,8 +1056,8 @@ so pay attention to any jumps and rts instructions in the inlined code!
one or more parameters in those 'registers'. You can just list the arguments directly.
*This also works on the Commodore 64!* (however they are not as efficient there because they're not in zeropage)
In prog8 and assembly code these 'registers' are directly accessible too via
``cx16.r0`` .. ``cx16.r15`` (these are memory mapped uword values),
``cx16.r0s`` .. ``cx16.r15s`` (these are memory mapped word values),
``cx16.r0`` .. ``cx16.r15`` (these are memory-mapped uword values),
``cx16.r0s`` .. ``cx16.r15s`` (these are memory-mapped word values),
and ``L`` / ``H`` variants are also available to directly access the low and high bytes of these.
You can use them directly but their name isn't very descriptive, so it may be useful to define
an alias for them when using them regularly.

View File

@ -6,7 +6,7 @@ Prog8 targets the following hardware:
- 8 bit MOS 6502/65c02/6510 CPU
- 64 Kb addressable memory (RAM or ROM)
- optional use of memory mapped I/O registers
- optional use of memory-mapped I/O registers
- optional use of system ROM routines
Currently these machines can be selected as a compilation target (via the ``-target`` compiler argument):

View File

@ -16,7 +16,7 @@ There is *no dynamic memory allocation*. The storage size of all variables
is fixed and is determined at compile time.
Variable declarations tend to appear at the top of the code block that uses them, but this is not mandatory.
They define the name and type of the variable, and its initial value.
Prog8 supports a small list of data types, including special 'memory mapped' types
Prog8 supports a small list of data types, including special memory-mapped types
that don't allocate storage but instead point to a fixed location in the address space.
@ -466,8 +466,8 @@ Range expressions are most often used in for loops, but can be also be used to c
byte[] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
Special types: const and memory-mapped
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Constants
^^^^^^^^^
When using ``const``, the value of the 'variable' cannot be changed; it has become a compile-time constant value instead.
You'll have to specify the initial value expression. This value is then used
@ -478,24 +478,30 @@ Variables on the other hand can't be optimized as much, need memory, and more co
Note that a subset of the library routines in the ``math``, ``strings`` and ``floats`` modules are recognised in
compile time expressions. For example, the compiler knows what ``math.sin8u(12)`` is and replaces it with the computed result.
When using ``&`` (the address-of operator but now applied to a datatype), the variable will point to specific location in memory,
rather than being newly allocated. The initial value (mandatory) must be a valid
memory address. Reading the variable will read the given data type from the
address you specified, and setting the variable will directly modify that memory location(s)::
Memory-mapped
^^^^^^^^^^^^^
When using ``&`` (the address-of operator but now applied to the datatype in the variable's declaration),
the variable will be placed at a designated position in memory rather than being newly allocated somewhere.
The initial value in the declaration should be the valid memory address where the variable should be placed.
Reading the variable will then read its value from that address, and setting the variable will directly modify those memory location(s)::
const byte max_age = 2000 - 1974 ; max_age will be the constant value 26
&word SCREENCOLORS = $d020 ; a 16-bit word at the address $d020-$d021
If you need to use the variable's memory address instead of the value placed there, you can still use `&variable` as usual.
You can memory map all datatypes except strings.
.. _pointervars:
Direct access to memory locations ('peek' and 'poke')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Normally memory locations are accessed by a *memory mapped* name, such as ``cbm.BGCOL0`` that is defined
as the memory mapped address $d021 (on the c64 target).
Usually specific memory locations are accessed through a memory-mapped variable, such as ``cbm.BGCOL0`` that is defined
as the background color register at the memory address $d021 (on the c64 target).
If you want to access a memory location directly (by using the address itself or via an uword pointer variable),
without defining a memory mapped location, you can do so by enclosing the address in ``@(...)``::
If you want to access any memory location directly (by using the address itself or via an uword pointer variable),
without defining a memory-mapped location, you can do so by enclosing the address in ``@(...)``::
color = @($d020) ; set the variable 'color' to the current c64 screen border color ("peek(53280)")
@($d020) = 0 ; set the c64 screen border to black ("poke 53280,0")

View File

@ -166,7 +166,7 @@ class IRStMemVar(name: String,
}
init {
require(!dt.isBool && !dt.isBoolArray)
require(!dt.isString)
}
val typeString: String = dt.typeString(length)