Мне нужно поменять байты в байтах как можно быстрее во встроенной системе с использованием процессора ARM Cortex M4. Я использую gcc. Объем данных является переменным, но max составляет чуть более 2K. не имеет значения, преобразуется ли несколько дополнительных байтов, потому что я могу использовать буфер размером выше.Самый быстрый способ смены альтернативных байтов на ARM Cortex M4 с использованием gcc
Я знаю, что ARM имеет инструкцию REV16
, которую я могу использовать для замены альтернативных байтов в 32-битном слове. Что я не знаю:
Есть ли способ получить эту инструкцию в gcc, не прибегая к ассемблеру? Объект
__builtin_bswap16
работает только с 16-битными словами. Преобразование 4 байтов за раз, безусловно, будет быстрее, чем преобразование 2 байтов.Имеет ли Cortex M4 буфер переупорядочения и/или выполняет переименование регистров? Если нет, что мне нужно сделать, чтобы минимизировать конвейеры, когда я конвертирую слова в буфер в частично развернутом цикле?
Например, этот код эффективен, где REV16
надлежащим образом определены для решения (1):
uint32_t *buf = ... ;
size_t n = ... ; // (number of bytes to convert + 15)/16
for (size_t i = 0; i < n; ++i)
{
uint32_t a = buf[0];
uint32_t b = buf[1];
uint32_t c = buf[2];
uint32_t d = buf[3];
REV16(a, a);
REV16(b, b);
REV16(c, c);
REV16(d, d);
buf[0] = a;
buf[1] = b;
buf[2] = c;
buf[3] = d;
buf += 4;
}
Что случилось с [встроенным ассемблером] (https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html).Он не переносимый, но ни один из них не является '__builtin_bswap16'. '__builtin_bswap16' подходит только для GCC с несколькими типами процессоров. В основном для авторов libc, ориентированных на GCC. Высокоприоритетный условный код, который вызывает ошибку при переносе, вероятно, будет приемлемым для большинства людей. Просто добавьте хорошие комментарии. См. [Bswapdi2.S] (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/lib/bswapsdi2.S) в ядре Linux. Возможно, ваша система связана с памятью, а не с ЦП. –
Смотрите: [godbolt] (https://godbolt.org/g/nEydDt) для некоторого прямого «C», используя метод маски «bswapdi2.s» для arch
Спасибо, я могу использовать встроенный ассемблер, если нет другого способа одинаково быстро. Могу ли я просто использовать: 'asm (" rev16 a, a ");' применить операцию rev16 к моей переменной 'a' в приведенном выше примере? – dc42