Register size-independent 65816 code

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
blargg
Posts: 42
Joined: 30 Dec 2003
Contact:

Register size-independent 65816 code

Post by blargg »

On the Wiki it is suggested to make code register size-independent by avoiding immediate values and instead referencing them by address. This way if the register is 8 bits, it uses the first byte only, without changing the interpretation of the instructions.

Code: Select all

and #$0F ; no, requires that size of accumulator be known

and mask ; works whether accumulator is 8 or 16 bits
...
mask: .word $0F ; that is, .byte $0F,$00
The following seems simpler: tell the assembler that A is 8 bits, then manually add a NOP after any instruction which uses immediate mode. This way, if 8 really is 8 bits, an extra NOP will be encountered, otherwise, the high byte of the immediate value will be $EA. Some code might need a zero for the high byte, but in most cases since it can only assume the low 8 bits of A are valid anyway, the junk in the upper byte wouldn't be a problem; in those cases that it does matter, the above technique might work best.

Code: Select all

.a8 ; tell assembler to use 8-bit immediate values for accumulator
and #$0F
nop

; What the 65816 sees when in 16-bit accumulator mode:
and #$EA0F
The same should apply to X and Y as well, though size-independent use of them would be less common.

EDIT: it might be better to code for the 16-bit case, so the $EA upper byte is obvious:

Code: Select all

.a16
and #$EA0F
User avatar
dclxvi
Posts: 362
Joined: 11 Mar 2004

Post by dclxvi »

I like it! It's smaller and faster. I've added it to the wiki as an optimization to look for. In my original example, the CMP high byte must be zero, and as a result so must the AND high byte, but under the reasonable assumption the OUTCHAR will ignore the high byte, the ADC and EOR can use NOP. Since it illustrates both cases, it turned out to be a good example...by accident, but hey, dumb luck is better than no luck at all. :)
Quote:
it might be better to code for the 16-bit case, so the $EA upper byte is obvious
Yeah, you could make case for either notation. You can check the wiki and see what I chose to do.
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Post by kc5tja »

When the registers are in 16-bit wide mode, note that carry and overflow occur on bits 15 and 14, not 7 and 6 like in 8-bit mode. Thus, register width-independent code cannot depend on these flags.
Post Reply