ARMv8 A64 汇编中的立即值范围
Range of immediate values in ARMv8 A64 assembly
我的理解是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(预发行版)
与A32的"flexible second operand"不同,A64中没有通用的立即数格式。对于立即操作数数据处理指令(忽略像移位这样无聊和直接的指令),
- 算术指令(
add{s}
、sub{s}
、cmp
、cmn
)采用 12 位无符号立即数和可选的 12 位左移。
- 移动指令(
movz
、movn
、movk
)将一个 16 位立即数选择性地移位到寄存器中任何 16 位对齐的位置。
- 地址计算(
adr
、adrp
)采用 21 位有符号立即数,尽管没有直接指定它的实际语法 - 为此,您必须求助于汇编程序表达式生成适当 "label". 的诡计
- 逻辑指令(
and{s}
、orr
、eor
、tst
)需要一个"bitmask immediate",我什至不确定我是否可以解释, 所以我只引用 the mind-bogglingly complicated definition:
Such an immediate is a 32-bit or 64-bit pattern viewed as a vector of identical elements of size e = 2, 4, 8, 16, 32, or 64 bits. Each element contains the same sub-pattern: a single run of 1 to e-1 non-zero bits, rotated by 0 to e-1 bits. This mechanism can generate 5,334 unique 64-bit patterns (as 2,667 pairs of pattern and their bitwise inverse).
这里有一段代码可以按照 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] = '[=10=]';
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;
}
位掩码立即数的另一种解释,现在是早上,我终于理解了“令人难以置信的复杂”定义。 (参见 Notlikethat 的回答。)也许有些人更容易理解。
就是X>0个连续的0跟Y>0个连续的1,其中X+Y是2的幂,重复填满整个参数然后任意旋转。
另请注意,其他立即数格式的可选移位是精确 位数,而不是“最多”。也就是说,16 位立即数可以 exactly 移动 0、16、32 或 48 位,而 12 位立即数 only 移动 0或 12 位。
我的理解是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(预发行版)
与A32的"flexible second operand"不同,A64中没有通用的立即数格式。对于立即操作数数据处理指令(忽略像移位这样无聊和直接的指令),
- 算术指令(
add{s}
、sub{s}
、cmp
、cmn
)采用 12 位无符号立即数和可选的 12 位左移。 - 移动指令(
movz
、movn
、movk
)将一个 16 位立即数选择性地移位到寄存器中任何 16 位对齐的位置。 - 地址计算(
adr
、adrp
)采用 21 位有符号立即数,尽管没有直接指定它的实际语法 - 为此,您必须求助于汇编程序表达式生成适当 "label". 的诡计
- 逻辑指令(
and{s}
、orr
、eor
、tst
)需要一个"bitmask immediate",我什至不确定我是否可以解释, 所以我只引用 the mind-bogglingly complicated definition:
Such an immediate is a 32-bit or 64-bit pattern viewed as a vector of identical elements of size e = 2, 4, 8, 16, 32, or 64 bits. Each element contains the same sub-pattern: a single run of 1 to e-1 non-zero bits, rotated by 0 to e-1 bits. This mechanism can generate 5,334 unique 64-bit patterns (as 2,667 pairs of pattern and their bitwise inverse).
这里有一段代码可以按照 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] = '[=10=]';
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;
}
位掩码立即数的另一种解释,现在是早上,我终于理解了“令人难以置信的复杂”定义。 (参见 Notlikethat 的回答。)也许有些人更容易理解。
就是X>0个连续的0跟Y>0个连续的1,其中X+Y是2的幂,重复填满整个参数然后任意旋转。
另请注意,其他立即数格式的可选移位是精确 位数,而不是“最多”。也就是说,16 位立即数可以 exactly 移动 0、16、32 或 48 位,而 12 位立即数 only 移动 0或 12 位。