[[insns-vandn, Vector And-Not]]
= vandn.[vv,vx]

Synopsis::
Bitwise And-Not

Mnemonic::
vandn.vv vd, vs2, vs1, vm +
vandn.vx vd, vs2, rs1, vm

Encoding (Vector-Vector)::
[wavedrom, , svg]
....
{reg:[
{bits: 7, name: 'OP-V'},
{bits: 5, name: 'vd'},
{bits: 3, name: 'OPIVV'},
{bits: 5, name: 'vs1'},
{bits: 5, name: 'vs2'},
{bits: 1, name: 'vm'},
{bits: 6, name: '000001'},
]}
....

Encoding (Vector-Scalar)::
[wavedrom, , svg]
....
{reg:[
{bits: 7, name: 'OP-V'},
{bits: 5, name: 'vd'},
{bits: 3, name: 'OPIVX'},
{bits: 5, name: 'rs1'},
{bits: 5, name: 'vs2'},
{bits: 1, name: 'vm'},
{bits: 6, name: '000001'},
]}
....

Vector-Vector Arguments::

[%autowidth]
[%header,cols="4,2,2"]
|===
|Register
|Direction
|Definition

| Vs1 | input  | Op1  (to be inverted)
| Vs2 | input  | Op2
| Vd  | output | Result 
|===

Vector-Scalar Arguments::

[%autowidth]
[%header,cols="4,2,2"]
|===
|Register
|Direction
|Definition

| Rs1     | input  | Op1  (to be inverted)
| Vs2     | input  | Op2 
| Vd      | output | Result 
|===

Description:: 
A bitwise _and-not_ operation is performed.

Each bit of `Op1` is inverted and logically ANDed with the corresponding bits in `vs2`.
In the vector-scalar version, `Op1` is the sign-extended or truncated value in scalar
register `rs1`. 
In the vector-vector version, `Op1` is `vs1`.

// This instruction must always be implemented such that its execution latency does not depend
// on the data being operated upon.

[NOTE]
.Note on necessity of instruction
====
This instruction is performance-critical to SHA3. Specifically, the Chi step of the FIPS 202 Keccak Permutation. 
Emulating it via 2 instructions is expected to have significant performance impact.
The `.vv` form of the instruction is what is needed for SHA3; the `.vx` form was added for completeness.
====

[NOTE]
====
There is no .vi version of this instruction because the same functionality can be achieved by using an inversion
of the immediate value with the `vand.vi` instruction.
====

Operation::
[source,sail]
--
function clause execute (VANDN(vs2, vs1, vd, suffix)) = {
  foreach (i from vstart to vl-1) {
    let op1 = match suffix {
      "vv" => get_velem(vs1, SEW, i),
      "vx" => sext_or_truncate_to_sew(X(vs1))
    };
    let op2 = get_velem(vs2, SEW, i);
    set_velem(vd, EEW=SEW, i, ~op1 & op2);
  }
  RETIRE_SUCCESS
}

--

Included in::
<<zvbb>>, <<zvkb>>, <<zvkn>>, <<zvknc>>, <<Zvkng>>, <<zvks>>
<<Zvksc>>, <<Zvksg>>

