immediate in assembly
aarch64
AArch64 is an ISA with a fixed instruction width of 32-bit. This obviously means there is not enough space to store a 64-bit immediate in a single instruction.
Assign immediate to register
Assigning the same value to the register x0 takes four instructions:
movz x0, 0x7788movk x0, 0x5566, lsl 16movk x0, 0x3344, lsl 32movk x0, 0x1122, lsl 48
- movz: assigns the given 16-bit value to the position given by the shift operand and zeroes all other bits. 移位 + 其他位置 0
- movn: assigns the given 16-bit value to the position given by the shift operand and negativing this value. movz 后对各 bit 取反
- movk: assigns the given 16-bit value to the position given by the shift operand and keeps the value of the other bits. 移位 + 其他位保持原来的值
Using immediate in Add/Sub
All instructions of the add/sub immediate instruction class allow a 12-bit unsigned immediate that can optionally be shifted by 12 bits (1 bit for the shift). If you want to use these instructions with an immediate that can’t be encoded in this format, you have no choice but to use a temporary register and possibly multiple instructions for initializing this register.
加减类的指令提供了 13bits 的空间用于支持立即数: 12bits 用于存放数据, 1bit 用于指示移位(左移 12bits)
Using immediate in Logic
The logical immediate instructions accept a bitmask immediate bimm32 or bimm64. Such an immediate consists EITHER of a single consecutive sequence with at least one non-zero bit, and at least one zero bit, within an element of 2, 4, 8, 16, 32 or 64 bits; the element then being replicated across the register width, or the bitwise inverse of such a value. The immediate values of all-zero and all-ones may not be encoded as a bitmask immediate, so an assembler must either generate an error for a logical instruction with such an immediate, or a programmer-friendly assembler may transform it into some other instruction which achieves the intended result.
| N | imms | immr | element size |
|---|---|---|---|
| 0 | 1 1 1 1 0 x | aaaaaa | 2 bits |
| 0 | 1 1 1 0 x x | aaaaaa | 4 bits |
| 0 | 1 1 0 x x x | aaaaaa | 8 bits |
| 0 | 1 0 x x x x | aaaaaa | 16 bits |
| 0 | 0 x x x x x | aaaaaa | 32 bits |
| 1 | x x x x x x | aaaaaa | 64 bits |
- size and length depends N and imms
- x is position of length
- rotation depends immr
C++ code to expand how logic immediate generate.
#include <stdint.h>#include <stdio.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 = 5334const 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;}
x86
Accept all immediate, place it at the end of instruction.
