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 (プレリリース) を使用しています

4

3 に答える 3

12

A32 の「柔軟な第 2 オペランド」とは異なり、A64 には共通の即値形式はありません。即時オペランドのデータ処理命令 (シフトのような退屈で単純なものは無視) の場合、

  • 算術命令 ( add{s}sub{s}cmpcmn) は、オプションの 12 ビット左シフトで 12 ビットの符号なし即値を取ります。
  • 移動命令 ( movzmovnmovk) は、オプションでレジスタ内の任意の 16 ビット境界位置にシフトされた 16 ビット即値を取ります。
  • アドレス計算 ( adr, adrp) は 21 ビットの符号付き即値を使用しますが、それを直接指定する実際の構文はありません。そのためには、適切な「ラベル」を生成するためにアセンブラー式のトリックに頼る必要があります。
  • 論理命令 ( and{s}orreortst) は「ビットマスクの即時」を使用しますが、これについて説明できるかどうかもわかりません。そのため、気が遠くなるほど複雑な定義を引用します。

このような即値は、サイズ e = 2、4、8、16、32、または 64 ビットの同一要素のベクトルとして表示される 32 ビットまたは 64 ビットのパターンです。各要素には同じサブパターンが含まれます。つまり、1 から e-1 までの非ゼロ ビットの単一ランであり、0 から e-1 ビットでローテーションされます。このメカニズムは、5,334 個の一意の 64 ビット パターンを生成できます (2,667 組のパターンとそのビットごとの反転として)。

于 2015-06-18T01:32:42.693 に答える
11

これは、Notlikethat's answer で引用されているメカニズムに従って、すべての正当なビットマスク イミディエイトをダンプするコードの一部です。ビットマスクの即時生成ルールがどのように機能するかを理解するのに役立つことを願っています。

    #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 に答える