关于arch/arm64/include/asm/atomic.h的atomic_add函数的问题

问题描述 投票:0回答:1

我对基于 Linux 内核的 C 编码风格非常陌生。我试图理解“arch/arm64/include/asm/atomic.h”文件中“atomic_add”函数的以下实现(here第112-124行)。

static inline void atomic_add(int i, atomic_t *v)
{ 
    unsigned long tmp;
    int result;
    asm volatile("// atomic_add\n"
        "1: ldxr    %w0, %2\n"
        "   add %w0, %w0, %w3\n"
        "   stxr    %w1, %w0, %2\n"
        "   cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
        : "Ir" (I));

}

请帮助我理解以下问题。

  1. %w0 或 %w3 是什么意思?我明白%2指的是计数器值。

  2. %w0 是指(结果)变量还是通用寄存器?

  3. 约束字符串“Ir”是否代表“立即注册”?

linux-kernel embedded-linux atomic inline-assembly arm64
1个回答
2
投票
  1. w
    是一个操作数修饰符。它导致内联汇编包含寄存器的 32 位名称(
    w0
    等),而不是默认的 64 位名称(
    x0
    )。请参阅文档。 (此功能在 gcc 13 及更早版本中没有记录,但在实践中已经支持了很长时间,以与 armclang 兼容。)您也可以 尝试一下,并注意,如果您写
    %0
    而不是
    %w0 
    ,生成的指令使用64位
    x
    寄存器。这不是您想要的,因为这些应该是 32 位加载和存储。

  2. 两者都有。与 GCC 风格的扩展 asm 一样,

    %w0
    指的是内联 asm 的操作数编号 0(如上所述,使用
    w
    修饰符来使用其 32 位名称)。这是用
    "=&r" (result)
    声明的。由于约束是
    r
    ,因此该操作数将被分配一个通用寄存器,并且 asm 代码中所有提及
    %0
    (分别为
    %w0
    )的内容都将替换为该寄存器的名称。在上面的 Godbolt 示例中,编译器选择了
    x9
    (分别为
    w9
    )。

    (result)
    意味着在asm语句之后,编译器应该将
    w9
    中剩下的内容存储在变量
    result
    中。它可以通过存储到内存或将
    mov
    存储到用于
    result
    的任何寄存器来实现此目的,或者它可以只在该变量本身中分配
    result
    。如果幸运的话,优化器应该选择后者;并且由于
    result
    asm
    之后不用于任何操作,因此它不应该对该寄存器执行任何进一步操作。因此,实际上,带有稍后不使用的变量的输出操作数是告诉编译器“请选择一个我可以用作暂存的寄存器”的一种方式。

  3. 这是两个约束,

    I
    r
    。 GCC 记录了约束:简单特定于机器,当给出多个约束时,编译器可以选择满足其中任何一个。

    I
    要求一个适合在 AArch64
    add
    指令中使用的立即值,即一个 12 位零扩展数,可选地移位 12 位,这是一个编译时常量。如您所知,
    r
    需要通用寄存器。因此,如果您编写
    atomic_add(1, &c)
    atomic_add(1+1+1, &c)
    atomic_add(4095, &c)
    atomic_add(4096, &c)
    中的任何一个,
    asm
    语句的第二行将作为立即
    add
    指令发出,并将常量直接编码到指令中:
    add w9, w9, #1
    等等。但是,如果您编写
    atomic_add(4097, &c)
    atomic_add(my_variable, &c)
    ,编译器将在
    asm
    之前生成额外的代码,以将适当的值加载到某个寄存器(例如
    w13
    )中,并在
    add w9, w9, w13
    内发出
    asm
    。这可以让编译器尽可能生成更高效的立即数
    add
    ,同时总体上仍能获得正确的代码。

© www.soinside.com 2019 - 2024. All rights reserved.