Convert between big-endian and little-endian on RISC-V

前端 未结 4 1457
-上瘾入骨i
-上瘾入骨i 2021-01-14 07:45

What is the simplest way to work with big-endian values in RISC-V at the assembly language level? That is, how to load a big-endian value from memory into a register, work w

4条回答
  •  梦毁少年i
    2021-01-14 07:57

    The RISC-V ISA has no explicit byte swapping instructions. Your best bet is to use a C builtin to perform this calculation, which in GCC land would be something like __builtin_bswap32(). This gives the compiler the most information possible so it can make good decisions. With the current set of defined ISAs you'll almost certainly end up calling into a routine, but if a B extension is ever defined you will transparently get better generated code. The full set of defined builtins is availiable online: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html .

    If you're stuck doing this in assembly, then your best bet is to call into an existing byte swap routine. The canonical one for a 32-bit swap is __bswapsi2, which is part of libgcc -- you're probably using that anyway, so it'll be around. That's what the compiler currently does so all you're losing is eliding the function call when there's a better implementation available.

    As a concrete example, here's my example C function

    unsigned swapb(unsigned in) { return __builtin_bswap32(in); }
    

    and the generated assembly

    swapb:
        addi    sp,sp,-16
        sd  ra,8(sp)
        call    __bswapsi2
        ld  ra,8(sp)
        sext.w  a0,a0
        addi    sp,sp,16
        jr  ra
    

提交回复
热议问题