ARMv8 A64程序集中的立即值范围

Zac*_*ack 3 assembly gcc arm64

我的理解是ARMv8 A64汇编中的直接参数可以是12位长.如果是这种情况,为什么这行汇编代码:

AND X12, X10, 0xFEF 
Run Code Online (Sandbox Code Playgroud)

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

Error:  immediate out of range at operand 3 -- `AND X12, X10, 0xFEF'
Run Code Online (Sandbox Code Playgroud)

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

ADD X12, X10, 0xFEF
Run Code Online (Sandbox Code Playgroud)

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

Not*_*hat 9

与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到1-e-1非零位的单次运行,旋转0到e-1位.这种机制可以生成5,334个唯一的64位模式(2,667对模式及其按位反转).

  • 这种解释更有意义:“逻辑立即数指令接受位掩码立即数 bimm32 或 bimm64。这样的立即数由元素内至少一个非零位和至少一个零位的单个连续序列组成2、4、8、16、32 或 64 位;然后在寄存器宽度上复制该元素,或该值的按位反转。” (2认同)

Yan*_*Yan 5

这是一段代码,用于按照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;
    }
Run Code Online (Sandbox Code Playgroud)