[Coco] 6502 to 6809 translation
William Astle
lost at l-w.ca
Mon Aug 1 14:40:38 EDT 2011
On 11-08-01 05:02 AM, Phill Harvey-Smith wrote:
> Hi All,
>
> I'm currently trying to translate some 6502 code to run on the
> Dragon/CoCo, all is prety easy except for one thing, the 6809 doesn't
> appear to have one of the 6502 indexed modes namely :
>
> asume that data_addr contains $8000
> and y=$20
>
> lda (data_addr),y
>
>
> which will IIRC take look in data_addr, find $8000 and load a from
> $800+$20 = $8020.
>
> the 6809 has
> lda (data_addr,y)
>
> but this will load a from where data_addr+$20 points to, which is not
> the same thing !
>
> So is there an easy way of translating the 6502 code in a couple of 6809
> instructions ?
I was going to stay out of this discussion since I don't know the 6502
very well, but here goes.
First note: the indirect addressing modes use square brackets ([ and ])
in standard 6809 notation. Parentheses mean nothing special to the 6809
assembler.
I think the biggest confusion with this translation is because the 6502
does not have 16 bit index registers even though it has a 16 bit address
space. This means that 6502 code has to do use some "interesting"
gimmicks to access the whole address space.
There are a couple of possibilities for translation, depending on
whether the value at data_addr is a constant or is expected to change at
runtime. Also, if the value in Y is a constant or not affects things,
too. That gives four possibilities. Below assumes the same values as in
your question.
1. value at data_addr is constant, Y is constant:
lda $8020
2. Y is constant, data_addr is not
ldu data_addr
lda $20,u
Note: this uses U because LDU is faster than LDY, and one byte shorter.
3. data_addr is constant, Y is not
lda $8000,y
Note: this is a 4 byte instruction and is horribly inefficient in most
contexts. It is worth reworking an entire code sequence to avoid this
type of operation in many cases. (This is a 16 bit constant offset from Y.)
4. neither is constant
ldd data_addr
lda d,y
Note: only D can be used for a 16 bit register offset from an index
register.
Given that the 6809 has 16 bit index registers, you will end up with
much better code by swapping the usage of registers so that the 16 bit
value ends up in Y. Even better, use X or U instead of Y. Then, if your
8 bit value is in the range of $00 through $7F, you can use either A or
B for the offset from the index register:
Assume offset ($20) is in B and base address ($8000) is in X:
lda b,x
This will not work if the offset is "negative" (bit 7 set) because the
"b,x" and "a,x" addressing modes treat the accumulator value as a signed
offset. So if B has $80 in it instead of $20, the above instruction
would read the address $7F80 ($8000-$80).
I'll close with a comment that it is very likely that completely
rewriting the code instead of doing a direct translation will result in
cleaner, faster, and more compact code on the 6809.
More information about the Coco
mailing list