st4
Store Multiple 4-Element Structures
ST4 { <Vt1>.<T>, <Vt2>.<T>, <Vt3>.<T>, <Vt4>.<T> }, [<Xn|SP>]
Stores four-element structures from four registers (Interleave RGBA).
Details
Stores four consecutive 4-element structures (e.g., RGBA pixels) from four NEON registers to memory with interleaved layout. The four registers (Vt1, Vt2, Vt3, Vt4) contain the elements to store; they are written as a block to the memory address in Xn|SP. The Q bit determines whether 64-bit (Q=0, 2 structures) or 128-bit (Q=1, 4 structures) operations are performed. No condition flags are affected; the instruction is AArch64 NEON-only.
Pseudocode Operation
address ← Xn|SP
element_size ← size_from_T
if Q == 1 then
structures ← 4
else
structures ← 2
for i = 0 to structures - 1 do
mem[address + (i * element_size * 0)] ← Vt1[i]
mem[address + (i * element_size * 1)] ← Vt2[i]
mem[address + (i * element_size * 2)] ← Vt3[i]
mem[address + (i * element_size * 3)] ← Vt4[i]
Xn|SP ← (post-index mode) ? Xn|SP + (4 * element_size * structures) : Xn|SP
Example
ST4 [x1]
Encoding
Binary Layout
0
Q
0011000
0
000000
0000
size
Rn
Rt
Operands
-
Vt1
R -
Vt2
G -
Vt3
B -
Vt4
A
Reference (Arm A64 ISA)
Instruction Forms
| Encoding | Instruction | ISA | Bit pattern | ||
|---|---|---|---|---|---|
| 0x0C000000 | ST4 { <Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>, <Vt4>.<T> }, [<Xn|SP>] | A64 | 0 | Q | 0011000 | 0 | 000000 | 0000 | size | Rn | Rt | ||
| 0x0C9F0000 | ST4 { <Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>, <Vt4>.<T> }, [<Xn|SP>], <imm> | A64 | 0 | Q | 0011001 | 0 | 0 | 11111 | 0000 | size | Rn | Rt | ||
| 0x0C800000 | ST4 { <Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>, <Vt4>.<T> }, [<Xn|SP>], <Xm> | A64 | 0 | Q | 0011001 | 0 | 0 | Rm | 0000 | size | Rn | Rt | ||
| 0x0D202000 | ST4 { <Vt>.B, <Vt2>.B, <Vt3>.B, <Vt4>.B }[<index>], [<Xn|SP>] | A64 | 0 | Q | 0011010 | 0 | 1 | 0000 | 0 | 001 | S | size | Rn | Rt | ||
| 0x0D206000 | ST4 { <Vt>.H, <Vt2>.H, <Vt3>.H, <Vt4>.H }[<index>], [<Xn|SP>] | A64 | 0 | Q | 0011010 | 0 | 1 | 0000 | 0 | 011 | S | size | Rn | Rt | ||
| 0x0D20A000 | ST4 { <Vt>.S, <Vt2>.S, <Vt3>.S, <Vt4>.S }[<index>], [<Xn|SP>] | A64 | 0 | Q | 0011010 | 0 | 1 | 0000 | 0 | 101 | S | 00 | Rn | Rt | ||
| 0x0D20A400 | ST4 { <Vt>.D, <Vt2>.D, <Vt3>.D, <Vt4>.D }[<index>], [<Xn|SP>] | A64 | 0 | Q | 0011010 | 0 | 1 | 0000 | 0 | 101 | 0 | 01 | Rn | Rt | ||
| 0x0DBF2000 | ST4 { <Vt>.B, <Vt2>.B, <Vt3>.B, <Vt4>.B }[<index>], [<Xn|SP>], #4 | A64 | 0 | Q | 0011011 | 0 | 1 | 11111 | 001 | S | size | Rn | Rt | ||
| 0x0DA02000 | ST4 { <Vt>.B, <Vt2>.B, <Vt3>.B, <Vt4>.B }[<index>], [<Xn|SP>], <Xm> | A64 | 0 | Q | 0011011 | 0 | 1 | Rm | 001 | S | size | Rn | Rt | ||
| 0x0DBF6000 | ST4 { <Vt>.H, <Vt2>.H, <Vt3>.H, <Vt4>.H }[<index>], [<Xn|SP>], #8 | A64 | 0 | Q | 0011011 | 0 | 1 | 11111 | 011 | S | size | Rn | Rt | ||
| 0x0DA06000 | ST4 { <Vt>.H, <Vt2>.H, <Vt3>.H, <Vt4>.H }[<index>], [<Xn|SP>], <Xm> | A64 | 0 | Q | 0011011 | 0 | 1 | Rm | 011 | S | size | Rn | Rt | ||
| 0x0DBFA000 | ST4 { <Vt>.S, <Vt2>.S, <Vt3>.S, <Vt4>.S }[<index>], [<Xn|SP>], #16 | A64 | 0 | Q | 0011011 | 0 | 1 | 11111 | 101 | S | 00 | Rn | Rt | ||
| 0x0DA0A000 | ST4 { <Vt>.S, <Vt2>.S, <Vt3>.S, <Vt4>.S }[<index>], [<Xn|SP>], <Xm> | A64 | 0 | Q | 0011011 | 0 | 1 | Rm | 101 | S | 00 | Rn | Rt | ||
| 0x0DBFA400 | ST4 { <Vt>.D, <Vt2>.D, <Vt3>.D, <Vt4>.D }[<index>], [<Xn|SP>], #32 | A64 | 0 | Q | 0011011 | 0 | 1 | 11111 | 101 | 0 | 01 | Rn | Rt |
Description
Store multiple 4-element structures from four registers. This instruction stores multiple 4-element structures to memory from four SIMD&FP registers, with interleaving. Every element of each register is stored.
Depending on the settings in the CPACR_EL1, CPTR_EL2, and CPTR_EL3 registers, and the current Security state and Exception level, an attempt to execute the instruction might be trapped.
Operation
CheckFPAdvSIMDEnabled64();
bits(64) address;
bits(64) eaddr;
bits(64) offs;
bits(datasize) rval;
integer tt;
constant integer ebytes = esize DIV 8;
AccessDescriptor accdesc = CreateAccDescASIMD(memop, nontemporal, tagchecked);
if n == 31 then
CheckSPAlignment();
address = SP[];
else
address = X[n, 64];
offs = Zeros(64);
for r = 0 to rpt-1
for e = 0 to elements-1
tt = (t + r) MOD 32;
for s = 0 to selem-1
rval = V[tt, datasize];
eaddr = GenerateAddress(address, offs, accdesc);
if memop == MemOp_LOAD then
Elem[rval, e, esize] = Mem[eaddr, ebytes, accdesc];
V[tt, datasize] = rval;
else // memop == MemOp_STORE
Mem[eaddr, ebytes, accdesc] = Elem[rval, e, esize];
offs = offs + ebytes;
tt = (tt + 1) MOD 32;
if wback then
if m != 31 then
offs = X[m, 64];
address = GenerateAddress(address, offs, accdesc);
if n == 31 then
SP[] = address;
else
X[n, 64] = address;