在RISC-V中,在汇编语言级别处理big-endian值最简单的方法是什么?也就是说,如何将big-endian值从内存加载到寄存器中,以本机端序(小端序)处理寄存器值,然后以big-endian将其存储回内存中。16、32和64位值用于许多网络协议和文件格式。
我找不到一个字节交换指令(相当于x86上的BSWAP或ARM上的REV)in the manual,也找不到任何关于big-endian加载和存储的东西。
在RISC-V中,在汇编语言级别处理big-endian值最简单的方法是什么?也就是说,如何将big-endian值从内存加载到寄存器中,以本机端序(小端序)处理寄存器值,然后以big-endian将其存储回内存中。16、32和64位值用于许多网络协议和文件格式。
我找不到一个字节交换指令(相当于x86上的BSWAP或ARM上的REV)in the manual,也找不到任何关于big-endian加载和存储的东西。
4条答案
按热度按时间eyh26e7m1#
在最新的RISC-V User-Level ISA Manual中没有提到字节交换指令(2.1版)。但是,手册中有一个占位符 *“B”位操作标准扩展 *。该扩展工作组的一些草稿材料是collected on GitHub。特别是,draft specification讨论了
grev
指令(广义反向),可以进行16、32和64位字节交换:该指令提供了一个硬件指令,它可以实现所有的字节顺序交换、逐位反转、短顺序交换、字顺序交换(RV 64)、半字节顺序交换、字节中的逐位反转等,所有这些都来自一个硬件指令。它接受一个寄存器值和一个立即数,该立即数通过控制递归树中发生反转的层来控制哪个函数发生。
扩展B工作组在最终确定规范之前“因官僚主义原因于2017年11月解散”。
2020年,工作组再次活跃起来,在链接的GitHub存储库上发布他们的工作成果。
因此,目前似乎没有什么比执行通常的shift-mask-or dance更简单的了。我在GCC或clang riscv端口中找不到任何汇编语言的bswap内部函数。作为一个例子,下面是
riscv64-linux-gnu-gcc
编译器8.1.0-12版本发出的bswapsi2
函数(该函数对32位值进行字节交换)的反汇编:vwoqyblh2#
RISC-V伊萨没有明确的字节交换指令。你最好的选择是使用一个C内建程序来执行这个计算,在GCC中可能是
__builtin_bswap32()
。这给了编译器尽可能多的信息,这样它就可以做出正确的决定。使用当前定义的ISA集,你几乎肯定会最终调用一个例程。但是如果定义了B扩展,您将透明地获得更好的生成代码。https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html。如果你在汇编中遇到了麻烦,那么你最好的办法就是调用一个现有的字节交换例程。一个32位的字节交换例程是
__bswapsi2
,它是libgcc的一部分--你可能会用到它,所以它就在附近。这就是编译器目前所做的,所以你所失去的就是在有更好的实现时省略函数调用。作为一个具体的例子,下面是我的示例C函数
并且所生成的组件
42fyovps3#
与x86不同,RISC-V没有
movbe
(可以在一个指令中加载和字节交换)。因此,在RISC-V上,你像往常一样加载/存储,在加载/存储之后/之前,你必须用额外的指令交换字节。
RISC-V "B" (Bitmanip) extension(版本0.92)包含通用的位反转指令(
grev
、grevi
)和几条可用于字节交换的伪指令:(表格基于第18页表2.5,RISC-V Bitmanip Extension V0.92)
截至2020年3月,“B”扩展处于草案状态,因此在硬件和模拟器中的支持有限。
如果没有“B”扩展,则必须使用多个基本指令来实现字节交换。例如,请参阅第16页的"B" specification,或者查看
__builtin_bswap16
、__builtin_bswap32
和__builtin_bswap64
gcc/clang内部函数的disassembled code。qzwqbdag4#
请注意,虽然有一条指令来执行此操作非常方便,但其他答案中使用的__bswapsi2函数在1.5 GHz HiFive Unleashed上的运行速度约为400 MB/s,这比gigE接口移动数据的速度要快得多。
即使在默认256 MHz下运行的HiFive 1上,它也将以60 MB/s的速度运行,而您只有16 KB的RAM和一堆GPIO,您不会在超过几MHz或几十MHz的频率下摆动。
我是BitManipulation工作组的成员。完整的GREV指令需要相当多的硬件(接近乘法器的东西),所以小型微控制器可能永远不会包含它。然而,我们计划使用相同的GREVI操作码,给予完整的字位反转和字节顺序反转,并将它们作为更简单的特殊情况指令来实现,不需要太多的电路,希望每个人都能包含它们。