Examples of Using Bitwise Instructions

Andreas Moshovos, Jan 2024

Here we discuss several example uses of the bitwise and shift instructions. We will present these as C functions first and then we will be discussing their implementation in NIOS II assembly.

Extracting a single bit from an input value

unsigned int

bit_read(unsigned int a, unsigned int index)

{

      unsigned int mask = (1<< index);

      if (a & mask) return 1;

      return 0;

}

 

This function returns the bit at position “index” from the input value “a”. The bits are numbered, left to right 0 to 31. An equivalent code in assembly is. Recall r4 is a and r5 is index and the return value goes into r2:

bit_read:

      movi r2, 1        # r2 = 1 // use r2 as temporary

      sll r5, r2, r5    # mask = r5 = (1 << index)

      and r2, r5, r4    # r2 = only the bit at index position from a

      cmpne r2, r2, r0  # convert that to 0 or 1

      ret

 

The shift instruction moves the 1 at the index position. Then the and instruction zeroes out all other bits from the input value in r4 except the one that is at the index position. The result in r2 is has 0s at all bit positions except at the index position. The bit at the index position can be 0 or 1 and its value is what a had at the same bit position. Here we take advantage of the fact that (a AND 1) = a. This is called “masking” we are masking out all other bits except the bit in position index.  ANDing with a value that has 1s at some positions allows us to “extract” only those bits from the input. E.g., ANDing with 0xF allows us to “keep” only the last 4 bits of the input. We will use this often when communicating with devices.

Setting a single bit of an input value to either 0 or 1

unsigned int

bit_write(unsigned int a, unsigned index, unsigned int value)

{

unsigned int mask = (1 << index);

 

a = a & (~mask); // zero out just the bit at index

mask = ((value & 1) << index); // the lower bit of value, is what we

                               // want the bit at index to be

                              // shift that into position (index)

a = a | mask;                 // OR it with the existing value

                              // recall we kept all bits as they were

                              // and zeroed out just the bit at index

return a;

}

 

The code is as follows:

bit_write:

      movi r2, -2       # r2 = 0xFFFFFFFE, zero at bit #0 all others are 1

      rol r2, r2, r5    # Place 0 at bit #index all others are 1

      and r4, r5, r4    # Zero out the bit #index of the input in r4

      andi r6, r6, 1    # extract bit #0 from value what we want the bit

                        # #index to be

      sll r2, r6, r5    # shift that to position index

      or r2, r2,  r4    # or it with the input value (which had bit #index

                        # zeroed out)

      ret

 

Toggling a bit

unsigned int

bit_toggle(unsigned int a, unsigned int index)

{

return a ^ (1 << index);

}

The code is as follows:

bit_toggle:

      movi r2, 1       

      sll r2, r2, r5    # r2 = (1 << index)

      xor r2, r2, r4    # r2 = a ^ (1 << index)

      ret

 

Setting a bit to 1

unsigned int

bit_set(unsigned int a, unsigned int index)

{

return a | (1 << index);

}

 

Translates to:

bit_toggle:

      movi r2, 1       

      sll r2, r2, r5    # r2 = (1 << index)

      or r2, r2, r4     # r2 = a | (1 << index)

      ret

 

Setting a bit to 0

unsigned int

bit_clear(unsigned int a, unsigned int index)

{

return a & ~(1 << index);

}

 

Translates to:

bit_write:

      movi r2, -2       # r2 = 0xFFFFFFFE, zero at bit #0 all others are 1

      rol r2, r2, r5    # Place 0 at bit #index all others are 1

      and r2, r2, r4    # Zero out the bit #index of the input in r4

      ret

 

Find the leading 1 bit: Position where there is the leftmost bit that is 1

unsigned int

bit_leadone(unsigned int a)

{

int t = (1 << 31);

int i = 31;

 

if (a == 0) return 32;

 

while ((a & t) == 0) {

t = t >> 1;

i--;

}

return i;

}

The code is as follows:

bit_leadone:

      movi r2, 32

      blt r4, r0, done # input is 0, return 32, no leading 1

      movi r2, 31

 

      movhi r5, 0x8000 # r5 = t = (1<<31)

loop: and r6, r4, r5    # r6 = value & r5

      bne r6, r0, done  # if non-zero found the leading one

      slli r5, r5, 1    # t = t >> 1

      addi r2, r2, -1   # i--

      br loop

done:

      ret