Page 1 of 2
Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 6:42 pm
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!
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 6:59 pm
by BigEd
How about:
Code: Select all
lda $c000
clc
ror
bcc !+
eor #$80
!:
sta $c000
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:01 pm
by Arlet
Code: Select all
lda $c000
lsr
bcc carry_clear
adc #$7f
carry_clear:
sta $c000
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:04 pm
by BigEd
oh, of course, lsr!
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:05 pm
by Arlet
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:06 pm
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
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:10 pm
by BigEd
Oh, Arlet might have it! So long as we're OK reading the source twice.
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:25 pm
by cbmeeks
You guys rock! I knew I came to the right place.
Thanks! I will give those a shot.
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:33 pm
by cbmeeks
Wait, I'm curious on how this one works.
Wouldn't the ROR be separate than the LDA/LSR?
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:37 pm
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)
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:46 pm
by cbmeeks
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:
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:48 pm
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.
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 7:50 pm
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.
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 8:46 pm
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:
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!
Re: Rotate bits when you don't care about carry.
Posted: Tue Nov 10, 2020 9:13 pm
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.