!C99Shell v. 2.1 [PHP 8 Update] [02.02.2022]!

Software: Apache/2.4.53 (Unix) OpenSSL/1.1.1o PHP/7.4.29 mod_perl/2.0.12 Perl/v5.34.1. PHP/7.4.29 

uname -a: Linux vps-2738122-x 4.15.0-213-generic #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023 x86_64 

uid=1(daemon) gid=1(daemon) grupos=1(daemon) 

Safe-mode: OFF (not secure)

/opt/apex_tdfonline/proyectos/tdfonline/www/docs/openssl/crypto/aes/asm/   drwxr-xr-x
Free 14.57 GB of 61.93 GB (23.53%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     aesni-sha256-x86_64.pl (43.5 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#! /usr/bin/env perl
# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
# ====================================================================
#
# January 2013
#
# This is AESNI-CBC+SHA256 stitch implementation. The idea, as spelled
# in http://download.intel.com/design/intarch/papers/323686.pdf, is
# that since AESNI-CBC encrypt exhibit *very* low instruction-level
# parallelism, interleaving it with another algorithm would allow to
# utilize processor resources better and achieve better performance.
# SHA256 instruction sequences(*) are taken from sha512-x86_64.pl and
# AESNI code is weaved into it. As SHA256 dominates execution time,
# stitch performance does not depend on AES key length. Below are
# performance numbers in cycles per processed byte, less is better,
# for standalone AESNI-CBC encrypt, standalone SHA256, and stitched
# subroutine:
#
#         AES-128/-192/-256+SHA256   this(**)    gain
# Sandy Bridge        5.05/6.05/7.05+11.6        13.0    +28%/36%/43%
# Ivy Bridge        5.05/6.05/7.05+10.3        11.6    +32%/41%/50%
# Haswell        4.43/5.29/6.19+7.80        8.79    +39%/49%/59%
# Skylake        2.62/3.14/3.62+7.70        8.10    +27%/34%/40%
# Bulldozer        5.77/6.89/8.00+13.7        13.7    +42%/50%/58%
# Ryzen(***)        2.71/-/3.71+2.05        2.74/-/3.73    +74%/-/54%
# Goldmont(***)        3.82/-/5.35+4.16        4.73/-/5.94    +69%/-/60%
#
# (*)    there are XOP, AVX1 and AVX2 code paths, meaning that
#    Westmere is omitted from loop, this is because gain was not
#    estimated high enough to justify the effort;
# (**)    these are EVP-free results, results obtained with 'speed
#    -evp aes-256-cbc-hmac-sha256' will vary by percent or two;
# (***)    these are SHAEXT results;

# $output is the last argument if it looks like a file (it has an extension)
# $flavour is the first argument if it doesn't look like a file
$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;

$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);

$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";

if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
        =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
    $avx = ($1>=2.19) + ($1>=2.22);
}

