diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt index 53b02b4fe..2cf709df9 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/VariableAllocator.kt @@ -48,9 +48,9 @@ internal class VariableAllocator(private val symboltable: SymbolTable, val numberOfAllocatableVariables = allVariables.size val varsRequiringZp = allVariables.filter { it.zpwish == ZeropageWish.REQUIRE_ZEROPAGE } val varsPreferringZp = allVariables.filter { it.zpwish == ZeropageWish.PREFER_ZEROPAGE } + val varsNotZp = allVariables.filter { it.zpwish == ZeropageWish.NOT_IN_ZEROPAGE } val varsDontCare = allVariables.filter { it.zpwish == ZeropageWish.DONTCARE } - val numberOfExplicitNonZpVariables = allVariables.count { it.zpwish == ZeropageWish.NOT_IN_ZEROPAGE } - require(varsDontCare.size + varsRequiringZp.size + varsPreferringZp.size + numberOfExplicitNonZpVariables == numberOfAllocatableVariables) + require(varsDontCare.size + varsRequiringZp.size + varsPreferringZp.size + varsNotZp.size == numberOfAllocatableVariables) var numVariablesAllocatedInZP = 0 var numberOfNonIntegerVariables = 0 @@ -86,7 +86,7 @@ internal class VariableAllocator(private val symboltable: SymbolTable, // no need to check for allocation error, if there is one, just allocate in normal system ram. } - // try to allocate any other interger variables into the zeropage until it is full. + // try to allocate the "don't care" interger variables into the zeropage until it is full. // TODO some form of intelligent priorization? most often used variables first? loopcounter vars first? ...? if(errors.noErrors()) { val sortedList = varsDontCare.sortedByDescending { it.scopedName } @@ -110,9 +110,7 @@ internal class VariableAllocator(private val symboltable: SymbolTable, } } -// println(" number of allocated vars: $numberOfAllocatableVariables") -// println(" put into zeropage: $numVariablesAllocatedInZP, non-zp allocatable: ${numberOfNonIntegerVariables+numberOfExplicitNonZpVariables}") -// println(" zeropage free space: ${zeropage.free.size} bytes") + // note: no zeropage allocation is done at all for the @nozp variables. This means they will always end up outside the zeropage. } private fun collectAllVariables(st: SymbolTable): Collection { diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt index 4c1da62cc..28e1ededd 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt @@ -674,6 +674,7 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl val zp = when { options.ZEROPAGEREQUIRE().isNotEmpty() -> ZeropageWish.REQUIRE_ZEROPAGE options.ZEROPAGE().isNotEmpty() -> ZeropageWish.PREFER_ZEROPAGE + options.ZEROPAGENOT().isNotEmpty() -> ZeropageWish.NOT_IN_ZEROPAGE else -> ZeropageWish.DONTCARE } val identifiers = identifier() diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 02e3f07c8..1f274bb0f 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -211,7 +211,7 @@ it will try to fill it with as much other variables as possible (before they wil Use ``@requirezp`` tag to *force* the variable into zeropage, but if there is no more free space the compilation will fail. It's possible to put strings, arrays and floats into zeropage too, however because Zp space is really scarce this is not advised as they will eat up the available space very quickly. It's best to only put byte or word -variables in zeropage. +variables in zeropage. By the way, there is also ``@nozp`` to keep a variable *out of the zeropage* at all times. Example:: diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index 63cfc747b..67a8429a0 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -342,6 +342,7 @@ Tag Effect ========== ====== @zp prioritize the variable for putting it into Zero page. No guarantees; if ZP is full the variable will be placed in another memory location. @requirezp force the variable into Zero page. If ZP is full, compilation will fail. +@nozp force the variable to normal system ram, never place it into zeropage. @shared means the variable is shared with some assembly code and that it cannot be optimized away if not used elsewhere. @split (only valid on (u)word arrays) Makes the array to be placed in memory as 2 separate byte arrays; one with the LSBs one with the MSBs of the word values. May improve performance. ========== ====== @@ -367,6 +368,7 @@ Various examples:: word @zp zpword = 9999 ; prioritize this when selecting vars for zeropage storage uword @requirezp zpaddr = $3000 ; we require this variable in zeropage word @shared asmvar ; variable is used in assembly code but not elsewhere + byte @nozp memvar ; variable that is never in zeropage Data types diff --git a/examples/test.p8 b/examples/test.p8 index 2b320ed56..2d739a1a6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,14 +2,14 @@ main { sub start() { - bool @split bb - ubyte @split bt - byte[200] @split ba - float @split fl - float[10] @split fla + ubyte @requirezp b1 + ubyte @zp b2 + ubyte b3 + ubyte @nozp b4 - bb=true - bt++ - fl++ + b1++ + b2++ + b3++ + b4++ } } diff --git a/parser/antlr/Prog8ANTLR.g4 b/parser/antlr/Prog8ANTLR.g4 index fee9e0060..d73362d42 100644 --- a/parser/antlr/Prog8ANTLR.g4 +++ b/parser/antlr/Prog8ANTLR.g4 @@ -57,6 +57,8 @@ ZEROPAGE : '@zp' ; ZEROPAGEREQUIRE : '@requirezp' ; +ZEROPAGENOT: '@nozp' ; + SHARED : '@shared' ; SPLIT: '@split' ; @@ -139,7 +141,7 @@ directivearg : stringliteral | identifier | integerliteral ; vardecl: datatype (arrayindex | ARRAYSIG)? decloptions identifier (',' identifier)* ; -decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | SPLIT)* ; +decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | ZEROPAGENOT | SPLIT)* ; varinitializer : vardecl '=' expression ; diff --git a/syntax-files/IDEA/Prog8.xml b/syntax-files/IDEA/Prog8.xml index 75d88784b..08b3079b9 100644 --- a/syntax-files/IDEA/Prog8.xml +++ b/syntax-files/IDEA/Prog8.xml @@ -13,7 +13,7 @@ - + diff --git a/syntax-files/NotepadPlusPlus/Prog8.xml b/syntax-files/NotepadPlusPlus/Prog8.xml index bc98d0acd..b9f188042 100644 --- a/syntax-files/NotepadPlusPlus/Prog8.xml +++ b/syntax-files/NotepadPlusPlus/Prog8.xml @@ -24,7 +24,7 @@ - void const str byte ubyte bool word uword float zp shared split requirezp + void const str byte ubyte bool word uword float zp shared split requirezp nozp %address %asm %ir %asmbinary %asminclude %breakpoint %encoding %import %launcher %option %output %zeropage %zpreserved %zpallowed inline sub asmsub romsub clobbers asm if when else if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z for in step do while repeat unroll break continue return goto abs all any call callfar clamp cmp divmod len lsb lsl lsr memory mkword min max msb peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex reverse rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sort sqrtw swap diff --git a/syntax-files/Vim/prog8.vim b/syntax-files/Vim/prog8.vim index 66c6bb9fa..f8947e80a 100644 --- a/syntax-files/Vim/prog8.vim +++ b/syntax-files/Vim/prog8.vim @@ -43,7 +43,7 @@ syn region prog8ArrayType matchgroup=prog8Type \ start="\<\%(u\?byte\|u\?word\|float\|str\|bool\)\[" end="\]" \ transparent syn keyword prog8StorageClass const -syn match prog8StorageClass "\(^\|\s\)\(@zp\|@shared\|@split\|@requirezp\)\>" +syn match prog8StorageClass "\(^\|\s\)\(@zp\|@shared\|@split\|@nozp\|@requirezp\)\>" syn region prog8Block start="{" end="}" transparent syn region prog8Expression start="(" end=")" transparent