It's of course pretty simple to do it manually, but there is no guarantee that the choice made by the programmer will be optimal. What I personally typically do is that I have all my "straight" variables in ZP, and all arrays non-ZP. The only exception is array of pointers which can be more efficient if they're in ZP as I can use the ($xx,X) addressing mode but this is extremely rare.
One way to guarantee optimal allocation would be to do the following :
First note that the ZP-only instructions are :
Code: Select all
any instruction using ($xx,X) or ($xx),Y
STX $xx,Y
STY $xx,XCode: Select all
JMP ($xxxx)
ADC $xxxx,Y
AND $xxxx,Y
CMP $xxxx,Y
EOR $xxxx,Y
LDA $xxxx,Y
ORA $xxxx,Y
SBC $xxxx,Y
STA $xxxx,Y1) Variables declared by the user as "ZP" are always allocated to zero page. If any instruction using non-ZP only addressing is used, the instruction is used with the high byte of address set to $00
2) Variable declared by the user as "non-ZP" are never allocated to zero page. If any instruction using ZP only addressing is used with this variable, an assembling error is emmited.
3) Variables declared as automatic are automatically allocated.
On a fist pass, the assembler counts the size of the code it will emit without actually emitting anything. Every time an ambiguous instruction is used (for example "STA variable"), as the instruction takes 2 bytes if ZP and 3 if non-ZP, the difference between both possibilities is 1 byte, so 1 is added to an internal counter relative to the variable.
For the simpler version of the optimizer, if any ZP-only addressing is ever used with a automatic variable, it is immediately changed into a ZP variable, and the byte count for the non-ZP route is discarded.
The the total byte count is something like this :
#bytes = integer_constant + 3*variable_1 + 152*variable_2 + [...]
As long as there is room for variables in ZP, variables with the highest count are asigned to ZP, and once ZP is full, remaining variables are assigned to non-ZP.
Then, during a second pass, the assembler actually assemble the code, this time knowing exactly what is ZP and what is non-ZP without ambiguity.
Does any assembler does anything like this ?
The only problem I see is that this is not taking into account the branch overflow problem, as it's impossible to predict whenever a branch will overflow or not on the 1st pass.