5

我的理解是 ARMv8 A64 程序集中的立即参数可以是 12 位长。如果是这样,为什么这行汇编代码:

AND X12, X10, 0xFEF 

产生此错误(使用 gcc 编译时)

Error:  immediate out of range at operand 3 -- `AND X12, X10, 0xFEF'

有趣的是,这行汇编代码编译得很好:

ADD X12, X10, 0xFEF

我正在使用 aarch64-linux-gnu-gcc (Linaro GCC 2014.11) 4.9.3 (prerelease)

4

3 回答 3

12

与 A32 的“灵活第二操作数”不同,A64 中没有通用的立即数格式。对于立即操作数数据处理指令(忽略无聊和直接的指令,如移位),

  • 算术指令 ( add{s}, sub{s}, cmp, cmn) 采用 12 位无符号立即数和可选的 12 位左移。
  • 移动指令 ( movz, movn, movk) 采用 16 位立即数,可以选择移位到寄存器内的任何 16 位对齐位置。
  • 地址计算 ( adr, adrp) 采用 21 位有符号立即数,尽管没有直接指定它的实际语法 - 为此,您必须求助于汇编器表达式技巧来生成适当的“标签”。
  • 逻辑指令(and{s}, orr, eor, tst)采用“位掩码立即数”,我不确定我什至可以解释,所以我只引用令人难以置信的复杂定义

这种立即数是 32 位或 64 位模式,被视为大小为 e = 2、4、8、16、32 或 64 位的相同元素的向量。每个元素都包含相同的子模式:单次运行 1 到 e-1 非零位,旋转 0 到 e-1 位。这种机制可以生成 5,334 个唯一的 64 位模式(作为 2,667 对模式及其按位反转)。

于 2015-06-18T01:32:42.693 回答
11

这是一段代码,用于按照 Notlikethat 的答案中引用的机制转储所有合法位掩码立即数。希望它有助于理解生成位掩码立即数的规则是如何工作的。

    #include <stdio.h>
    #include <stdint.h>

    // Dumps all legal bitmask immediates for ARM64
    // Total number of unique 64-bit patterns: 
    //   1*2 + 3*4 + 7*8 + 15*16 + 31*32 + 63*64 = 5334

    const char *uint64_to_binary(uint64_t x) {
      static char b[65];
      unsigned i;
      for (i = 0; i < 64; i++, x <<= 1)
        b[i] = (0x8000000000000000ULL & x)? '1' : '0';
      b[64] = '\0';
      return b;
    }

    int main() {
      uint64_t result;
      unsigned size, length, rotation, e;
      for (size = 2; size <= 64; size *= 2)
        for (length = 1; length < size; ++length) {
          result = 0xffffffffffffffffULL >> (64 - length);
          for (e = size; e < 64; e *= 2)
            result |= result << e;
          for (rotation = 0; rotation < size; ++rotation) {
            printf("0x%016llx %s (size=%u, length=%u, rotation=%u)\n",
                (unsigned long long)result, uint64_to_binary(result),
                size, length, rotation);
            result = (result >> 63) | (result << 1);
          }
        }
      return 0;
    }
于 2015-10-21T16:54:11.970 回答
2

位掩码立即数的另一种解释,现在是早上,我终于理解了“令人难以置信的复杂”的定义。(参见 Notlikethat's answer。)也许有些人会更容易理解。

它是 X>0 个连续零,然后是 Y>0 个连续零,其中 X+Y 是 2 的幂,重复以填充整个参数,然后任意旋转。

另请注意,其他立即格式的可选移位是精确的位数,而不是“最多”。也就是说,16 位立即数可以精确地移动 0、16、32 或 48 位,而 12 位立即数只能移动012位。

于 2021-11-22T10:20:13.853 回答