Quote:
The thing I'm not sure about here is that we need 16-bit bytes. So every opcode is 16 bits, and operands are 16 or 32 bits. Now, you might think you can just output pairs of bytes. But the PC counts in 16-bit bytes, so you'd need to take into account that branching back by 6 (16-bit) bytes is only a distance of 6, not 12.
Also, branch distances are now 16-bit signed quantities, so ideally an assembler can cope with distances much greater than 128. A very simple macro-based approach might only allow distances of 64, depending on how the byte-counting was tackled.
My first impression is that the main thing to understand is exactly how the program counter works on your processor.
You said the equivalent of "LDA #$00" works out to "00A90000". Suppose those 32 bits are stored at location zero ($00000000). After that is the program counter value two ($00000002) or four ($00000004)?
Relative branches are easy to work out with macros. The equivalent of a standard 6502 "BEQ" instruction might be:
.macro BEQ, ?target
.byte $F0, *-(?target)+1
.endm
Giving that a 16-bit range would be:
.macro BEQ, ?target
.word $00F0, *-(?target)+2
.endm
At least when dealing with 8-bit bytes. This also works if the program counter value I asked about above is four, rather than two. If the value is two, I'd have to think about it some more.
Mmm, if the value is two, doesn't that mean you have only 2^31 addressable locations, rather than 2^32, even with a 32-bit address bus?
--------
After thinking about it a bit longer, suppose we have this source:
here BEQ here
and are using the 16-bit relative branch above.
Should the assembled code be "00F0 FFFC" (BEQ -4)? If so, no changes necessary. If instead it should be "00F0 FFFE" (BEQ -2), then we can do this, I think:
.macro BEQ, ?target
.word $00F0, (*-(?target)+2)/2
.endm