void aesni_crypt_ecb(int nr, unsigned char *rk, int mode,
                     const unsigned char input[16], unsigned char output[16]) {
  asm("movdqu    (%3), %%xmm0    \n\t"
      "movdqu    (%1), %%xmm1    \n\t"
      "pxor      %%xmm1, %%xmm0  \n\t"
      "addq      $16, %1         \n\t"
      "subl      $1, %0          \n\t"
      "test      %2, %2          \n\t"
      "jz        2f              \n\t"
      "1:                        \n\t"
      "movdqu    (%1), %%xmm1    \n\t"
      ".byte 0x66,0x0F,0x38,0xDC,"
      "0xC1"
      "\n\t"
      "addq      $16, %1         \n\t"
      "subl      $1, %0          \n\t"
      "jnz       1b              \n\t"
      "movdqu    (%1), %%xmm1    \n\t"
      ".byte 0x66,0x0F,0x38,0xDD,"
      "0xC1"
      "\n\t"
      "jmp       3f              \n\t"
      "2:                        \n\t"
      "movdqu    (%1), %%xmm1    \n\t"
      ".byte 0x66,0x0F,0x38,0xDE,"
      "0xC1"
      "\n\t"
      "addq      $16, %1         \n\t"
      "subl      $1, %0          \n\t"
      "jnz       2b              \n\t"
      "movdqu    (%1), %%xmm1    \n\t"
      ".byte 0x66,0x0F,0x38,0xDF,"
      "0xC1"
      "\n\t"
      "3:                        \n\t"
      "movdqu    %%xmm0, (%4)    \n\t"
      :
      : "r"(nr), "r"(rk), "r"(mode), "r"(input), "r"(output)
      : "memory", "cc", "xmm0", "xmm1");
}


x86 assembly (clang, -O0):
<aesni_crypt_ecb>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    -0x4(%rbp),%eax
mov    -0x10(%rbp),%rcx
mov    -0x14(%rbp),%edx
mov    -0x20(%rbp),%rsi
mov    -0x28(%rbp),%rdi
movdqu (%rsi),%xmm0
movdqu (%rcx),%xmm1
pxor   %xmm1,%xmm0
add    $0x10,%rcx
sub    $0x1,%eax
test   %edx,%edx
je     1167 <aesni_crypt_ecb+0x67>
movdqu (%rcx),%xmm1
aesenc %xmm1,%xmm0
add    $0x10,%rcx
sub    $0x1,%eax
jne    1143 <aesni_crypt_ecb+0x43>
movdqu (%rcx),%xmm1
aesenclast %xmm1,%xmm0
jmp    1186 <aesni_crypt_ecb+0x86>
movdqu (%rcx),%xmm1
aesdec %xmm1,%xmm0
add    $0x10,%rcx
sub    $0x1,%eax
jne    1167 <aesni_crypt_ecb+0x67>
movdqu (%rcx),%xmm1
aesdeclast %xmm1,%xmm0
movdqu %xmm0,(%rdi)
pop    %rbp
ret

x86 assembly (clang, -O2):
<aesni_crypt_ecb>:
movdqu (%rcx),%xmm0
movdqu (%rsi),%xmm1
pxor   %xmm1,%xmm0
add    $0x10,%rsi
sub    $0x1,%edi
test   %edx,%edx
je     1134 <aesni_crypt_ecb+0x34>
movdqu (%rsi),%xmm1
aesenc %xmm1,%xmm0
add    $0x10,%rsi
sub    $0x1,%edi
jne    1117 <aesni_crypt_ecb+0x17>
movdqu (%rsi),%xmm1
aesenclast %xmm1,%xmm0
jmp    114f <aesni_crypt_ecb+0x4f>
movdqu (%rsi),%xmm1
aesdec %xmm1,%xmm0
add    $0x10,%rsi
sub    $0x1,%edi
jne    1134 <aesni_crypt_ecb+0x34>
movdqu (%rsi),%xmm1
aesdeclast %xmm1,%xmm0
movdqu %xmm0,(%r8)
ret

LLVM IR (-O0):
define void @aesni_crypt_ecb(i32 %0, i8* %1, i32 %2, i8* %3, i8* %4) {
%6 = alloca i32
%7 = alloca i8*
%8 = alloca i32
%9 = alloca i8*
%10 = alloca i8*
store i32 %0, i32* %6
store i8* %1, i8** %7
store i32 %2, i32* %8
store i8* %3, i8** %9
store i8* %4, i8** %10
%11 = load i32, i32* %6
%12 = load i8*, i8** %7
%13 = load i32, i32* %8
%14 = load i8*, i8** %9
%15 = load i8*, i8** %10
ret void
}

LLVM IR (-O2):
define void @aesni_crypt_ecb(i32 %0, i8* %1, i32 %2, i8* %3, i8* %4) {
tail call void asm sideeffect "movdqu ($3), %xmm0 \0A\09movdqu ($1), %xmm1 \0A\09pxor %xmm1, %xmm0 \0A\09addq $$16, $1 \0A\09subl $$1, $0 \0A\09test $2, $2 \0A\09jz 2f \0A\091: \0A\09movdqu ($1), %xmm1 \0A\09.byte 0x66,0x0F,0x38,0xDC,0xC1\0A\09addq $$16, $1 \0A\09subl $$1, $0 \0A\09jnz 1b \0A\09movdqu ($1), %xmm1 \0A\09.byte 0x66,0x0F,0x38,0xDD,0xC1\0A\09jmp 3f \0A\092: \0A\09movdqu ($1), %xmm1 \0A\09.byte 0x66,0x0F,0x38,0xDE,0xC1\0A\09addq $$16, $1 \0A\09subl $$1, $0 \0A\09jnz 2b \0A\09movdqu ($1), %xmm1 \0A\09.byte 0x66,0x0F,0x38,0xDF,0xC1\0A\093: \0A\09movdqu %xmm0, ($4) \0A\09", "r,r,r,r,r,~{memory},~{cc},~{xmm0},~{xmm1},~{dirflag},~{fpsr},~{flags}"(i32 %0, i8* %1, i32 %2, i8* %3, i8* %4)
ret void
}