I try use the opportunity now to give a quick overview of how 65816 programming is supported currently for those interested. It's a bit late but as I've spent 3+ hours to write this I don't wanted to throw it away now.
64tass compiles the usual 65816 opcodes with their addressing modes. By default ambiguous addressing modes are resolved through numeric ranges.
There's a 256 byte direct page range and if the address falls within then direct page addressing is used with the offset within that range. This can be set by .dpage and by default it's 0. That's why addresses <256 are normally direct page.
Similar a data bank can be defined for data bank addresses which is changeable by the .databank directive. It's 0 by default so addresses <65536 will use data bank addressing. The assembler of course knows which opcodes use bank 0 or program bank addressing and those are not subject to this range.
Anything else uses long addressing if available.
This is good enough for simple use cases but not if direct page or data bank gets moved around a lot.
That's usually when the not too pretty @b, @w and @l style address size forcing comes up. Yes it can be used to force 16 or 24 bit addressing to get data bank or long addressing but then it's used as a work-around against the address range detection.
On the other hand the address ranges can be disabled and then there won't be any automatic direct page (with .dpage ?) or data bank (with .databank ?) addressing modes generated. Without the range check these addressing modes must be explicitly written out to get them as follows:
Code:
lda 4,d ; for direct page
lda 12,b ; for data bank
Which is non-standard but more consistent than the address size forcing. For completeness there's also 0,k for the program bank. Of course these addressing modes are available even if the ranges are still in use.
As one does not want to repeat them normally (unlike the index registers) it's better to write them into constant definitions:
Code:
tmp = 0,d
tmp2 = 2,d
lda tmp,x ; for lda 0,d,x
sta tmp2 ; for lda 2,d
Or define regular labels with them:
Code:
.virtual 6,d ; accepted for *= or .logical/.here as well
tmp .word ?
tmp2 .word ?
.endv
The above constructs works with stack addressing similarly which can simplify stack variable referencing:
Code:
lda (tmp),y ; for lda (6,s),y
The other challenge is managing the immediate addressing mode's constant size.
There's nothing innovative here, the accu/index sizes are selected with directives (.al, .xl, .as, .xs) or through rep/sep constant tracking if enabled (.autsiz).
Alternatively if one does not want to bother with the directives the address size forcing may be used where it's needed:
Code:
lda @w#0 ; 16 bit immediate
The >64KiB address space is supported but of course an appropriately large output format must be used for that. Banks are crossed in the image file while the program counter remains in the current program bank.
That's all I can think of which may be relevant for 65816 programming with 64tass.
[edited]
Of course I forgot a few things, like what to do about the ,d and ,b register bases in the addresses when direct offsets are needed for indexed addressing. I'll add it here as the end of thread is too far away. I've added code blocks above as well were needed.
Code:
tmp = 7,d
lda tmp ; direct access is nothing special. But for an indexed one
ldx #tmp-(0,d) ; subtract the "base" (it's 0,d here) to get the offset
lda 0,d,x ; as the CPU will add the direct page base back here
If this subtraction would get repetitive for a table of direct page offsets then lists/tuples help:
Code:
.byte (adr1, adr2, adr3, adr4, adr5)-(0,d) ; subtracts 0,d from each of them
The 0,d had to be in parentheses because of operator precedence rules.
The same offset calculation is needed if the .dpage range was set to something else than zero just with a plain number.
65816 code can be in another program bank than zero and then jump address tables may need ".addr" instead of ".word". If an address gets larger than 16 bits .word will complain about it while .addr stores the last 16 bits and fails only if an address points to a different program bank.
There are no special directives yet for tables of 16 bit data bank or 8 bit direct page addresses which would strip ,b and ,d and take into account the current .databank and .dpage settings like .addr for program addresses. No one asked for them and it can be done by using other directives (.byte/.word) combined with base subtraction, as above.