if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
       `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
    $avx = ($1>=2.09) + ($1>=2.10);
}

if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
       `ml64 2>&1` =~ /Version ([0-9]+)\./) {
    $avx = ($1>=10) + ($1>=12);
}

if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:clang|LLVM) version|.*based on LLVM) ([0-9]+\.[0-9]+)/) {
    $avx = ($2>=3.0) + ($2>3.0);
}

$shaext=$avx;    ### set to zero if compiling for 1.0.1
$avx=1        if (!$shaext && $avx);

open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
    or die "can't call $xlate: $!";
*STDOUT=*OUT;

$func="aesni_cbc_sha256_enc";
$TABLE="K256";
$SZ=4;
@ROT=($A,$B,$C,$D,$E,$F,$G,$H)=("%eax","%ebx","%ecx","%edx",
                "%r8d","%r9d","%r10d","%r11d");
($T1,$a0,$a1,$a2,$a3)=("%r12d","%r13d","%r14d","%r15d","%esi");
@Sigma0=( 2,13,22);
@Sigma1=( 6,11,25);
@sigma0=( 7,18, 3);
@sigma1=(17,19,10);
$rounds=64;

########################################################################
# void aesni_cbc_sha256_enc(const void *inp,
#            void *out,
#            size_t length,
#            const AES_KEY *key,
#            unsigned char *iv,
#            SHA256_CTX *ctx,
#            const void *in0);
($inp,  $out,  $len,  $key,  $ivp, $ctx, $in0) =
("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");

$Tbl="%rbp";

$_inp="16*$SZ+0*8(%rsp)";
$_out="16*$SZ+1*8(%rsp)";
$_end="16*$SZ+2*8(%rsp)";
$_key="16*$SZ+3*8(%rsp)";
$_ivp="16*$SZ+4*8(%rsp)";
$_ctx="16*$SZ+5*8(%rsp)";
$_in0="16*$SZ+6*8(%rsp)";
$_rsp="`16*$SZ+7*8`(%rsp)";
$framesz=16*$SZ+8*8;

$code=<<___;
.text

.extern    OPENSSL_ia32cap_P
.globl    $func
.type    $func,\@abi-omnipotent
.align    16
$func:
.cfi_startproc
___
                        if ($avx) {
$code.=<<___;
    lea    OPENSSL_ia32cap_P(%rip),%r11
    mov    \$1,%eax
    cmp    \$0,`$win64?"%rcx":"%rdi"`
    je    .Lprobe
    mov    0(%r11),%eax
    mov    4(%r11),%r10
___
$code.=<<___ if ($shaext);
    bt    \$61,%r10            # check for SHA
    jc    ${func}_shaext
___
$code.=<<___;
    mov    %r10,%r11
    shr    \$32,%r11

    test    \$`1<<11`,%r10d            # check for XOP
    jnz    ${func}_xop
___
$code.=<<___ if ($avx>1);
    and    \$`1<<8|1<<5|1<<3`,%r11d    # check for BMI2+AVX2+BMI1
    cmp    \$`1<<8|1<<5|1<<3`,%r11d
    je    ${func}_avx2
___
$code.=<<___;
    and    \$`1<<28`,%r10d            # check for AVX
    jnz    ${func}_avx
    ud2
___
                        }
$code.=<<___;
    xor    %eax,%eax
    cmp    \$0,`$win64?"%rcx":"%rdi"`
    je    .Lprobe
    ud2
.Lprobe:
    ret
.cfi_endproc
.size    $func,.-$func

.align    64
.type    $TABLE,\@object
$TABLE:
    .long    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
    .long    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
    .long    0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
    .long    0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
    .long    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
    .long    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
    .long    0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
    .long    0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
    .long    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
    .long    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
    .long    0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
    .long    0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
    .long    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
    .long    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
    .long    0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
    .long    0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
    .long    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
    .long    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
    .long    0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
    .long    0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
    .long    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
    .long    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
    .long    0xd192e819,0xd6990624,0xf40e3585,0x106aa070
    .long    0xd192e819,0xd6990624,0xf40e3585,0x106aa070
    .long    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
    .long    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
    .long    0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
    .long    0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
    .long    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
    .long    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
    .long    0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
    .long    0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2

    .long    0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
    .long    0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f
    .long    0,0,0,0,   0,0,0,0,   -1,-1,-1,-1
    .long    0,0,0,0,   0,0,0,0
    .asciz    "AESNI-CBC+SHA256 stitch for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
.align    64
___

######################################################################
# SIMD code paths
#
{{{
($iv,$inout,$roundkey,$temp,
 $mask10,$mask12,$mask14,$offload)=map("%xmm$_",(8..15));

$aesni_cbc_idx=0;
@aesni_cbc_block = (
##    &vmovdqu    ($roundkey,"0x00-0x80($inp)");'
##    &vmovdqu    ($inout,($inp));
##    &mov        ($_inp,$inp);

    '&vpxor        ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x10-0x80($inp)");',

    '&vpxor        ($inout,$inout,$iv);',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x20-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x30-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x40-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x50-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x60-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x70-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x80-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x90-0x80($inp)");',

    '&vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0xa0-0x80($inp)");',

    '&vaesenclast    ($temp,$inout,$roundkey);'.
    ' &vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0xb0-0x80($inp)");',

    '&vpand        ($iv,$temp,$mask10);'.
    ' &vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0xc0-0x80($inp)");',

    '&vaesenclast    ($temp,$inout,$roundkey);'.
    ' &vaesenc    ($inout,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0xd0-0x80($inp)");',

    '&vpand        ($temp,$temp,$mask12);'.
    ' &vaesenc    ($inout,$inout,$roundkey);'.
     '&vmovdqu    ($roundkey,"0xe0-0x80($inp)");',

    '&vpor        ($iv,$iv,$temp);'.
    ' &vaesenclast    ($temp,$inout,$roundkey);'.
    ' &vmovdqu    ($roundkey,"0x00-0x80($inp)");'

##    &mov        ($inp,$_inp);
##    &mov        ($out,$_out);
##    &vpand        ($temp,$temp,$mask14);
##    &vpor        ($iv,$iv,$temp);
##    &vmovdqu    ($iv,($out,$inp);
##    &lea        (inp,16($inp));
);

my $a4=$T1;
my ($a,$b,$c,$d,$e,$f,$g,$h);

sub AUTOLOAD()        # thunk [simplified] 32-bit style perlasm
{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
  my $arg = pop;
    $arg = "\$$arg" if ($arg*1 eq $arg);
    $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
}

sub body_00_15 () {
    (
    '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'.

    '&ror    ($a0,$Sigma1[2]-$Sigma1[1])',
    '&mov    ($a,$a1)',
    '&mov    ($a4,$f)',

    '&xor    ($a0,$e)',
    '&ror    ($a1,$Sigma0[2]-$Sigma0[1])',
    '&xor    ($a4,$g)',            # f^g

    '&ror    ($a0,$Sigma1[1]-$Sigma1[0])',
    '&xor    ($a1,$a)',
    '&and    ($a4,$e)',            # (f^g)&e

    @aesni_cbc_block[$aesni_cbc_idx++].
    '&xor    ($a0,$e)',
    '&add    ($h,$SZ*($i&15)."(%rsp)")',    # h+=X[i]+K[i]
    '&mov    ($a2,$a)',

    '&ror    ($a1,$Sigma0[1]-$Sigma0[0])',
    '&xor    ($a4,$g)',            # Ch(e,f,g)=((f^g)&e)^g
    '&xor    ($a2,$b)',            # a^b, b^c in next round

    '&ror    ($a0,$Sigma1[0])',        # Sigma1(e)
    '&add    ($h,$a4)',            # h+=Ch(e,f,g)
    '&and    ($a3,$a2)',            # (b^c)&(a^b)

    '&xor    ($a1,$a)',
    '&add    ($h,$a0)',            # h+=Sigma1(e)
    '&xor    ($a3,$b)',            # Maj(a,b,c)=Ch(a^b,c,b)

    '&add    ($d,$h)',            # d+=h
    '&ror    ($a1,$Sigma0[0])',        # Sigma0(a)
    '&add    ($h,$a3)',            # h+=Maj(a,b,c)

    '&mov    ($a0,$d)',
    '&add    ($a1,$h);'.            # h+=Sigma0(a)
    '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;'
    );
}

if ($avx) {{
######################################################################
# XOP code path
#
$code.=<<___;
.type    ${func}_xop,\@function,6
.align    64
${func}_xop:
.cfi_startproc
.Lxop_shortcut:
    mov    `($win64?56:8)`(%rsp),$in0    # load 7th parameter
    mov    %rsp,%rax        # copy %rsp
.cfi_def_cfa_register    %rax
    push    %rbx
.cfi_push    %rbx
    push    %rbp
.cfi_push    %rbp
    push    %r12
.cfi_push    %r12
    push    %r13
.cfi_push    %r13
    push    %r14
.cfi_push    %r14
    push    %r15
.cfi_push    %r15
    sub    \$`$framesz+$win64*16*10`,%rsp
    and    \$-64,%rsp        # align stack frame

    shl    \$6,$len
    sub    $inp,$out        # re-bias
    sub    $inp,$in0
    add    $inp,$len        # end of input

    #mov    $inp,$_inp        # saved later
    mov    $out,$_out
    mov    $len,$_end
    #mov    $key,$_key        # remains resident in $inp register
    mov    $ivp,$_ivp
    mov    $ctx,$_ctx
    mov    $in0,$_in0
    mov    %rax,$_rsp
.cfi_cfa_expression    $_rsp,deref,+8
___
$code.=<<___ if ($win64);
    movaps    %xmm6,`$framesz+16*0`(%rsp)
    movaps    %xmm7,`$framesz+16*1`(%rsp)
    movaps    %xmm8,`$framesz+16*2`(%rsp)
    movaps    %xmm9,`$framesz+16*3`(%rsp)
    movaps    %xmm10,`$framesz+16*4`(%rsp)
    movaps    %xmm11,`$framesz+16*5`(%rsp)
    movaps    %xmm12,`$framesz+16*6`(%rsp)
    movaps    %xmm13,`$framesz+16*7`(%rsp)
    movaps    %xmm14,`$framesz+16*8`(%rsp)
    movaps    %xmm15,`$framesz+16*9`(%rsp)
___
$code.=<<___;
.Lprologue_xop:
    vzeroall

    mov    $inp,%r12        # borrow $a4
    lea    0x80($key),$inp        # size optimization, reassign
    lea    $TABLE+`$SZ*2*$rounds+32`(%rip),%r13    # borrow $a0
    mov    0xf0-0x80($inp),%r14d    # rounds, borrow $a1
    mov    $ctx,%r15        # borrow $a2
    mov    $in0,%rsi        # borrow $a3
    vmovdqu    ($ivp),$iv        # load IV
    sub    \$9,%r14

    mov    $SZ*0(%r15),$A
    mov    $SZ*1(%r15),$B
    mov    $SZ*2(%r15),$C
    mov    $SZ*3(%r15),$D
    mov    $SZ*4(%r15),$E
    mov    $SZ*5(%r15),$F
    mov    $SZ*6(%r15),$G
    mov    $SZ*7(%r15),$H

    vmovdqa    0x00(%r13,%r14,8),$mask14
    vmovdqa    0x10(%r13,%r14,8),$mask12
    vmovdqa    0x20(%r13,%r14,8),$mask10
    vmovdqu    0x00-0x80($inp),$roundkey
    jmp    .Lloop_xop
___
                    if ($SZ==4) {    # SHA256
    my @X = map("%xmm$_",(0..3));
    my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7));

$code.=<<___;
.align    16
.Lloop_xop:
    vmovdqa    $TABLE+`$SZ*2*$rounds`(%rip),$t3
    vmovdqu    0x00(%rsi,%r12),@X[0]
    vmovdqu    0x10(%rsi,%r12),@X[1]
    vmovdqu    0x20(%rsi,%r12),@X[2]
    vmovdqu    0x30(%rsi,%r12),@X[3]
    vpshufb    $t3,@X[0],@X[0]
    lea    $TABLE(%rip),$Tbl
    vpshufb    $t3,@X[1],@X[1]
    vpshufb    $t3,@X[2],@X[2]
    vpaddd    0x00($Tbl),@X[0],$t0
    vpshufb    $t3,@X[3],@X[3]
    vpaddd    0x20($Tbl),@X[1],$t1
    vpaddd    0x40($Tbl),@X[2],$t2
    vpaddd    0x60($Tbl),@X[3],$t3
    vmovdqa    $t0,0x00(%rsp)
    mov    $A,$a1
    vmovdqa    $t1,0x10(%rsp)
    mov    $B,$a3
    vmovdqa    $t2,0x20(%rsp)
    xor    $C,$a3            # magic
    vmovdqa    $t3,0x30(%rsp)
    mov    $E,$a0
    jmp    .Lxop_00_47

.align    16
.Lxop_00_47:
    sub    \$-16*2*$SZ,$Tbl    # size optimization
    vmovdqu    (%r12),$inout        # $a4
    mov    %r12,$_inp        # $a4
___
sub XOP_256_00_47 () {
my $j = shift;
my $body = shift;
my @X = @_;
my @insns = (&$body,&$body,&$body,&$body);    # 104 instructions

    &vpalignr    ($t0,@X[1],@X[0],$SZ);    # X[1..4]
      eval(shift(@insns));
      eval(shift(@insns));
     &vpalignr    ($t3,@X[3],@X[2],$SZ);    # X[9..12]
      eval(shift(@insns));
      eval(shift(@insns));
    &vprotd        ($t1,$t0,8*$SZ-$sigma0[1]);
      eval(shift(@insns));
      eval(shift(@insns));
    &vpsrld        ($t0,$t0,$sigma0[2]);
      eval(shift(@insns));
      eval(shift(@insns));
     &vpaddd    (@X[0],@X[0],$t3);    # X[0..3] += X[9..12]
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
    &vprotd        ($t2,$t1,$sigma0[1]-$sigma0[0]);
      eval(shift(@insns));
      eval(shift(@insns));
    &vpxor        ($t0,$t0,$t1);
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
     &vprotd    ($t3,@X[3],8*$SZ-$sigma1[1]);
      eval(shift(@insns));
      eval(shift(@insns));
    &vpxor        ($t0,$t0,$t2);        # sigma0(X[1..4])
      eval(shift(@insns));
      eval(shift(@insns));
     &vpsrld    ($t2,@X[3],$sigma1[2]);
      eval(shift(@insns));
      eval(shift(@insns));
    &vpaddd        (@X[0],@X[0],$t0);    # X[0..3] += sigma0(X[1..4])
      eval(shift(@insns));
      eval(shift(@insns));
     &vprotd    ($t1,$t3,$sigma1[1]-$sigma1[0]);
      eval(shift(@insns));
      eval(shift(@insns));
     &vpxor        ($t3,$t3,$t2);
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
     &vpxor        ($t3,$t3,$t1);        # sigma1(X[14..15])
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
    &vpsrldq    ($t3,$t3,8);
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
    &vpaddd        (@X[0],@X[0],$t3);    # X[0..1] += sigma1(X[14..15])
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
     &vprotd    ($t3,@X[0],8*$SZ-$sigma1[1]);
      eval(shift(@insns));
      eval(shift(@insns));
     &vpsrld    ($t2,@X[0],$sigma1[2]);
      eval(shift(@insns));
      eval(shift(@insns));
     &vprotd    ($t1,$t3,$sigma1[1]-$sigma1[0]);
      eval(shift(@insns));
      eval(shift(@insns));
     &vpxor        ($t3,$t3,$t2);
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
     &vpxor        ($t3,$t3,$t1);        # sigma1(X[16..17])
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
    &vpslldq    ($t3,$t3,8);        # 22 instructions
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
    &vpaddd        (@X[0],@X[0],$t3);    # X[2..3] += sigma1(X[16..17])
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
      eval(shift(@insns));
    &vpaddd        ($t2,@X[0],16*2*$j."($Tbl)");
      foreach (@insns) { eval; }        # remaining instructions
    &vmovdqa    (16*$j."(%rsp)",$t2);
}

    $aesni_cbc_idx=0;
    for ($i=0,$j=0; $j<4; $j++) {
    &XOP_256_00_47($j,\&body_00_15,@X);
    push(@X,shift(@X));            # rotate(@X)
    }
        &mov        ("%r12",$_inp);        # borrow $a4
    &vpand        ($temp,$temp,$mask14);
    &mov        ("%r15",$_out);        # borrow $a2
    &vpor        ($iv,$iv,$temp);
    &vmovdqu    ("(%r15,%r12)",$iv);    # write output
    &lea        ("%r12","16(%r12)");    # inp++

    &cmpb    ($SZ-1+16*2*$SZ."($Tbl)",0);
    &jne    (".Lxop_00_47");

    &vmovdqu    ($inout,"(%r12)");
    &mov        ($_inp,"%r12");

    $aesni_cbc_idx=0;
    for ($i=0; $i<16; ) {
    foreach(body_00_15()) { eval; }
    }
                    }
$code.=<<___;
    mov    $_inp,%r12        # borrow $a4
    mov    $_out,%r13        # borrow $a0
    mov    $_ctx,%r15        # borrow $a2
    mov    $_in0,%rsi        # borrow $a3

    vpand    $mask14,$temp,$temp
    mov    $a1,$A
    vpor    $temp,$iv,$iv
    vmovdqu    $iv,(%r13,%r12)        # write output
    lea    16(%r12),%r12        # inp++

    add    $SZ*0(%r15),$A
    add    $SZ*1(%r15),$B
    add    $SZ*2(%r15),$C
    add    $SZ*3(%r15),$D
    add    $SZ*4(%r15),$E
    add    $SZ*5(%r15),$F
    add    $SZ*6(%r15),$G
    add    $SZ*7(%r15),$H

    cmp    $_end,%r12

    mov    $A,$SZ*0(%r15)
    mov    $B,$SZ*1(%r15)
    mov    $C,$SZ*2(%r15)
    mov    $D,$SZ*3(%r15)
    mov    $E,$SZ*4(%r15)
    mov    $F,$SZ*5(%r15)
    mov    $G,$SZ*6(%r15)
    mov    $H,$SZ*7(%r15)

    jb    .Lloop_xop

    mov    $_ivp,$ivp
    mov    $_rsp,%rsi
.cfi_def_cfa    %rsi,8
    vmovdqu    $iv,($ivp)        # output IV
    vzeroall
___
$code.=<<___ if ($win64);
    movaps    `$framesz+16*0`(%rsp),%xmm6
    movaps    `$framesz+16*1`(%rsp),%xmm7
    movaps    `$framesz+16*2`(%rsp),%xmm8
    movaps    `$framesz+16*3`(%rsp),%xmm9
    movaps    `$framesz+16*4`(%rsp),%xmm10
    movaps    `$framesz+16*5`(%rsp),%xmm11
    movaps    `$framesz+16*6`(%rsp),%xmm12
    movaps    `$framesz+16*7`(%rsp),%xmm13
    movaps    `$framesz+16*8`(%rsp),%xmm14
    movaps    `$framesz+16*9`(%rsp),%xmm15
___
$code.=<<___;
    mov    -48(%rsi),%r15
.cfi_restore    %r15
    mov    -40(%rsi),%r14
.cfi_restore    %r14
    mov    -32(%rsi),%r13
.cfi_restore    %r13
    mov    -24(%rsi),%r12
.cfi_restore    %r12
    mov    -16(%rsi),%rbp
.cfi_restore    %rbp
    mov    -8(%rsi),%rbx
.cfi_restore    %rbx
    lea    (%rsi),%rsp
.cfi_def_cfa_register    %rsp
.Lepilogue_xop:
    ret
.cfi_endproc
.size    ${func}_xop,.-${func}_xop
___
######################################################################
# AVX+shrd code path
#
local *ror = sub { &shrd(@_[0],@_) };

$code.=<<___;
.type    ${func}_avx,\@function,6
.align    64
${func}_avx:
.cfi_startproc
.Lavx_shortcut:
    mov    `($win64?56:8)`(%rsp),$in0    # load 7th parameter
    mov    %rsp,%rax        # copy %rsp
.cfi_def_cfa_register    %rax
    push    %rbx
.cfi_push    %rbx
    push    %rbp
.cfi_push    %rbp
    push    %r12
.cfi_push    %r12
    push    %r13
.cfi_push    %r13
    push    %r14
.cfi_push    %r14
    push    %r15
.cfi_push    %r15
    sub    \$`$framesz+$win64*16*10`,%rsp
    and    \$-64,%rsp        # align stack frame

    shl    \$6,$len
    sub    $inp,$out        # re-bias
    sub    $inp,$in0
    add    $inp,$len        # end of input

    #mov    $inp,$_inp        # saved later
    mov    $out,$_out
    mov    $len,$_end
    #mov    $key,$_key        # remains resident in $inp register
    mov    $ivp,$_ivp
    mov    $ctx,$_ctx
    mov    $in0,$_in0
    mov    %rax,$_rsp
.cfi_cfa_expression    $_rsp,deref,+8
___
$code.=<<___ if ($win64);
    movaps    %xmm6,`$framesz+16*0`(%rsp)
    movaps    %xmm7,`$framesz+16*1`(%rsp)
    movaps    %xmm8,`$framesz+16*2`(%rsp)
    movaps    %xmm9,`$framesz+16*3`(%rsp)
    movaps    %xmm10,`$framesz+16*4`(%rsp)
    movaps    %xmm11,`$framesz+16*5`(%rsp)
    movaps    %xmm12,`$framesz+16*6`(%rsp)
    movaps    %xmm13,`$framesz+16*7`(%rsp)
    movaps    %xmm14,`$framesz+16*8`(%rsp)
    movaps    %xmm15,`$framesz+16*9`(%rsp)
___
$code.=<<___;
.Lprologue_avx:
    vzeroall

    mov    $inp,%r12        # borrow $a4
    lea    0x80($key),$inp        # size optimization, reassign
    lea    $TABLE+`$SZ*2*$rounds+32`(%rip),%r13    # borrow $a0
    mov    0xf0-0x80($inp),%r14d    # rounds, borrow $a1
    mov    $ctx,%r15        # borrow $a2
    mov    $in0,%rsi        # borrow $a3
    vmovdqu    ($ivp),$iv        # load IV
    sub    \$9,%r14

    mov    $SZ*0(%r15),$A
    mov    $SZ*1(%r15),$B
    mov    $SZ*2(%r15),$C
    mov    $SZ*3(%r15),$D
    mov    $SZ*4(%r15),$E
    mov    $SZ*5(%r15),$F
    mov    $SZ*6(%r15),$G
    mov    $SZ*7(%r15),$H

    vmovdqa    0x00(%r13,%r14,8),$mask14
    vmovdqa    0x10(%r13,%r14,8),$mask12
    vmovdqa    0x20(%r13,%r14,8),$mask10
    vmovdqu    0x00-0x80($inp),$roundkey
___
                    if ($SZ==4) {    # SHA256
    my @X = map("%xmm$_",(0..3));
    my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7));

$code.=<<___;
    jmp    .Lloop_avx
.align    16
.Lloop_avx:
    vmovdqa    $TABLE+`$SZ*2*$rounds`(%rip),$t3
    vmovdqu    0x00(%rsi,%r12),@X[0]
    vmovdqu    0x10(%rsi,%r12),@X[1]
    vmovdqu    0x20(%rsi,%r12),@X[2]
    vmovdqu    0x30(%rsi,%r12),@X[3]
    vpshufb    $t3,@X[0],@X[0]
    lea    $TABLE(%rip),$Tbl
    vpshufb    $t3,@X[1],@X[1]
    vpshufb    $t3,@X[2],@X[2]
    vpaddd    0x00($Tbl),@X[0],$t0
    vpshufb    $t3,@X[3],@X[3]
    vpaddd    0x20($Tbl),@X[1],$t1
    vpaddd    0x40($Tbl),@X[2],$t2
    vpaddd    0x60($Tbl),@X[3],$t3
    vmovdqa    $t0,0x00(%rsp)
    mov    $A,$a1
    vmovdqa    $t1,0x10(%rsp)
    mov    $B,$a3
    vmovdqa    $t2,0x20(%rsp)
    xor    $C,$a3            # magic
    vmovdqa    $t3,0x30(%rsp)
    mov    $E,$a0
    jmp    .Lavx_00_47

.align    16
.Lavx_00_47:
    sub    \$-16*2*$SZ,$Tbl    # size optimization
    vmovdqu    (%r12),$inout        # $a4
    mov    %r12,$_inp        # $a4
___
sub Xupdate_256_AVX () {
    (
    '&vpalignr    ($t0,@X[1],@X[0],$SZ)',    # X[1..4]
     '&vpalignr    ($t3,@X[3],@X[2],$SZ)',    # X[9..12]
    '&vpsrld    ($t2,$t0,$sigma0[0]);',
     '&vpaddd    (@X[0],@X[0],$t3)',    # X[0..3] += X[9..12]
    '&vpsrld    ($t3,$t0,$sigma0[2])',
    '&vpslld    ($t1,$t0,8*$SZ-$sigma0[1]);',
    '&vpxor        ($t0,$t3,$t2)',
     '&vpshufd    ($t3,@X[3],0b11111010)',# X[14..15]
    '&vpsrld    ($t2,$t2,$sigma0[1]-$sigma0[0]);',
    '&vpxor        ($t0,$t0,$t1)',
    '&vpslld    ($t1,$t1,$sigma0[1]-$sigma0[0]);',
    '&vpxor        ($t0,$t0,$t2)',
     '&vpsrld    ($t2,$t3,$sigma1[2]);',
    '&vpxor        ($t0,$t0,$t1)',        # sigma0(X[1..4])
     '&vpsrlq    ($t3,$t3,$sigma1[0]);',
    '&vpaddd    (@X[0],@X[0],$t0)',    # X[0..3] += sigma0(X[1..4])
     '&vpxor    ($t2,$t2,$t3);',
     '&vpsrlq    ($t3,$t3,$sigma1[1]-$sigma1[0])',
     '&vpxor    ($t2,$t2,$t3)',        # sigma1(X[14..15])
     '&vpshufd    ($t2,$t2,0b10000100)',
     '&vpsrldq    ($t2,$t2,8)',
    '&vpaddd    (@X[0],@X[0],$t2)',    # X[0..1] += sigma1(X[14..15])
     '&vpshufd    ($t3,@X[0],0b01010000)',# X[16..17]
     '&vpsrld    ($t2,$t3,$sigma1[2])',
     '&vpsrlq    ($t3,$t3,$sigma1[0])',
     '&vpxor    ($t2,$t2,$t3);',
     '&vpsrlq    ($t3,$t3,$sigma1[1]-$sigma1[0])',
     '&vpxor    ($t2,$t2,$t3)',
     '&vpshufd    ($t2,$t2,0b11101000)',
     '&vpslldq    ($t2,$t2,8)',
    '&vpaddd    (@X[0],@X[0],$t2)'    # X[2..3] += sigma1(X[16..17])
    );
}

sub AVX_256_00_47 () {
my $j = shift;
my $body = shift;
my @X = @_;
my @insns = (&$body,&$body,&$body,&$body);    # 104 instructions

    foreach (Xupdate_256_AVX()) {        # 29 instructions
        eval;
        eval(shift(@insns));
        eval(shift(@insns));
        eval(shift(@insns));
    }
    &vpaddd        ($t2,@X[0],16*2*$j."($Tbl)");
      foreach (@insns) { eval; }        # remaining instructions
    &vmovdqa    (16*$j."(%rsp)",$t2);
}

    $aesni_cbc_idx=0;
    for ($i=0,$j=0; $j<4; $j++) {
    &AVX_256_00_47($j,\&body_00_15,@X);
    push(@X,shift(@X));            # rotate(@X)
    }
        &mov        ("%r12",$_inp);        # borrow $a4
    &vpand        ($temp,$temp,$mask14);
    &mov        ("%r15",$_out);        # borrow $a2
    &vpor        ($iv,$iv,$temp);
    &vmovdqu    ("(%r15,%r12)",$iv);    # write output
    &lea        ("%r12","16(%r12)");    # inp++

    &cmpb    ($SZ-1+16*2*$SZ."($Tbl)",0);
    &jne    (".Lavx_00_47");

    &vmovdqu    ($inout,"(%r12)");
    &mov        ($_inp,"%r12");

    $aesni_cbc_idx=0;
    for ($i=0; $i<16; ) {
    foreach(body_00_15()) { eval; }
    }

                    }
$code.=<<___;
    mov    $_inp,%r12        # borrow $a4
    mov    $_out,%r13        # borrow $a0
    mov    $_ctx,%r15        # borrow $a2
    mov    $_in0,%rsi        # borrow $a3

    vpand    $mask14,$temp,$temp
    mov    $a1,$A
    vpor    $temp,$iv,$iv
    vmovdqu    $iv,(%r13,%r12)        # write output
    lea    16(%r12),%r12        # inp++

    add    $SZ*0(%r15),$A
    add    $SZ*1(%r15),$B
    add    $SZ*2(%r15),$C
    add    $SZ*3(%r15),$D
    add    $SZ*4(%r15),$E
    add    $SZ*5(%r15),$F
    add    $SZ*6(%r15),$G
    add    $SZ*7(%r15),$H

    cmp    $_end,%r12

    mov    $A,$SZ*0(%r15)
    mov    $B,$SZ*1(%r15)
    mov    $C,$SZ*2(%r15)
    mov    $D,$SZ*3(%r15)
    mov    $E,$SZ*4(%r15)
    mov    $F,$SZ*5(%r15)
    mov    $G,$SZ*6(%r15)
    mov    $H,$SZ*7(%r15)
    jb    .Lloop_avx

    mov    $_ivp,$ivp
    mov    $_rsp,%rsi
.cfi_def_cfa    %rsi,8
    vmovdqu    $iv,($ivp)        # output IV
    vzeroall
___
$code.=<<___ if ($win64);
    movaps    `$framesz+16*0`(%rsp),%xmm6
    movaps    `$framesz+16*1`(%rsp),%xmm7
    movaps    `$framesz+16*2`(%rsp),%xmm8
    movaps    `$framesz+16*3`(%rsp),%xmm9
    movaps    `$framesz+16*4`(%rsp),%xmm10
    movaps    `$framesz+16*5`(%rsp),%xmm11
    movaps    `$framesz+16*6`(%rsp),%xmm12
    movaps    `$framesz+16*7`(%rsp),%xmm13
    movaps    `$framesz+16*8`(%rsp),%xmm14
    movaps    `$framesz+16*9`(%rsp),%xmm15
___
$code.=<<___;
    mov    -48(%rsi),%r15
.cfi_restore    %r15
    mov    -40(%rsi),%r14
.cfi_restore    %r14
    mov    -32(%rsi),%r13
.cfi_restore    %r13
    mov    -24(%rsi),%r12
.cfi_restore    %r12
    mov    -16(%rsi),%rbp
.cfi_restore    %rbp
    mov    -8(%rsi),%rbx
.cfi_restore    %rbx
    lea    (%rsi),%rsp
.cfi_def_cfa_register    %rsp
.Lepilogue_avx:
    ret
.cfi_endproc
.size    ${func}_avx,.-${func}_avx
___

if ($avx>1) {{
######################################################################
# AVX2+BMI code path
#
my $a5=$SZ==4?"%esi":"%rsi";    # zap $inp
my $PUSH8=8*2*$SZ;
use integer;

sub bodyx_00_15 () {
    # at start $a1 should be zero, $a3 - $b^$c and $a4 copy of $f
    (
    '($a,$b,$c,$d,$e,$f,$g,$h)=@ROT;'.

    '&add    ($h,(32*($i/(16/$SZ))+$SZ*($i%(16/$SZ)))%$PUSH8.$base)',    # h+=X[i]+K[i]
    '&and    ($a4,$e)',        # f&e
    '&rorx    ($a0,$e,$Sigma1[2])',
    '&rorx    ($a2,$e,$Sigma1[1])',

    '&lea    ($a,"($a,$a1)")',    # h+=Sigma0(a) from the past
    '&lea    ($h,"($h,$a4)")',
    '&andn    ($a4,$e,$g)',        # ~e&g
    '&xor    ($a0,$a2)',

    '&rorx    ($a1,$e,$Sigma1[0])',
    '&lea    ($h,"($h,$a4)")',    # h+=Ch(e,f,g)=(e&f)+(~e&g)
    '&xor    ($a0,$a1)',        # Sigma1(e)
    '&mov    ($a2,$a)',

    '&rorx    ($a4,$a,$Sigma0[2])',
    '&lea    ($h,"($h,$a0)")',    # h+=Sigma1(e)
    '&xor    ($a2,$b)',        # a^b, b^c in next round
    '&rorx    ($a1,$a,$Sigma0[1])',

    '&rorx    ($a0,$a,$Sigma0[0])',
    '&lea    ($d,"($d,$h)")',    # d+=h
    '&and    ($a3,$a2)',        # (b^c)&(a^b)
    @aesni_cbc_block[$aesni_cbc_idx++].
    '&xor    ($a1,$a4)',

    '&xor    ($a3,$b)',        # Maj(a,b,c)=Ch(a^b,c,b)
    '&xor    ($a1,$a0)',        # Sigma0(a)
    '&lea    ($h,"($h,$a3)");'.    # h+=Maj(a,b,c)
    '&mov    ($a4,$e)',        # copy of f in future

    '($a2,$a3) = ($a3,$a2); unshift(@ROT,pop(@ROT)); $i++;'
    );
    # and at the finish one has to $a+=$a1
}

$code.=<<___;
.type    ${func}_avx2,\@function,6
.align    64
${func}_avx2:
.cfi_startproc
.Lavx2_shortcut:
    mov    `($win64?56:8)`(%rsp),$in0    # load 7th parameter
    mov    %rsp,%rax        # copy %rsp
.cfi_def_cfa_register    %rax
    push    %rbx
.cfi_push    %rbx
    push    %rbp
.cfi_push    %rbp
    push    %r12
.cfi_push    %r12
    push    %r13
.cfi_push    %r13
    push    %r14
.cfi_push    %r14
    push    %r15
.cfi_push    %r15
    sub    \$`2*$SZ*$rounds+8*8+$win64*16*10`,%rsp
    and    \$-256*$SZ,%rsp        # align stack frame
    add    \$`2*$SZ*($rounds-8)`,%rsp

    shl    \$6,$len
    sub    $inp,$out        # re-bias
    sub    $inp,$in0
    add    $inp,$len        # end of input

    #mov    $inp,$_inp        # saved later
    #mov    $out,$_out        # kept in $offload
    mov    $len,$_end
    #mov    $key,$_key        # remains resident in $inp register
    mov    $ivp,$_ivp
    mov    $ctx,$_ctx
    mov    $in0,$_in0
    mov    %rax,$_rsp
.cfi_cfa_expression    $_rsp,deref,+8
___
$code.=<<___ if ($win64);
    movaps    %xmm6,`$framesz+16*0`(%rsp)
    movaps    %xmm7,`$framesz+16*1`(%rsp)
    movaps    %xmm8,`$framesz+16*2`(%rsp)
    movaps    %xmm9,`$framesz+16*3`(%rsp)
    movaps    %xmm10,`$framesz+16*4`(%rsp)
    movaps    %xmm11,`$framesz+16*5`(%rsp)
    movaps    %xmm12,`$framesz+16*6`(%rsp)
    movaps    %xmm13,`$framesz+16*7`(%rsp)
    movaps    %xmm14,`$framesz+16*8`(%rsp)
    movaps    %xmm15,`$framesz+16*9`(%rsp)
___
$code.=<<___;
.Lprologue_avx2:
    vzeroall

    mov    $inp,%r13        # borrow $a0
    vpinsrq    \$1,$out,$offload,$offload
    lea    0x80($key),$inp        # size optimization, reassign
    lea    $TABLE+`$SZ*2*$rounds+32`(%rip),%r12    # borrow $a4
    mov    0xf0-0x80($inp),%r14d    # rounds, borrow $a1
    mov    $ctx,%r15        # borrow $a2
    mov    $in0,%rsi        # borrow $a3
    vmovdqu    ($ivp),$iv        # load IV
    lea    -9(%r14),%r14

    vmovdqa    0x00(%r12,%r14,8),$mask14
    vmovdqa    0x10(%r12,%r14,8),$mask12
    vmovdqa    0x20(%r12,%r14,8),$mask10

    sub    \$-16*$SZ,%r13        # inp++, size optimization
    mov    $SZ*0(%r15),$A
    lea    (%rsi,%r13),%r12    # borrow $a0
    mov    $SZ*1(%r15),$B
    cmp    $len,%r13        # $_end
    mov    $SZ*2(%r15),$C
    cmove    %rsp,%r12        # next block or random data
    mov    $SZ*3(%r15),$D
    mov    $SZ*4(%r15),$E
    mov    $SZ*5(%r15),$F
    mov    $SZ*6(%r15),$G
    mov    $SZ*7(%r15),$H
    vmovdqu    0x00-0x80($inp),$roundkey
___
                    if ($SZ==4) {    # SHA256
    my @X = map("%ymm$_",(0..3));
    my ($t0,$t1,$t2,$t3) = map("%ymm$_",(4..7));

$code.=<<___;
    jmp    .Loop_avx2
.align    16
.Loop_avx2:
    vmovdqa    $TABLE+`$SZ*2*$rounds`(%rip),$t3
    vmovdqu    -16*$SZ+0(%rsi,%r13),%xmm0
    vmovdqu    -16*$SZ+16(%rsi,%r13),%xmm1
    vmovdqu    -16*$SZ+32(%rsi,%r13),%xmm2
    vmovdqu    -16*$SZ+48(%rsi,%r13),%xmm3

    vinserti128    \$1,(%r12),@X[0],@X[0]
    vinserti128    \$1,16(%r12),@X[1],@X[1]
     vpshufb    $t3,@X[0],@X[0]
    vinserti128    \$1,32(%r12),@X[2],@X[2]
     vpshufb    $t3,@X[1],@X[1]
    vinserti128    \$1,48(%r12),@X[3],@X[3]

    lea    $TABLE(%rip),$Tbl
    vpshufb    $t3,@X[2],@X[2]
    lea    -16*$SZ(%r13),%r13
    vpaddd    0x00($Tbl),@X[0],$t0
    vpshufb    $t3,@X[3],@X[3]
    vpaddd    0x20($Tbl),@X[1],$t1
    vpaddd    0x40($Tbl),@X[2],$t2
    vpaddd    0x60($Tbl),@X[3],$t3
    vmovdqa    $t0,0x00(%rsp)
    xor    $a1,$a1
    vmovdqa    $t1,0x20(%rsp)
___
$code.=<<___ if (!$win64);
# temporarily use %rsi as frame pointer
        mov     $_rsp,%rsi
.cfi_def_cfa    %rsi,8
___
$code.=<<___;
    lea    -$PUSH8(%rsp),%rsp
___
$code.=<<___ if (!$win64);
# the frame info is at $_rsp, but the stack is moving...
# so a second frame pointer is saved at -8(%rsp)
# that is in the red zone
        mov     %rsi,-8(%rsp)
.cfi_cfa_expression     %rsp-8,deref,+8
___
$code.=<<___;
    mov    $B,$a3
    vmovdqa    $t2,0x00(%rsp)
    xor    $C,$a3            # magic
    vmovdqa    $t3,0x20(%rsp)
    mov    $F,$a4
    sub    \$-16*2*$SZ,$Tbl    # size optimization
    jmp    .Lavx2_00_47

.align    16
.Lavx2_00_47:
    vmovdqu    (%r13),$inout
    vpinsrq    \$0,%r13,$offload,$offload
___

sub AVX2_256_00_47 () {
my $j = shift;
my $body = shift;
my @X = @_;
my @insns = (&$body,&$body,&$body,&$body);    # 96 instructions
my $base = "+2*$PUSH8(%rsp)";

    if (($j%2)==0) {
    &lea    ("%rsp","-$PUSH8(%rsp)");
$code.=<<___ if (!$win64);
.cfi_cfa_expression     %rsp+`$PUSH8-8`,deref,+8
# copy secondary frame pointer to new location again at -8(%rsp)
        pushq   $PUSH8-8(%rsp)
.cfi_cfa_expression     %rsp,deref,+8
        lea     8(%rsp),%rsp
.cfi_cfa_expression     %rsp-8,deref,+8
___
    }
    foreach (Xupdate_256_AVX()) {        # 29 instructions
        eval;
        eval(shift(@insns));
        eval(shift(@insns));
        eval(shift(@insns));
    }
    &vpaddd        ($t2,@X[0],16*2*$j."($Tbl)");
      foreach (@insns) { eval; }        # remaining instructions
    &vmovdqa    ((32*$j)%$PUSH8."(%rsp)",$t2);
}
    $aesni_cbc_idx=0;
    for ($i=0,$j=0; $j<4; $j++) {
    &AVX2_256_00_47($j,\&bodyx_00_15,@X);
    push(@X,shift(@X));            # rotate(@X)
    }
    &vmovq        ("%r13",$offload);    # borrow $a0
    &vpextrq    ("%r15",$offload,1);    # borrow $a2
    &vpand        ($temp,$temp,$mask14);
    &vpor        ($iv,$iv,$temp);
    &vmovdqu    ("(%r15,%r13)",$iv);    # write output
    &lea        ("%r13","16(%r13)");    # inp++

    &lea    ($Tbl,16*2*$SZ."($Tbl)");
    &cmpb    (($SZ-1)."($Tbl)",0);
    &jne    (".Lavx2_00_47");

    &vmovdqu    ($inout,"(%r13)");
    &vpinsrq    ($offload,$offload,"%r13",0);

    $aesni_cbc_idx=0;
    for ($i=0; $i<16; ) {
    my $base=$i<8?"+$PUSH8(%rsp)":"(%rsp)";
    foreach(bodyx_00_15()) { eval; }
    }
                    }
$code.=<<___;
    vpextrq    \$1,$offload,%r12        # $_out, borrow $a4
    vmovq    $offload,%r13            # $_inp, borrow $a0
    mov    `2*$SZ*$rounds+5*8`(%rsp),%r15    # $_ctx, borrow $a2
    add    $a1,$A
    lea    `2*$SZ*($rounds-8)`(%rsp),$Tbl

    vpand    $mask14,$temp,$temp
    vpor    $temp,$iv,$iv
    vmovdqu    $iv,(%r12,%r13)            # write output
    lea    16(%r13),%r13

    add    $SZ*0(%r15),$A
    add    $SZ*1(%r15),$B
    add    $SZ*2(%r15),$C
    add    $SZ*3(%r15),$D
    add    $SZ*4(%r15),$E
    add    $SZ*5(%r15),$F
    add    $SZ*6(%r15),$G
    add    $SZ*7(%r15),$H

    mov    $A,$SZ*0(%r15)
    mov    $B,$SZ*1(%r15)
    mov    $C,$SZ*2(%r15)
    mov    $D,$SZ*3(%r15)
    mov    $E,$SZ*4(%r15)
    mov    $F,$SZ*5(%r15)
    mov    $G,$SZ*6(%r15)
    mov    $H,$SZ*7(%r15)

    cmp    `$PUSH8+2*8`($Tbl),%r13        # $_end
    je    .Ldone_avx2

    xor    $a1,$a1
    mov    $B,$a3
    mov    $F,$a4
    xor    $C,$a3            # magic
    jmp    .Lower_avx2
.align    16
.Lower_avx2:
    vmovdqu    (%r13),$inout
    vpinsrq    \$0,%r13,$offload,$offload
___
    $aesni_cbc_idx=0;
    for ($i=0; $i<16; ) {
    my $base="+16($Tbl)";
    foreach(bodyx_00_15()) { eval; }
    &lea    ($Tbl,"-$PUSH8($Tbl)")    if ($i==8);
    }
$code.=<<___;
    vmovq    $offload,%r13            # borrow $a0
    vpextrq    \$1,$offload,%r15        # borrow $a2
    vpand    $mask14,$temp,$temp
    vpor    $temp,$iv,$iv
    lea    -$PUSH8($Tbl),$Tbl
    vmovdqu    $iv,(%r15,%r13)            # write output
    lea    16(%r13),%r13            # inp++
    cmp    %rsp,$Tbl
    jae    .Lower_avx2

    mov    `2*$SZ*$rounds+5*8`(%rsp),%r15    # $_ctx, borrow $a2
    lea    16*$SZ(%r13),%r13
    mov    `2*$SZ*$rounds+6*8`(%rsp),%rsi    # $_in0, borrow $a3
    add    $a1,$A
    lea    `2*$SZ*($rounds-8)`(%rsp),%rsp

    add    $SZ*0(%r15),$A
    add    $SZ*1(%r15),$B
    add    $SZ*2(%r15),$C
    add    $SZ*3(%r15),$D
    add    $SZ*4(%r15),$E
    add    $SZ*5(%r15),$F
    add    $SZ*6(%r15),$G
    lea    (%rsi,%r13),%r12
    add    $SZ*7(%r15),$H

    cmp    $_end,%r13

    mov    $A,$SZ*0(%r15)
    cmove    %rsp,%r12        # next block or stale data
    mov    $B,$SZ*1(%r15)
    mov    $C,$SZ*2(%r15)
    mov    $D,$SZ*3(%r15)
    mov    $E,$SZ*4(%r15)
    mov    $F,$SZ*5(%r15)
    mov    $G,$SZ*6(%r15)
    mov    $H,$SZ*7(%r15)

    jbe    .Loop_avx2
    lea    (%rsp),$Tbl
# temporarily use $Tbl as index to $_rsp
# this avoids the need to save a secondary frame pointer at -8(%rsp)
.cfi_cfa_expression     $Tbl+`16*$SZ+7*8`,deref,+8

.Ldone_avx2:
    mov    16*$SZ+4*8($Tbl),$ivp
    mov    16*$SZ+7*8($Tbl),%rsi
.cfi_def_cfa    %rsi,8
    vmovdqu    $iv,($ivp)        # output IV
    vzeroall
___
$code.=<<___ if ($win64);
    movaps    `$framesz+16*0`($Tbl),%xmm6
    movaps    `$framesz+16*1`($Tbl),%xmm7
    movaps    `$framesz+16*2`($Tbl),%xmm8
    movaps    `$framesz+16*3`($Tbl),%xmm9
    movaps    `$framesz+16*4`($Tbl),%xmm10
    movaps    `$framesz+16*5`($Tbl),%xmm11
    movaps    `$framesz+16*6`($Tbl),%xmm12
    movaps    `$framesz+16*7`($Tbl),%xmm13
    movaps    `$framesz+16*8`($Tbl),%xmm14
    movaps    `$framesz+16*9`($Tbl),%xmm15
___
$code.=<<___;
    mov    -48(%rsi),%r15
.cfi_restore    %r15
    mov    -40(%rsi),%r14
.cfi_restore    %r14
    mov    -32(%rsi),%r13
.cfi_restore    %r13
    mov    -24(%rsi),%r12
.cfi_restore    %r12
    mov    -16(%rsi),%rbp
.cfi_restore    %rbp
    mov    -8(%rsi),%rbx
.cfi_restore    %rbx
    lea    (%rsi),%rsp
.cfi_def_cfa_register    %rsp
.Lepilogue_avx2:
    ret
.cfi_endproc
.size    ${func}_avx2,.-${func}_avx2
___
}}
}}
{{
my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");

my ($rounds,$Tbl)=("%r11d","%rbx");

my ($iv,$in,$rndkey0)=map("%xmm$_",(6,14,15));
my @rndkey=("%xmm4","%xmm5");
my $r=0;
my $sn=0;

my ($Wi,$ABEF,$CDGH,$TMP,$BSWAP,$ABEF_SAVE,$CDGH_SAVE)=map("%xmm$_",(0..3,7..9));
my @MSG=map("%xmm$_",(10..13));

my $aesenc=sub {
  use integer;
  my ($n,$k)=($r/10,$r%10);
    if ($k==0) {
      $code.=<<___;
    movups        `16*$n`($in0),$in        # load input
    xorps        $rndkey0,$in
___
      $code.=<<___ if ($n);
    movups        $iv,`16*($n-1)`($out,$in0)    # write output
___
      $code.=<<___;
    xorps        $in,$iv
    movups        `32+16*$k-112`($key),$rndkey[1]
    aesenc        $rndkey[0],$iv
___
    } elsif ($k==9) {
      $sn++;
      $code.=<<___;
    cmp        \$11,$rounds
    jb        .Laesenclast$sn
    movups        `32+16*($k+0)-112`($key),$rndkey[1]
    aesenc        $rndkey[0],$iv
    movups        `32+16*($k+1)-112`($key),$rndkey[0]
    aesenc        $rndkey[1],$iv
    je        .Laesenclast$sn
    movups        `32+16*($k+2)-112`($key),$rndkey[1]
    aesenc        $rndkey[0],$iv
    movups        `32+16*($k+3)-112`($key),$rndkey[0]
    aesenc        $rndkey[1],$iv
.Laesenclast$sn:
    aesenclast    $rndkey[0],$iv
    movups        16-112($key),$rndkey[1]        # forward reference
    nop
___
    } else {
      $code.=<<___;
    movups        `32+16*$k-112`($key),$rndkey[1]
    aesenc        $rndkey[0],$iv
___
    }
    $r++;    unshift(@rndkey,pop(@rndkey));
};

if ($shaext) {
my $Tbl="%rax";

$code.=<<___;
.type    ${func}_shaext,\@function,6
.align    32
${func}_shaext:
.cfi_startproc
    mov    `($win64?56:8)`(%rsp),$inp    # load 7th argument
___
$code.=<<___ if ($win64);
    lea    `-8-10*16`(%rsp),%rsp
    movaps    %xmm6,-8-10*16(%rax)
    movaps    %xmm7,-8-9*16(%rax)
    movaps    %xmm8,-8-8*16(%rax)
    movaps    %xmm9,-8-7*16(%rax)
    movaps    %xmm10,-8-6*16(%rax)
    movaps    %xmm11,-8-5*16(%rax)
    movaps    %xmm12,-8-4*16(%rax)
    movaps    %xmm13,-8-3*16(%rax)
    movaps    %xmm14,-8-2*16(%rax)
    movaps    %xmm15,-8-1*16(%rax)
.Lprologue_shaext:
___
$code.=<<___;
    lea        K256+0x80(%rip),$Tbl
    movdqu        ($ctx),$ABEF        # DCBA
    movdqu        16($ctx),$CDGH        # HGFE
    movdqa        0x200-0x80($Tbl),$TMP    # byte swap mask

    mov        240($key),$rounds
    sub        $in0,$out
    movups        ($key),$rndkey0        # $key[0]
    movups        ($ivp),$iv        # load IV
    movups        16($key),$rndkey[0]    # forward reference
    lea        112($key),$key        # size optimization

    pshufd        \$0x1b,$ABEF,$Wi    # ABCD
    pshufd        \$0xb1,$ABEF,$ABEF    # CDAB
    pshufd        \$0x1b,$CDGH,$CDGH    # EFGH
    movdqa        $TMP,$BSWAP        # offload
    palignr        \$8,$CDGH,$ABEF        # ABEF
    punpcklqdq    $Wi,$CDGH        # CDGH

    jmp    .Loop_shaext

.align    16
.Loop_shaext:
    movdqu        ($inp),@MSG[0]
    movdqu        0x10($inp),@MSG[1]
    movdqu        0x20($inp),@MSG[2]
    pshufb        $TMP,@MSG[0]
    movdqu        0x30($inp),@MSG[3]

    movdqa        0*32-0x80($Tbl),$Wi
    paddd        @MSG[0],$Wi
    pshufb        $TMP,@MSG[1]
    movdqa        $CDGH,$CDGH_SAVE    # offload
    movdqa        $ABEF,$ABEF_SAVE    # offload
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 0-3
    pshufd        \$0x0e,$Wi,$Wi
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $CDGH,$ABEF

    movdqa        1*32-0x80($Tbl),$Wi
    paddd        @MSG[1],$Wi
    pshufb        $TMP,@MSG[2]
    lea        0x40($inp),$inp
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 4-7
    pshufd        \$0x0e,$Wi,$Wi
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $CDGH,$ABEF

    movdqa        2*32-0x80($Tbl),$Wi
    paddd        @MSG[2],$Wi
    pshufb        $TMP,@MSG[3]
    sha256msg1    @MSG[1],@MSG[0]
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 8-11
    pshufd        \$0x0e,$Wi,$Wi
    movdqa        @MSG[3],$TMP
    palignr        \$4,@MSG[2],$TMP
    paddd        $TMP,@MSG[0]
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $CDGH,$ABEF

    movdqa        3*32-0x80($Tbl),$Wi
    paddd        @MSG[3],$Wi
    sha256msg2    @MSG[3],@MSG[0]
    sha256msg1    @MSG[2],@MSG[1]
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 12-15
    pshufd        \$0x0e,$Wi,$Wi
___
    &$aesenc();
$code.=<<___;
    movdqa        @MSG[0],$TMP
    palignr        \$4,@MSG[3],$TMP
    paddd        $TMP,@MSG[1]
    sha256rnds2    $CDGH,$ABEF
___
for($i=4;$i<16-3;$i++) {
    &$aesenc()    if (($r%10)==0);
$code.=<<___;
    movdqa        $i*32-0x80($Tbl),$Wi
    paddd        @MSG[0],$Wi
    sha256msg2    @MSG[0],@MSG[1]
    sha256msg1    @MSG[3],@MSG[2]
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 16-19...
    pshufd        \$0x0e,$Wi,$Wi
    movdqa        @MSG[1],$TMP
    palignr        \$4,@MSG[0],$TMP
    paddd        $TMP,@MSG[2]
___
    &$aesenc();
    &$aesenc()    if ($r==19);
$code.=<<___;
    sha256rnds2    $CDGH,$ABEF
___
    push(@MSG,shift(@MSG));
}
$code.=<<___;
    movdqa        13*32-0x80($Tbl),$Wi
    paddd        @MSG[0],$Wi
    sha256msg2    @MSG[0],@MSG[1]
    sha256msg1    @MSG[3],@MSG[2]
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 52-55
    pshufd        \$0x0e,$Wi,$Wi
    movdqa        @MSG[1],$TMP
    palignr        \$4,@MSG[0],$TMP
    paddd        $TMP,@MSG[2]
___
    &$aesenc();
    &$aesenc();
$code.=<<___;
    sha256rnds2    $CDGH,$ABEF

    movdqa        14*32-0x80($Tbl),$Wi
    paddd        @MSG[1],$Wi
    sha256msg2    @MSG[1],@MSG[2]
    movdqa        $BSWAP,$TMP
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 56-59
    pshufd        \$0x0e,$Wi,$Wi
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $CDGH,$ABEF

    movdqa        15*32-0x80($Tbl),$Wi
    paddd        @MSG[2],$Wi
___
    &$aesenc();
    &$aesenc();
$code.=<<___;
    sha256rnds2    $ABEF,$CDGH        # 60-63
    pshufd        \$0x0e,$Wi,$Wi
___
    &$aesenc();
$code.=<<___;
    sha256rnds2    $CDGH,$ABEF
    #pxor        $CDGH,$rndkey0        # black magic
___
    while ($r<40)    { &$aesenc(); }        # remaining aesenc's
$code.=<<___;
    #xorps        $CDGH,$rndkey0        # black magic
    paddd        $CDGH_SAVE,$CDGH
    paddd        $ABEF_SAVE,$ABEF

    dec        $len
    movups        $iv,48($out,$in0)    # write output
    lea        64($in0),$in0
    jnz        .Loop_shaext

    pshufd        \$0xb1,$CDGH,$CDGH    # DCHG
    pshufd        \$0x1b,$ABEF,$TMP    # FEBA
    pshufd        \$0xb1,$ABEF,$ABEF    # BAFE
    punpckhqdq    $CDGH,$ABEF        # DCBA
    palignr        \$8,$TMP,$CDGH        # HGFE

    movups        $iv,($ivp)        # write IV
    movdqu        $ABEF,($ctx)
    movdqu        $CDGH,16($ctx)
___
$code.=<<___ if ($win64);
    movaps    0*16(%rsp),%xmm6
    movaps    1*16(%rsp),%xmm7
    movaps    2*16(%rsp),%xmm8
    movaps    3*16(%rsp),%xmm9
    movaps    4*16(%rsp),%xmm10
    movaps    5*16(%rsp),%xmm11
    movaps    6*16(%rsp),%xmm12
    movaps    7*16(%rsp),%xmm13
    movaps    8*16(%rsp),%xmm14
    movaps    9*16(%rsp),%xmm15
    lea    8+10*16(%rsp),%rsp
.Lepilogue_shaext:
___
$code.=<<___;
    ret
.cfi_endproc
.size    ${func}_shaext,.-${func}_shaext
___
}
}}}}}

# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
#        CONTEXT *context,DISPATCHER_CONTEXT *disp)
if ($win64 && $avx) {
$rec="%rcx";
$frame="%rdx";
$context="%r8";
$disp="%r9";

$code.=<<___;
.extern    __imp_RtlVirtualUnwind
.type    se_handler,\@abi-omnipotent
.align    16
se_handler:
    push    %rsi
    push    %rdi
    push    %rbx
    push    %rbp
    push    %r12
    push    %r13
    push    %r14
    push    %r15
    pushfq
    sub    \$64,%rsp

    mov    120($context),%rax    # pull context->Rax
    mov    248($context),%rbx    # pull context->Rip

    mov    8($disp),%rsi        # disp->ImageBase
    mov    56($disp),%r11        # disp->HanderlData

    mov    0(%r11),%r10d        # HandlerData[0]
    lea    (%rsi,%r10),%r10    # prologue label
    cmp    %r10,%rbx        # context->Rip<prologue label
    jb    .Lin_prologue

    mov    152($context),%rax    # pull context->Rsp

    mov    4(%r11),%r10d        # HandlerData[1]
    lea    (%rsi,%r10),%r10    # epilogue label
    cmp    %r10,%rbx        # context->Rip>=epilogue label
    jae    .Lin_prologue
___
$code.=<<___ if ($shaext);
    lea    aesni_cbc_sha256_enc_shaext(%rip),%r10
    cmp    %r10,%rbx
    jb    .Lnot_in_shaext

    lea    (%rax),%rsi
    lea    512($context),%rdi    # &context.Xmm6
    mov    \$20,%ecx
    .long    0xa548f3fc        # cld; rep movsq
    lea    168(%rax),%rax        # adjust stack pointer
    jmp    .Lin_prologue
.Lnot_in_shaext:
___
$code.=<<___ if ($avx>1);
    lea    .Lavx2_shortcut(%rip),%r10
    cmp    %r10,%rbx        # context->Rip<avx2_shortcut
    jb    .Lnot_in_avx2

    and    \$-256*$SZ,%rax
    add    \$`2*$SZ*($rounds-8)`,%rax
.Lnot_in_avx2:
___
$code.=<<___;
    mov    %rax,%rsi        # put aside Rsp
    mov    16*$SZ+7*8(%rax),%rax    # pull $_rsp

    mov    -8(%rax),%rbx
    mov    -16(%rax),%rbp
    mov    -24(%rax),%r12
    mov    -32(%rax),%r13
    mov    -40(%rax),%r14
    mov    -48(%rax),%r15
    mov    %rbx,144($context)    # restore context->Rbx
    mov    %rbp,160($context)    # restore context->Rbp
    mov    %r12,216($context)    # restore context->R12
    mov    %r13,224($context)    # restore context->R13
    mov    %r14,232($context)    # restore context->R14
    mov    %r15,240($context)    # restore context->R15

    lea    16*$SZ+8*8(%rsi),%rsi    # Xmm6- save area
    lea    512($context),%rdi    # &context.Xmm6
    mov    \$20,%ecx
    .long    0xa548f3fc        # cld; rep movsq

.Lin_prologue:
    mov    8(%rax),%rdi
    mov    16(%rax),%rsi
    mov    %rax,152($context)    # restore context->Rsp
    mov    %rsi,168($context)    # restore context->Rsi
    mov    %rdi,176($context)    # restore context->Rdi

    mov    40($disp),%rdi        # disp->ContextRecord
    mov    $context,%rsi        # context
    mov    \$154,%ecx        # sizeof(CONTEXT)
    .long    0xa548f3fc        # cld; rep movsq

    mov    $disp,%rsi
    xor    %rcx,%rcx        # arg1, UNW_FLAG_NHANDLER
    mov    8(%rsi),%rdx        # arg2, disp->ImageBase
    mov    0(%rsi),%r8        # arg3, disp->ControlPc
    mov    16(%rsi),%r9        # arg4, disp->FunctionEntry
    mov    40(%rsi),%r10        # disp->ContextRecord
    lea    56(%rsi),%r11        # &disp->HandlerData
    lea    24(%rsi),%r12        # &disp->EstablisherFrame
    mov    %r10,32(%rsp)        # arg5
    mov    %r11,40(%rsp)        # arg6
    mov    %r12,48(%rsp)        # arg7
    mov    %rcx,56(%rsp)        # arg8, (NULL)
    call    *__imp_RtlVirtualUnwind(%rip)

    mov    \$1,%eax        # ExceptionContinueSearch
    add    \$64,%rsp
    popfq
    pop    %r15
    pop    %r14
    pop    %r13
    pop    %r12
    pop    %rbp
    pop    %rbx
    pop    %rdi
    pop    %rsi
    ret
.size    se_handler,.-se_handler

.section    .pdata
    .rva    .LSEH_begin_${func}_xop
    .rva    .LSEH_end_${func}_xop
    .rva    .LSEH_info_${func}_xop

    .rva    .LSEH_begin_${func}_avx
    .rva    .LSEH_end_${func}_avx
    .rva    .LSEH_info_${func}_avx
___
$code.=<<___ if ($avx>1);
    .rva    .LSEH_begin_${func}_avx2
    .rva    .LSEH_end_${func}_avx2
    .rva    .LSEH_info_${func}_avx2
___
$code.=<<___ if ($shaext);
    .rva    .LSEH_begin_${func}_shaext
    .rva    .LSEH_end_${func}_shaext
    .rva    .LSEH_info_${func}_shaext
___
$code.=<<___;
.section    .xdata
.align    8
.LSEH_info_${func}_xop:
    .byte    9,0,0,0
    .rva    se_handler
    .rva    .Lprologue_xop,.Lepilogue_xop        # HandlerData[]

.LSEH_info_${func}_avx:
    .byte    9,0,0,0
    .rva    se_handler
    .rva    .Lprologue_avx,.Lepilogue_avx        # HandlerData[]
___
$code.=<<___ if ($avx>1);
.LSEH_info_${func}_avx2:
    .byte    9,0,0,0
    .rva    se_handler
    .rva    .Lprologue_avx2,.Lepilogue_avx2        # HandlerData[]
___
$code.=<<___ if ($shaext);
.LSEH_info_${func}_shaext:
    .byte    9,0,0,0
    .rva    se_handler
    .rva    .Lprologue_shaext,.Lepilogue_shaext    # HandlerData[]
___
}

####################################################################
sub rex {
  local *opcode=shift;
  my ($dst,$src)=@_;
  my $rex=0;

    $rex|=0x04            if($dst>=8);
    $rex|=0x01            if($src>=8);
    unshift @opcode,$rex|0x40    if($rex);
}

{
  my %opcodelet = (
        "sha256rnds2" => 0xcb,
          "sha256msg1"  => 0xcc,
        "sha256msg2"  => 0xcd    );

  sub sha256op38 {
    my $instr = shift;

    if (defined($opcodelet{$instr}) && @_[0] =~ /%xmm([0-9]+),\s*%xmm([0-9]+)/) {
      my @opcode=(0x0f,0x38);
    rex(\@opcode,$2,$1);
    push @opcode,$opcodelet{$instr};
    push @opcode,0xc0|($1&7)|(($2&7)<<3);        # ModR/M
    return ".byte\t".join(',',@opcode);
    } else {
    return $instr."\t".@_[0];
    }
  }
}

$code =~ s/\`([^\`]*)\`/eval $1/gem;
$code =~ s/\b(sha256[^\s]*)\s+(.*)/sha256op38($1,$2)/gem;
print $code;
close STDOUT or die "error closing STDOUT: $!";

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.1 [PHP 8 Update] [02.02.2022] maintained byC99Shell Github | Generation time: 0.8362 ]--