Bit Manipulation

Bit-masking is a technique to selectively modify individual bits without affecting other bits.

Bit SET

To set a bit, we need to use the OR operator. This is just like an OR logical gate you should've learned in your Digital Design course.

 // We want to set Bit #7 of a variable called: REG
REG = REG | 0x80;
// Let's set bit #31:
REG = REG | 0x80000000;
// Here is an easier way to write these:
// (1 << 31) means 1 gets shifted left 31 times to produce 0x80000000
REG = REG | (1 << 31);
// Simplify further:
REG |= (1 << 31);
// Set Bit #21 and Bit #23 at the same time
REG |= (1 << 21) | (1 << 23);

Bit CLEAR

To set a bit to 0, in other words reset or clear a bit, the logic is similar, but instead of ORing a bit, we will an AND function to clear. Note: that ANDing something with 0 clears it and ANDing something with a 1 does not change it. The tilde (~) operator can help us invert the bits of a value in the following examples:

// Assume we want to reset Bit#7 of a register called: REG
REG = REG &   0x7F;    
REG = REG & ~(0x80); // Same thing as above, but using ~ is easier

// Let's reset bit#31:
REG = REG & ~(0x80000000);

// Let's show you the easier way:
REG = REG & ~(1 << 31);

// Simplify further:
REG &= ~(1 << 31);

// Reset Bit#21 and Bit# 23:
REG &= ~( (1 << 21) | (1 << 23) );

Bit TOGGLE

 // Using XOR operator to toggle 5th bit
REG ^= (1 << 5);

Bit CHECK

Suppose you want to check bit 7 of a register is set:

bool check_bit = REG & (1 << 7);
if(check_bit)
{
 	DoAThing();
}

Now let's work through another example in which we want to wait until bit#9 is 0:

// One way:
while(REG & (1 << 9) != 0)
{
  continue;
}
// Another way:
while(REG & (1 << 9))
{
  continue;
}

Multi-Bit Insertion

// Insert a set of continguous bits into a target value.
// Value within target is unknown. This is shown using X's
//
// target   =        0xXXXX'XXXX
//                        ^
//                       /
//                      /
// value   = 0xABCD --+
// position = 16
// width    = 16
//
// return   =        0xABCD'XXXX

// First you must clear the bits in that location
target &= ~(0xFFFF << 16);
// Now that there are only 0s from position 16 to 31, ew
// can OR those bits with our own set of 1s.
target |=  (0xABCD << 16);

Multi-Bit Extraction

/// Extract a set of contiguous bits from a target value.
///
/// target   =        0x00FE'DCBA
///                            ^
///                           /
///                          /
/// value  = 4 -----------+
/// width    = 8
///
/// return   = 0xCB

// Shift target to the left by 4 to make the 0th bit the start of the bits you want to extract.
// Store the result in to a local variable
uint32_t result = target >> 4;
// Since we only want 8 bits from the result, we need to clear away the rest of the bits from 
// the original target.
// AND the result with 0xFF, to clear everything except for the first 8 bits.
result = result & 0xFF;

 

Back to top