## Saturday, September 15, 2018

### Rotating and shifting bits Left

The 6502 rotation operations assume a byte’s highest bit is leftmost and lowest bit is rightmost. The ASL command shifts the bits to the left. Shifting simply moves what value was in the highest bit into the carry flag, then moves the bits to the right by 1 and places a 0 in the lowest bit. In other words, 10101010 becomes 01010101 with a carry of 1.
Related to the ASL command is the ROL command which rotates the bits to the left. Rotating is the same as shifting with the exception that the value in the carry flag is shifted into the high bit. This effectively means that if you rotate a byte 9 times (8 bits plus 1 carry bit) you will end up with the number that you started with. The following diagram illustrates both of these instructions

This is all fascinating, but why would you ever want to do this? The two most common reasons is to reposition bits if you have bit-packed values and for multiplying.

As mentioned earlier, due to low amount of memory early machines had, every bit counts. Lets say you wanted a playing card to be represented in a byte. You may have a bit to representing if the card was revealed, 4 bits to hold the face value, and 2 bits to hold the suit. This would give us a packed byte in the format 0RFFFFSS. Here is how you would pack the 3 bytes into a single byte.

LDA cardShowing
ASL
ASL
ASL
ASL
ORA cardFace
ASL
ASL
ORA cardSuit

The 6502 does not have any multiplication or division instructions so those operations need to be done manually. This is where rotation really comes in handy. Shifting left is the equivalent to multiplying by 2. Shifting twice is the same as multiplying by 4, and so on for the powers of 2. Combining the shifting multiplications with additions lets you multiply by any value. For instance, multiplying by 10 can be done by multiplying by 8 then adding to that value the original value multiplied by 2.

Multi-byte shifting or multiplication is done as follows:
LDA lowByte
ASL
STA lowByte
LDA highByte
ROL
STA highByte

The idea here is that the ASL puts the high bit into the carry flag and the ROL uses the carry from the previous byte.

ROLROtate Left by one bit
 Address Mode Decimal OPCode Hexadecimal OpCode Size Cycles Accumulator 42 \$2A 1 2 Zero Page 38 \$26 2 5 Zero Page,X 54 \$36 2 6 Absolute 46 \$2E 3 6 Absolute,X 62 \$3E 3 7
Flags affected: CNZ
Usage: Rotates bits left using the carry bit to fill in the missing bit and putting the sign bit into the carry flag. Used primarily for multi-byte multiplication by powers of 2 and reading serial data though can be used to reposition bits.
Test Code:
; ROL accumulator
CLC
LDA #128
ROL A
BRK
; expect A=0, Z=1, C=1, N=0

; ROL with memory
LDX #1
ROL 254
ROL 254,X
ROL 256
ROL 256,X
BRK
.ORG 254
.BYTE 128 127 \$77 \$77
;expect MFE=0 MFF=255 M100=\$EE M101=\$EE N=1, Z=0, C=0

Implementation:
// Accumulator
state.acc = performLeftBitShift(state.acc, true)
// Zero Page
// Zero Page, X
// Absolute
// Absolute, X

ASLArithmetic Shift Left by one bit
 Address Mode Decimal OPCode Hexadecimal OpCode Size Cycles Accumulator 10 \$0A 1 2 Zero Page 6 \$06 2 5 Zero Page,X 22 \$16 2 6 Absolute 14 \$0E 3 6 Absolute,X 30 \$1E 3 7
Flags affected: CNZ
Usage: Rotates bits left using the carry bit to fill in the missing bit and putting the sign bit into the carry flag. Used primarily for single byte multiplication by powers of 2 and reading serial data though can be used to reposition bits.
Test Code:
; ASL accumulator
LDA #128
SEC
ASL A
BRK
; expect A=0, Z=1, C=1, N=0

; ASL with memory
LDX #1
ASL 254
ASL 254,X
ASL 256
ASL 256,X
BRK
.ORG 254
.BYTE 128 127 \$F7 \$77
;expect MFE=0 MFF=254 M100=\$EE M101=\$EE N=1, Z=0, C=0

Implementation:
// Accumulator
state.acc = performLeftBitShift(state.acc, false)
// Zero Page
// Zero Page, X