gpt4 book ai didi

gcc - 使用 gcc 在 ARM Cortex M4 上交换备用字节的最快方法

转载 作者:行者123 更新时间:2023-12-01 15:39:22 26 4
gpt4 key购买 nike

我需要在使用 ARM Cortex M4 处理器的嵌入式系统中尽快交换缓冲区中的交替字节。我使用海湾合作委员会。数据量是可变的,但最大值略高于 2K。转换一些额外的字节并不重要,因为我可以使用超大缓冲区。

我知道 ARM 有 REV16 指令,我可以用它来交换 32 位字中的交替字节。我不知道的是:

  1. 有没有办法在不借助汇编程序的情况下在 gcc 中获取此指令? __builtin_bswap16 内在函数似乎只对 16 位字进行操作。一次转换 4 个字节肯定比转换 2 个字节快。

  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;
}

最佳答案

您不能使用 __builtin_bswap16 函数,因为您声明的原因,它适用于 16 位字,因此其他半字将为 0。我想这样做的原因是为了在没有与 ARM 上的 REV16 行为相似的指令的处理器上保持内在工作相同。

函数

uint32_t swap(uint32_t in)
{
in = __builtin_bswap32(in);
in = (in >> 16) | (in << 16);
return in;
}

编译为 (ARM GCC 5.4.1 -O3 -std=c++11 -march=armv7-m -mtune=cortex-m4 -mthumb)

    rev     r0, r0
ror r0, r0, #16
bx lr

您可能会要求编译器将其内联,这将为您提供每个 32 位字 2 条指令。我想不出一种方法让 GCC 生成具有 32 位操作数的 REV16,而无需使用内联汇编声明您自己的函数。

编辑

作为跟进,基于 artless noise 关于 __builtin_bswap 函数不可移植性的评论,the compiler recognizes

uint32_t swap(uint32_t in)
{
in = ((in & 0xff000000) >> 24) | ((in & 0x00FF0000) >> 8) | ((in & 0x0000FF00) << 8) | ((in & 0xFF) << 24);
in = (in >> 16) | (in << 16);
return in;
}

并创建与上面相同的 3 指令函数,因此这是一种更可移植的实现方式。不同的编译器是否会产生相同的输出...

编辑编辑

如果允许内联汇编器,下面的函数

inline uint32_t Rev16(uint32_t a)
{
asm ("rev16 %1,%0"
: "=r" (a)
: "r" (a));
return a;
}

得到内联,并作为单个指令,可以看出 here.

关于gcc - 使用 gcc 在 ARM Cortex M4 上交换备用字节的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41675438/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com