Page 1 of 1

Flipping a Byte

Posted: Sat Feb 13, 2021 6:23 pm
by chysn
Is this the best-possible subroutine for flipping a single byte? By "flip" I mean that ABCDEFGH becomes HGFEDCBA and by "best" I mean the smallest-possible code:

Code: Select all

; Flip A and return flipped value in A
Flip:   sta ZP
        ldx #$08
-loop:  lsr ZP
        rol a
        dex
        bne loop
        rts

Re: Flipping a Byte

Posted: Sun Feb 14, 2021 2:53 am
by tlr
How about:

Code: Select all

; Flip A and return flipped value in A
Flip:   sta ZP
        lda #$01
-loop:  lsr ZP
        rol a
        bcc loop
        rts
This is 1 byte shorter, 16 cycles faster, and doesn't touch the X-register.

Re: Flipping a Byte

Posted: Sun Feb 14, 2021 6:14 am
by chysn
tlr wrote: Sun Feb 14, 2021 2:53 am This is 1 byte shorter, 16 cycles faster, and doesn't touch the X-register.
That’s awesome, thank you!

And this technique, which is new for me, goes beyond this project; it can be used to constrain accumulator operations for lots of things.

Re: Flipping a Byte

Posted: Sun Feb 14, 2021 7:26 am
by groepaz
Wasnt there a compo with this theme a while ago.... on F64 perhaps? mmmmh

Re: Flipping a Byte

Posted: Sun Feb 14, 2021 7:56 am
by tlr
chysn wrote: Sun Feb 14, 2021 6:14 am
tlr wrote: Sun Feb 14, 2021 2:53 am This is 1 byte shorter, 16 cycles faster, and doesn't touch the X-register.
That’s awesome, thank you!

And this technique, which is new for me, goes beyond this project; it can be used to constrain accumulator operations for lots of things.
There's also a variant of this:

Code: Select all

; Flip A and return flipped value in A
Flip:   sec
        rol a
-loop:  ror ZP
        asl a
        bne loop
        lda ZP
        rts
This is two cycles slower than the previous version but leaves the result in ZP so the lda can be omitted in cases it would be stored there anyway.

Re: Flipping a Byte

Posted: Sun Feb 14, 2021 10:33 am
by chysn
tlr wrote: Sun Feb 14, 2021 7:56 am This is two cycles slower than the previous version but leaves the result in ZP so the lda can be omitted in cases it would be stored there anyway.
In my game, It's likely that I will work in-place, probably via ROR absolute,X. Basically, the idea is to make a contiguous set of ten custom characters (80 bytes) turn the other direction. This construction lets me use X as a byte index instead of a bit count.
groepaz wrote: Sun Feb 14, 2021 7:26 am Wasnt there a compo with this theme a while ago.... on F64 perhaps? mmmmh
It would be an interesting read. I did a Google search before posting my code, and didn't find anything smaller than mine. And right now, I can't imagine anything being smaller than @tlr's.

Re: Flipping a Byte

Posted: Sun Feb 14, 2021 7:43 pm
by malcontent
Not exactly the same thing, but has some similar requirements but flipping an 8x8 bit matrix along the diagonal is discussed here: http://forum.6502.org/viewtopic.php?f=2&t=6412

Re: Flipping a Byte

Posted: Mon Feb 15, 2021 2:24 am
by Mike
If flipping a byte formed a time-critical part of preparing a display, I'd still be willing to throw a 256 byte table against it. ;)
chysn wrote:And this technique, which is new for me, goes beyond this project; it can be used to constrain accumulator operations for lots of things.
This 'guard bit' technique is also used in the BASIC interpreter while multiplying two float mantissas, see the loop $DA5E..$DA89.

Re: Flipping a Byte

Posted: Mon Feb 15, 2021 12:32 pm
by chysn
Mike wrote: Mon Feb 15, 2021 2:24 am If flipping a byte formed a time-critical part of preparing a display, I'd still be willing to throw a 256 byte table against it. ;)
I see what you mean. The operation I have in mind will take .0168 seconds, which would be rough in some cases. For my project, the switch is happening between half-innings in a baseball game. It's the part of the game where the spectators get up to use the restroom and get a beer. I'll probably even have to add another second of artificial delay. If it was time-critical, I'd probably just store my flipped characters in memory.
Mike wrote: Mon Feb 15, 2021 2:24 am
chysn wrote:And this technique, which is new for me, goes beyond this project; it can be used to constrain accumulator operations for lots of things.
This 'guard bit' technique is also used in the BASIC interpreter while multiplying two float mantissas, see the loop $DA5E..$DA89.
I admire the usage here because it's totally organic. The iterator and the result are one value, and it's very elegant. I don't really understand this usage in the BASIC interpreter. It's storing the iterator accumulator in Y while the accumulator is used for other stuff, and then from Y back to accumulator to do the shift and the carry check. In other words, I don't understand why it's

Code: Select all

lda #$80
-loop tay
;yada yada
tya
lsr
bne loop
versus just regular old

Code: Select all

ldy #$08
-loop ;yada yada
dey
bne loop
Edit: Well, yeah, I get it on closer examination. Carry is checked first and the accumulator isn't always thrown out like I originally thought it was.