assemblyx86x86-64intelmachine-code

What do NDS, NDD, and DDS stand for in encoding VEX instructions?


From Intel's x86 manuals, Vol2, Section 3.1.1.2: Opcode Column in the Instruction Summary Table (Instructions with VEX prefix)

NDS, NDD, DDS: specifies that VEX.vvvv field is valid for the encoding of a register operand:

  • VEX.NDS: VEX.vvvv encodes the first source register in an instruction syntax where the content of source registers will be preserved.
  • VEX.NDD: VEX.vvvv encodes the destination register that cannot be encoded by ModR/M:reg field.
  • VEX.DDS: VEX.vvvv encodes the second source register in a three-operand instruction syntax where the content of first source register will be overwritten by the result.

I think that it has something to do with "non-destructive source" and I presume that's what NDS stands for. What do the others stand for, and how does that affect an instruction's encoding? On a similar note, why do they even matter - as the AMD manual does not include any reference as far as I can tell to these terms?


Solution

  • According to the Intel APX docs (Advanced Performance Extensions: REX2 and EVEX for legacy integer instructions like sub, and finally an encoding of setcc that writes a full 32/64-bit register: Intel APX Architecture Specification - July 2023 Revision 1.0):

    Presumably the pre-2018 SDM editions used the same expansions for the acronyms.


    I haven't looked at the AMD manuals, but I assume they chose some other way to indicate which operand is encoded by the VEX.vvvv field, for instructions that use it.

    Intel uses this notation to remind you / make it clear which operand is the vvvv field. It's already redundant, because the "Operand Encoding" table for each instruction shows which operand is encoded in which field.


    Update: Intel removed them from their manual maybe in the Nov 2018 update. They were also removed from the "future extensions" manual rev 035 in October 2018 which has instruction listings in the same format as the vol.2 manual, and has a revision table where they provided this changelog:

    Removal of NDD/DDS/NDS terms from instructions. Note: Previously, the terms NDS, NDD and DDS were used in instructions with an EVEX (or VEX) prefix. These terms indicated that the vvvv field was valid for encoding, and specified register usage. These terms are no longer necessary and are redundant with the instruction operand encoding tables provided with each instruction. The instruction operand encoding tables give explicit details on all operands, indicating where every operand is stored and if they are read or written. If vvvv is not listed as an operand in the instruction operand encoding table, then EVEX (or VEX) vvvv must be 0b1111.

    So that tells us that the purpose of those NDD/DDS/NDS tags was to indicate which operand was which, and whether they were read or write.


    Non-Destructive Source is a phrase used elsewhere in the same volume of the manual (see below), so I'm pretty confident that's the correct interpretation of NDS.

    I think the obvious interpretation of NDD is Non-Destructive Destination (where the SSE2 versions of shifts annoyingly are destructive).

    It's unclear what DDS is supposed to stand for. "Destructive Destination-Source" doesn't fit, because it's the other source reg that gets overwritten.


    Intel manual vol2 Section 2.3.5 The VEX Prefix:

    The bit fields of the VEX prefix can be summarized by its functional purposes:

    • Non-destructive source register encoding (applicable to three and four operand syntax): This is the first source operand in the instruction syntax. VEX.vvvv.

    (inverted: 1111 for xmm0, 0000 for xmm15. As described later, the inversion avoids overlapping with valid encodings of 32bit-only LES and LDS (load far-pointer) instructions. 32bit mode can only use xmm0-7, so the first bit is always the required 1, making it not a valid LES/LDS.)

    So yes, "Non Destructive source" is a phrase that Intel's manual uses.


    Section 2.3.6: Instruction Operand Encoding and VEX.vvvv, ModR/M

    Some VEX-encoded instructions have syntax with less than three operands, e.g. VEX-encoded pack shift instructions support one source operand and one destination operand).

    The roles of VEX.vvvv, reg field of ModR/M byte (ModR/M.reg), r/m field of ModR/M byte (ModR/M.r/m) with respect to encoding destination and source operands vary with different type of instruction syntax.

    The role of VEX.vvvv can be summarized to three situations:

    • VEX.vvvv encodes the first source register operand, specified in inverted (1’s complement) form and is valid for instructions with 2 or more source operands. (This is the NDS case)

    • VEX.vvvv encodes the destination register operand, specified in 1’s complement form for certain vector shifts. The instructions where VEX.vvvv is used as a destination are listed in Table 2-9. The notation in the “Opcode” column in Table 2-9 is described in detail in section 3.1.1. (The part quoted in the question)

    The vector shifts in question are VPS{R,L}L{W,D,Q}, VPSRA{W,D,Q}, and VPS{R,L}LDQ (byte-shift), that use the /r field of mod/rm as extra opcode bits like some one-operand integer instructions (e.g. and r/m32, imm8). e.g.

    This is why the SSE versions are in-place bit/byte shifts, frequently requiring a movdqa instruction. There are a few free opcodes in the 66 0F xx SSE2 coding space which Intel could have used instead making these frequently-used instructions destructive. I guess they were already stuck with their decision to use the /r field for the 0F xx MMX version, though. Making the new-with-SSE2 byte-shift insn destructive too was unnecessary, I think. At least they managed to make one non-destructive shuffle, pshufd.