c - RISC-V函数序言48位神秘转变

标签 c assembly riscv

我将一个 32 位打包值传递给沙箱内的函数,然后我假装它是 guest 中的一个结构。一切都很好,但序言中有一些神秘的说明:

uint16_t stdCactusVisibility(Block src, Block dst, uint16_t facing)
{
    // Only add sides if cacti meet
    if (src.getID() == dst.getID())
        return_fast(facing & (1 | 2 | 16 | 32));
    return_fast(facing);
}

该结构是 2x 16 位整数的包装器:

struct Block {
    uint16_t id;
    uint16_t otherbits;
};

简化版本。

stdCactusVisibility():
  4010c0:       03059593                slli    a1,a1,0x30
  4010c4:       03051513                slli    a0,a0,0x30
  4010c8:       0305d593                srli    a1,a1,0x30
  4010cc:       03055513                srli    a0,a0,0x30
  4010d0:       ff010113                addi    sp,sp,-16
  4010d4:       00a58663                beq     a1,a0,4010e0 <stdCactusVisibility+0x20>
  4010d8:       00060513                mv      a0,a2
  ...

我真正想知道的是这些 48 位移位想要实现什么?

我尝试过:使 Block 成为一个具有 2 个共享 16 位成员的 union 体。没有变化。

我尝试过:以正确的方式将寄存器解压到 block 中。没有变化。

我尝试过:返回完整的寄存器值。没有变化。

我的猜测是,这就是 RISC-V 创建 16 位值的方式,这是这里的返回值,也用于 ID 比较(a0 == a1)。如果是这样,那就太烦人了。

这是 RISC-V 的一个有问题的领域吗?有什么想法如何改进这个吗?这是一种在极低延迟模拟器中被调用约十亿次的函数。内部之所以有 C++,是为了通过适当抽象的魔力来减少指令数量。在最坏的情况下,调用的成本约为 3 纳秒,但如果函数中有很多指令,它会很快变得丑陋。

最佳答案

您将 srcdst 作为结构(而不​​是指针)传递。每个结构都在寄存器中传入:分别是 a0a1

它们的布局如下:

[63-48]   [47-32]   [31-16]   [15-0]
 XXXX      XXXX     otherbits  id

左移后,每个寄存器将如下所示:

[63-48]   [47-32]   [31-16]   [15-0]
   id      0000      0000      0000

然后右移后,如下所示:

[63-48]   [47-32]   [31-16]   [15-0]
 0000      0000      0000      id

基本上,它是从结构中提取 id 字段。这是执行 a0 &= 0xffff 的不同方式。我猜编译器认为这种方式比构造掩码并执行 AND 更有效。

关于c - RISC-V函数序言48位神秘转变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75591700/

相关文章:

iphone - 如何在 iOS 设备上编译 ARM 汇编文件和 iOS 模拟器使用常规 C 之间进行选择

assembly - 除以负数会导致 NASM 溢出

assembly - rbp 不允许作为 SIB 基础?

c - 大津阈值化

c - 有没有办法将文件描述符与用户定义的数据相关联?

linux - 我如何编译汇编代码以便可以看到它的十六进制字节代码?

linux - 如何为 RISC-V 编译 Linux Kernel 4.20

factorial - 如何在RISC-V中实现阶乘函数

riscv - RISC V LD 错误 - (.text+0xc4) : relocation truncated to fit: R_RISCV_JAL against `*UND*'

c - 程序在mac os下运行正常,在linux下运行异常