ld2r

Load 2-Element Structure Replicate

LD2R { <Vt1>.<T>, <Vt2>.<T> }, [<Xn|SP>]

Loads 2 elements and replicates them to all lanes.

Details

Loads two consecutive elements from memory and replicates each to all corresponding lanes of two destination NEON vector registers. The two elements are interleaved in memory; Q bit selects 64-bit (Q=0, 1 pair) or 128-bit (Q=1, 2 pairs) operation. No condition flags are affected; the instruction is AArch64 NEON-only.

Pseudocode Operation

address ← Xn|SP
element_size ← size_from_T
element1 ← mem[address + 0 * element_size]
element2 ← mem[address + 1 * element_size]
if Q == 1 then
  lanes ← 16 / element_size
else
  lanes ← 8 / element_size
for i = 0 to lanes - 1 do
  Vt1[i] ← element1
  Vt2[i] ← element2
Xn|SP ← (post-index mode) ? Xn|SP + (2 * element_size) : Xn|SP

Example

LD2R [x1]

Encoding

Binary Layout
0
Q
0011010
1
1
0000
0
110
0
size
Rn
Rt
 
Format SIMD Load/Store
Opcode 0x0D60C000
Extension NEON (SIMD)

Operands

  • Vt1
    Dest 1
  • Vt2
    Dest 2
  • Xn
    First source / base 64-bit integer register

Reference (Arm A64 ISA)

Instruction Forms

Encoding Instruction ISA Bit pattern
0x0D60C000 LD2R { <Vt>.<T>, <Vt2>.<T> }, [<Xn|SP>] A64 0 | Q | 0011010 | 1 | 1 | 0000 | 0 | 110 | 0 | size | Rn | Rt
0x0DFFC000 LD2R { <Vt>.<T>, <Vt2>.<T> }, [<Xn|SP>], <imm> A64 0 | Q | 0011011 | 1 | 1 | 11111 | 110 | 0 | size | Rn | Rt
0x0DE0C000 LD2R { <Vt>.<T>, <Vt2>.<T> }, [<Xn|SP>], <Xm> A64 0 | Q | 0011011 | 1 | 1 | Rm | 110 | 0 | size | Rn | Rt

Description

Load single 2-element structure and Replicate to all lanes of two registers. This instruction loads a 2-element structure from memory and replicates the structure to all the lanes of the two SIMD&FP registers. 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(128) rval;
bits(esize) element;
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);
if replicate then
    // load and replicate to all elements
    for s = 0 to selem-1
        eaddr = GenerateAddress(address, offs, accdesc);
        element = Mem[eaddr, ebytes, accdesc];
        // replicate to fill 128- or 64-bit register
        V[t, datasize] = Replicate(element, datasize DIV esize);
        offs = offs + ebytes;
        t = (t + 1) MOD 32;
else
    // load/store one element per register
    for s = 0 to selem-1
        rval = V[t, 128];
        eaddr = GenerateAddress(address, offs, accdesc);
        if memop == MemOp_LOAD then
            // insert into one lane of 128-bit register
            Elem[rval, index, esize] = Mem[eaddr, ebytes, accdesc];
            V[t, 128] = rval;
        else // memop == MemOp_STORE
            // extract from one lane of 128-bit register
            Mem[eaddr, ebytes, accdesc] = Elem[rval, index, esize];
        offs = offs + ebytes;
        t = (t + 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;