Ich muss alternative Bytes in einem Puffer so schnell wie möglich in einem eingebetteten System mit ARM Cortex M4-Prozessor austauschen. Ich benutze gcc. Die Datenmenge ist variabel, aber die maximale ist etwas über 2K. Es spielt keine Rolle, ob ein paar zusätzliche Bytes konvertiert werden, weil ich einen übergroßen Puffer verwenden kann.Schnellste Möglichkeit, alternative Bytes auf ARM Cortex M4 mit gcc auszutauschen
Ich weiß, dass der ARM die REV16
Anweisung hat, die ich verwenden kann, um alternative Bytes in einem 32-Bit-Wort zu tauschen. Was ich nicht weiß ist:
Gibt es eine Möglichkeit, diese Anweisung in gcc ohne Assembler zu bekommen? Das
__builtin_bswap16
intrinsische System scheint nur mit 16-Bit-Wörtern zu arbeiten. Das Konvertieren von 4 Bytes gleichzeitig ist sicherlich schneller als das Konvertieren von 2 Bytes.Hat der Cortex M4 einen Umordnungspuffer und/oder registriert er Umbenennen? Wenn nicht, was muss ich tun, um Pipeline-Blockierungen zu minimieren, wenn ich die dwords des Puffers in einer teilweise abgerollten Schleife konvertiere?
Zum Beispiel dieser Code effizient ist, wo REV16
in geeigneter Weise zu lösen (1) definiert ist:
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;
}
Was ist falsch mit [Inline-Assembler] (https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html).Es ist nicht tragbar, aber auch nicht "__builtin_bswap16". '__builtin_bswap16' ist nur gut für GCC mit mehreren CPU-Typen. Hauptsächlich für libc-Autoren, die auf GCC abzielen. Ein sehr gezielter bedingter Code, der beim Portieren einen Fehler verursacht, wäre für die meisten Leute wahrscheinlich akzeptabel. Schreiben Sie einfach ein paar gute Kommentare. Siehe: [bswapdi2.S] (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/lib/bswaps- di2.S) im Linux-Kernel. Ihr System ist möglicherweise speichergebunden und nicht an die CPU gebunden. –
Siehe: [godbolt] (https://godbolt.org/g/nEydDt) für einige gerade 'C' mit der Maskenmethode von 'bswapdi2.s' für arch
Danke, ich kann Inline-Assembler verwenden, wenn kein anderer Weg gleich schnell ist. Kann ich einfach verwenden: 'asm (" rev16 a, a ");' um die rev16-Operation auf meine Variable 'a' im obigen Beispiel anzuwenden? – dc42