stp

Store Pair of Registers (64-bit)

STP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]

Stores two 64-bit registers.

Details

Stores two consecutive 64-bit registers to memory at an address calculated from a base register and a signed immediate offset (scaled by 8). Does not affect condition flags. AArch64-only instruction; the immediate offset is encoded as imm7 and scaled by 8 to form the actual offset.

Pseudocode Operation

address ← Xn + (imm7 << 3)
[address] ← Xt1
[address + 8] ← Xt2

Example

STP x3, x4, [x1, #16]

Encoding

Binary Layout
10
101
0
010
0
imm7
Rt2
Rn
Rt
 
Format Load/Store Pair
Opcode 0xA9000000
Extension Base

Operands

  • Xt1
    First transfer 64-bit register (load/store pair)
  • Xt2
    Second transfer 64-bit register (load/store pair)
  • Xn
    First source / base 64-bit integer register
  • imm
    Signed immediate value

Reference (Arm A64 ISA)

Instruction Forms

Encoding Instruction ISA Bit pattern
0x2C800000 STP <St1>, <St2>, [<Xn|SP>], #<imm> A64 00 | 101 | 1 | 001 | 0 | imm7 | Rt2 | Rn | Rt
0x6C800000 STP <Dt1>, <Dt2>, [<Xn|SP>], #<imm> A64 01 | 101 | 1 | 001 | 0 | imm7 | Rt2 | Rn | Rt
0xAC800000 STP <Qt1>, <Qt2>, [<Xn|SP>], #<imm> A64 10 | 101 | 1 | 001 | 0 | imm7 | Rt2 | Rn | Rt
0x2D800000 STP <St1>, <St2>, [<Xn|SP>, #<imm>]! A64 00 | 101 | 1 | 011 | 0 | imm7 | Rt2 | Rn | Rt
0x6D800000 STP <Dt1>, <Dt2>, [<Xn|SP>, #<imm>]! A64 01 | 101 | 1 | 011 | 0 | imm7 | Rt2 | Rn | Rt
0xAD800000 STP <Qt1>, <Qt2>, [<Xn|SP>, #<imm>]! A64 10 | 101 | 1 | 011 | 0 | imm7 | Rt2 | Rn | Rt
0x2D000000 STP <St1>, <St2>, [<Xn|SP>{, #<imm>}] A64 00 | 101 | 1 | 010 | 0 | imm7 | Rt2 | Rn | Rt
0x6D000000 STP <Dt1>, <Dt2>, [<Xn|SP>{, #<imm>}] A64 01 | 101 | 1 | 010 | 0 | imm7 | Rt2 | Rn | Rt
0xAD000000 STP <Qt1>, <Qt2>, [<Xn|SP>{, #<imm>}] A64 10 | 101 | 1 | 010 | 0 | imm7 | Rt2 | Rn | Rt
0x28800000 STP <Wt1>, <Wt2>, [<Xn|SP>], #<imm> A64 00 | 101 | 0 | 001 | 0 | imm7 | Rt2 | Rn | Rt
0xA8800000 STP <Xt1>, <Xt2>, [<Xn|SP>], #<imm> A64 10 | 101 | 0 | 001 | 0 | imm7 | Rt2 | Rn | Rt
0x29800000 STP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]! A64 00 | 101 | 0 | 011 | 0 | imm7 | Rt2 | Rn | Rt
0xA9800000 STP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]! A64 10 | 101 | 0 | 011 | 0 | imm7 | Rt2 | Rn | Rt
0x29000000 STP <Wt1>, <Wt2>, [<Xn|SP>{, #<imm>}] A64 00 | 101 | 0 | 010 | 0 | imm7 | Rt2 | Rn | Rt

Description

Store Pair of Registers calculates an address from a base register value and an immediate offset, and stores two 32-bit words or two 64-bit doublewords to the calculated address, from two registers. For information about memory accesses, see Load/Store addressing modes.

Operation

bits(64) address;
bits(64) address2;
bits(datasize) data1;
bits(datasize) data2;
constant integer dbytes = datasize DIV 8;
boolean privileged = PSTATE.EL != EL0;

AccessDescriptor accdesc = CreateAccDescGPR(MemOp_STORE, FALSE, privileged, tagchecked);

if n == 31 then
    CheckSPAlignment();
    address = SP[];
else
    address = X[n, 64];

if !postindex then
    address = GenerateAddress(address, offset, accdesc);

if rt_unknown && t == n then
    data1 = bits(datasize) UNKNOWN;
else
    data1 = X[t, datasize];
if rt_unknown && t2 == n then
    data2 = bits(datasize) UNKNOWN;
else
    data2 = X[t2, datasize];
if IsFeatureImplemented(FEAT_LSE2) then
    bits(2*datasize) full_data;
    if BigEndian(accdesc.acctype) then
        full_data = data1:data2;
    else
        full_data = data2:data1;
    accdesc.ispair = TRUE;
    Mem[address, 2*dbytes, accdesc] = full_data;
else
    address2 = GenerateAddress(address, dbytes, accdesc);
    Mem[address, dbytes, accdesc] = data1;
    Mem[address2, dbytes, accdesc] = data2;

if wback then
    if postindex then
        address = GenerateAddress(address, offset, accdesc);
    if n == 31 then
        SP[] = address;
    else
        X[n, 64] = address;