Background: Given some input bytes B0, B1, B2, B3 and B4, I want to extract selected bits from these 5 bytes and generate an output word.
For example, denoting the nth bit of Bi as Bi[n]
, I want to be able to write a mapping f : (B0, B1, B2, B3, B4) → B2[4] B3[5] B3[4] B3[3] B3[2] B3[1] B0[5] B0[3] B0[1]
. So f(0b11001, 0b01100, 0b10101, 0b10011, 0b11111)
would return 0b010011101
.
An expression in C that might do this exact example would be
(B2 & 4 << 5) | (B3 << 3) | (B0 & 16 << 2) | (B0 & 4 << 1) | (B0 & 1)
using naive bitmasks and bitshifts.
Question: Is there any way to simplify such an expression to minimize the number of operations that need to be carried out?
For example, I note that B3 is copied in its entirety to some of the bits of the output, so I put it in place using B3 << 3
instead of masking and shifting individual bits. The first thing I thought of were Karnaugh maps since they came in handy in simplifying Boolean expressions, but I realised that since I am extracting and placing individual bits in different parts of a byte there is no simplification possible using Boolean algebra.
Reasoning: The reason why I want to do this is to be able to light the LEDs in a programmer-friendly manner on the BBC micro:bit. I want B0 to B4 to represent which LEDs are on in the physical 5x5 arrangement, but electronically these LEDs are wired in a complex 3x9 configuration. More information on the LEDs can be found here.
Typically a pattern would be stored in memory according to the physical 3x9 arrangement so as to be able to output this pattern to the LEDs in a single instruction, but I want to be able to map a 5x5 pattern to the 3x9 pattern programmatically. However an expression as shown above would require 5 load instructions, 9 bitwise AND/OR operations and 4 logical shifts, which is at least 9 times more inefficient that the normal method.