Если вы идете на сырую скорость, то использование таблицы поиска (чтобы избежать внутреннего цикла с битовыми сдвигами), вероятно, лучший подход.
static int16 [] lookup = {
0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x007f,
0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x0081,
0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x0081, 0x007f,
0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x007f, 0x0081, 0x0081,
/* skip 251 entries */
0x0081, 0x0081, 0x0081, 0x0081, 0x0081, 0x0081, 0x0081, 0x0081,
};
void inline BitsToWords(int8 * input, int16 * output, int32 length) {
while ( length-- ) {
memcpy( output, lookup[ *input++ ], 16 );
output += 8;
}
}
Проблема в том, что сама таблица поиска будет 4 КБ (256 * 16), что больше, чем у вас есть. Это можно обойти одним из двух способов. Самое простое и маленькое решение будет примерно таким:
static int16 [] lookup = {
0x007f, 0x007f, 0x007f, 0x007f,
0x007f, 0x007f, 0x007f, 0x0081,
0x007f, 0x007f, 0x0081, 0x007f,
0x007f, 0x007f, 0x0081, 0x0081,
/* skip 11 entries */
0x0081, 0x0081, 0x0081, 0x0081,
};
void inline BitsToWords(int8 * input, int16 * output, int32 length) {
while ( length-- ) {
int 8 c = *input++;
memcpy( output, &lookup[ c &0x0f ], 8 );
memcpy( output+4, &lookup[ c >> 4 ], 8 );
output += 8;
}
}
Более сложным, но, возможно, более быстрым способом было бы использовать последовательность Де Брюина для кодирования всех возможных значений поиска. Это уменьшило бы таблицу поиска с 4 КБ до 512 + 14, но потребовало бы дополнительного уровня косвенности и другой индексной таблицы (256 байтов), в общей сложности 782 байта. Это приведет к удалению одного из вызовов memcpy (), а также сдвига и побитового вычисления, и за счет еще одного индекса. Вероятно, не обязательно в вашем случае, но все равно интересно.