Rotate bits when you don't care about carry.

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Rotate bits when you don't care about carry.

Post by cbmeeks »

Once I load a value into the accumulator, I want to then rotate it either left or right one bit.

The issue is that "9th bit" of the carry is causing more code that I want. For example:

Code: Select all

                clc
                lda $c000
                ror
                bcs !carry_set+
            !carry_clear:
                jmp !+
            !carry_set:
                clc
                adc #$80
            !:
                sta $c000
This is just pseudo code that I *THINK* may work. But is it the most efficient?
Bottom line, I only want to rotate the 8 bits of an address left/right and don't care about the carry. But, obviously, I have to deal with it somehow.

Would it be more efficient to use a SHIFT but then check to see if I need to set the MSB or LSB? Not sure on that one.

Advice would be appreciated. :-)

Thanks!
Cat; the other white meat.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Rotate bits when you don't care about carry.

Post by BigEd »

How about:

Code: Select all

                lda $c000
                clc
                ror
                bcc !+
                eor #$80
            !:
                sta $c000
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Rotate bits when you don't care about carry.

Post by Arlet »

Code: Select all

lda $c000
lsr
bcc carry_clear
adc #$7f
carry_clear:
sta $c000
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Rotate bits when you don't care about carry.

Post by BigEd »

oh, of course, lsr!
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Rotate bits when you don't care about carry.

Post by Arlet »

How about

Code: Select all

lda $c000
lsr
ror $c000
hoglet
Posts: 367
Joined: 29 Jun 2014

Re: Rotate bits when you don't care about carry.

Post by hoglet »

Rotating left:

Code: Select all

LDA $C000
ASL A
ADC #$00
STA $C000
Rotating right:

Code: Select all

LDA $C000
LSR A
BCC !+
ORA #$80
!:
STA $C000
Dave
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Rotate bits when you don't care about carry.

Post by BigEd »

Oh, Arlet might have it! So long as we're OK reading the source twice.
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: Rotate bits when you don't care about carry.

Post by cbmeeks »

You guys rock! I knew I came to the right place. :-)

Thanks! I will give those a shot.
Cat; the other white meat.
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: Rotate bits when you don't care about carry.

Post by cbmeeks »

Arlet wrote:
How about

Code: Select all

lda $c000
lsr
ror $c000

Wait, I'm curious on how this one works.
Wouldn't the ROR be separate than the LDA/LSR?
Cat; the other white meat.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Rotate bits when you don't care about carry.

Post by Arlet »

The final ROR $C000 would be all that you need if the 6502 had an 8-bit rotate without the carry flag.

Since it does rotate through the carry flag, we just need to make sure that the carry is preset correctly with the least significant bit. That's what the LDA/LSR do. (You could also do LDA/ROR, which would look more pleasing)
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: Rotate bits when you don't care about carry.

Post by cbmeeks »

Arlet wrote:
The final ROR $C000 would be all that you need if the 6502 had an 8-bit rotate without the carry flag.

Since it does rotate through the carry flag, we just need to make sure that the carry is preset correctly with the least significant bit. That's what the LDA/LSR do. (You could also do LDA/ROR, which would look more pleasing)
Ah, OK. So, to rotate left, I assume the following would work:

Code: Select all

lda $c000
asl
rol $c000
Cat; the other white meat.
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Rotate bits when you don't care about carry.

Post by floobydust »

There's always many ways to twiddle bits with the 6502... if you just wanted to make a (sub)routine that would rotate a value in accumulator, you could use this:

Code: Select all

   PHA    ;Save value
   LSR A  ;Shift bit to carry
   PLA    ;Get original value back
   ROR A  ;Rotate it
   RTS    ;Return to caller
If you didn't care about clobbering an Index register, you could xfer the A reg before the shift, then xfer it back before the rotate. It would save some clock cycles from using the stack.
User avatar
Arlet
Posts: 2353
Joined: 16 Nov 2010
Location: Gouda, The Netherlands
Contact:

Re: Rotate bits when you don't care about carry.

Post by Arlet »

Yes. And if you wanted to rotate two bits, you could do:

Code: Select all

lda $c000
ror
ror $c000
ror
ror $c000
Note that you could make it a few cycles faster if you can put the data in zeropage.
User avatar
cbmeeks
Posts: 1254
Joined: 17 Aug 2005
Location: Soddy-Daisy, TN USA
Contact:

Re: Rotate bits when you don't care about carry.

Post by cbmeeks »

OK, so I ran the rotate code in a loop and noticed some strange numbers.

So, your code worked great...but it showed a flaw in my design! lol

Here are the numbers I got:

Code: Select all

        $48 01001000
        $24 00100100
        $12 00010010
        $09 00001001
        $84 10000100
        $42 01000010
        $21 00100001
        $90 10010000
Well, that's technically correct. But what I missed what that I actually need to rotate within the two NYBBLE's.

Totally my fault! I didn't "see" the issue until the code ran.

So, why do I need this? Well, I'm using one byte to represent a sprite. The byte contains the direction it is pointing along with the direction it's moving.

Like this:

Code: Select all

Facing  Moving
NESW    NESW
1000    0100
Which means the sprite is facing north and moving east.

So, when I rotate right, I need the upper nybble to not spill into the lower nybble.

I'll keep digging at this but any pointers are greatly appreciated (AGAIN).

Thanks!
Cat; the other white meat.
User avatar
floobydust
Posts: 1394
Joined: 05 Mar 2013

Re: Rotate bits when you don't care about carry.

Post by floobydust »

Well, that's not quite the same thing :?

I would take a different approach. As there's only 16 bit combinations to a nibble, you can simply use a 16-byte lookup table with the rotated values. You can mask off the upper 4-bits (to retain the lower 4 bits), xfer to an index register and load the accumulator indexed from the lookup table.

For the upper nibble, you would need to do 4 LSR A instructions and again xfer it to an index register. To save time, you could use a different 16-byte table where the rotated values are in the upper 4 bits. Once you have both values, you just OR them together for the twin-shifted nibbles.
Post Reply