I wrote this as an article to Dragon Update (the newsletter of the National Dragon User's Group) and it got published in the February 1994 issue. It documents the effects of executing certain op-codes in the 6809 that are marked in the data sheet as 'illegal'.
Whilst looking through your 'Inside The Dragon', you may have come across the bit under TFR/EXG where it says "...all other combinations are undefined and invalid..." Fair enough, looks like a reasonable restriction... WELL IT ISN'T! It's a plot by Motorola to force you to pay attention to what they say! You CAN use other combinations (or at least you can on mine), and the functionality is as follows:
When transferring from register M to register N, as many bits are filled from bit 0 in N as can be obtained from M, and the rest (if any) are filled with 1s. So, transferring A to B transfers the 8 bits of A into the lower bits of B, and that's it ... nothing left to fill with 1s.
BUT, transferring B into Y, for example, would take the 8 bits of B and shove them into the lower 8 bits of Y, and since it has run out of B, would fill the upper 8 bits of Y with 1s. Transferring X into A would mean A equals the lower 8 bits of X.
Good, eh? Useful? No? Well, what about when you're using X as a screen pointer, and need to know how far along you are? Usually you might
PSHS A TFR X,D ANDB $1F
and B would then be the amount of character positions across the screen you were. You then, of course, need to PULS A again (assuming B is a scratch var, so doesn't need value stored). But, using illegal transfers, all you have to do is
TFR X,B ANDB $1F
There is, of course, one slight snag, and that is that Dream will chuck out any transfers where the registers are of unequal size, so to get round that you have to include a line saying something like
FDB $1F19 ; TFR X,B
which directly includes the code for TFR ($1F) and the parameter X,B (X=1, B=9). Look at your data sheet for register values.
For an EXG, you would just use $1E instead of $1F ... EXG operation follows the same guidelines as TFR.
Another useful hint is that an undefined register value (say 7) is treated as a register of 0 bits, i.e. FDB $1F72 (tranfer reg 7 into Y) would act the same as LDY #$FFFF, but in one less byte. The disadvantage is that the transfer takes two more clock cycles, so is slower - decide which trade-off you want for the application you have in mind.
Also, I think that executing $3E (undefined in data sheet) calls the reset vector ($FFFE/F) in a similar way that SWI ($3F) invokes the SWI vector ($FFFA/B). Can't really think of any uses for this except if you needed to automatically reset the machine to install something.