[#insns-aes64esm, reftext="AES encrypt middle round instruction (RV64)"]
=== aes64esm

Synopsis::
AES middle round encryption instruction for RV64.

Mnemonic::
aes64esm rd, rs1, rs2

Encoding::
[wavedrom, , svg]
....
{reg:[
{bits: 7, name: 0x33},
{bits: 5, name: 'rd'},
{bits: 3, name: 0x0},
{bits: 5, name: 'rs1'},
{bits: 5, name: 'rs2'},
{bits: 5, name: 0x1b},
{bits: 2, name: 0x0},
]}
....

Description:: 
Uses the two 64-bit source registers to represent the entire AES state,
and produces _half_ of the next round output, applying the ShiftRows,
SubBytes and MixColumns steps.
This instruction must _always_ be implemented such that its execution
latency does not depend on the data being operated on.

.Note To Software Developers
[NOTE,caption="SH"]
====
The following code snippet shows one middle round of the AES block encryption.
`t0` and `t1` hold the current round state.
`t2` and `t3` hold the next round state.

  aes64esm t2, t0, t1
  aes64esm t3, t1, t0

Note the reversed register order of the second instruction.
====

Operation::
[source,sail]
--
function clause execute (AES64ESM(rs2, rs1, rd)) = {
  let sr : bits(64) = aes_rv64_shiftrows_fwd(X(rs2)[63..0], X(rs1)[63..0]);
  let wd : bits(64) = sr[63..0];
  let sb : bits(64) = aes_apply_fwd_sbox_to_each_byte(wd);
  X(rd)  =  aes_mixcolumn_fwd(sb[63..32]) @ aes_mixcolumn_fwd(sb[31..0]);
  RETIRE_SUCCESS
}
--

Included in::
[%header,cols="4,2,2"]
|===
|Extension
|Minimum version
|Lifecycle state

| <<zkne>> (RV64)
| v1.0.0
| Frozen
| <<zkn>> (RV64)
| v1.0.0
| Frozen
| <<zk>> (RV64)
| v1.0.0
| Frozen
|===


