[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