// File: /workspace/github_c_makefile_star2_O2/mjosaarinen[P]brutus/crypto_aead/stribob192r2/ssse3/wbob_pissse3.c
// Function: wbob_pi
void wbob_pi(w512_t *s512)
{
    int r;

    __m128i x0, x1, x2, x3;
    __m128i y0, y1, y2, y3;
    __m128i s0_box, s1_box, s2_box;
    __m128i rot0, rot1, rot2, rot3, ileave;
    __m128i mask, zero, poly, *rcon;

    rcon = (__m128i *)RCON;
    s0_box = _mm_load_si128((__m128i*)(SBOXES +  0));
    s1_box = _mm_load_si128((__m128i*)(SBOXES + 16));
    s2_box = _mm_load_si128((__m128i*)(SBOXES + 32));
    rot0 = _mm_load_si128((__m128i*)(CONSTANTS +  0));
    rot1 = _mm_load_si128((__m128i*)(CONSTANTS + 16));
    rot2 = _mm_load_si128((__m128i*)(CONSTANTS + 32));
    rot3 = _mm_load_si128((__m128i*)(CONSTANTS + 48));
    ileave = _mm_load_si128((__m128i*)(CONSTANTS + 64));

    mask = _mm_set1_epi8(0xF);
    poly = _mm_set1_epi8(0x1D);
    zero = _mm_xor_si128(mask,mask);

    y0 = _mm_loadu_si128((__m128i*)(&s512->b[ 0]));
    y1 = _mm_loadu_si128((__m128i*)(&s512->b[16]));
    y2 = _mm_loadu_si128((__m128i*)(&s512->b[32]));
    y3 = _mm_loadu_si128((__m128i*)(&s512->b[48]));

    /* slice going in -- packs two columns per xmm */
    TRANSPOSE(x,y);

    for (r = 0; r < 12; r++) {                      // 12 rounds

        /* SubBytes */
        GAMMA(y0,x0);
        GAMMA(y1,x1);
        GAMMA(y2,x2);
        GAMMA(y3,x3);

        /* ShiftColumns */
        x0 = _mm_shuffle_epi8(y0,rot0);
        x1 = _mm_shuffle_epi8(y1,rot1);
        x2 = _mm_shuffle_epi8(y2,rot2);
        x3 = _mm_shuffle_epi8(y3,rot3);

        /* MixRows */
        __m128i v0,v1,v2,v3,v4,v5,v6,v7;

        /* this basically compensates for the fact that
           we are packing two columns in each xmm but
           need complete diffusion across the rows */
        v4 = _mm_alignr_epi8(x2,x1,8); // 3 4 L H
        v5 = _mm_alignr_epi8(x3,x2,8); // 5 6
        v6 = _mm_alignr_epi8(x0,x3,8); // 7 0
        v7 = _mm_alignr_epi8(x1,x0,8); // 1 2

        v0 = _mm_xor_si128(v4,x3);
        v1 = _mm_xor_si128(v5,x0);
        v2 = _mm_xor_si128(v6,x1);
        v3 = _mm_xor_si128(v7,x2);

        MULX(y0,v3);
        MULX(y1,v0);
        MULX(y2,v1);
        MULX(y3,v2);

        y0 = _mm_xor_si128(y0,v0);
        y1 = _mm_xor_si128(y1,v1);
        y2 = _mm_xor_si128(y2,v2);
        y3 = _mm_xor_si128(y3,v3);

        MULX(y0,y0);
        MULX(y1,y1);
        MULX(y2,y2);
        MULX(y3,y3);

        y0 = _mm_xor_si128(y0,x1);
        y1 = _mm_xor_si128(y1,x2);
        y2 = _mm_xor_si128(y2,x3);
        y3 = _mm_xor_si128(y3,x0);

        MULX(y0,y0);
        MULX(y1,y1);
        MULX(y2,y2);
        MULX(y3,y3);

        y0 = _mm_xor_si128(y0,x0);
        y1 = _mm_xor_si128(y1,x1);
        y2 = _mm_xor_si128(y2,x2);
        y3 = _mm_xor_si128(y3,x3);

        v4 = _mm_xor_si128(v4,v5);
        v6 = _mm_xor_si128(v6,v7);
        v0 = _mm_xor_si128(v4,v6);

        y0 = _mm_xor_si128(y0,v0);
        y1 = _mm_xor_si128(y1,v0);
        y2 = _mm_xor_si128(y2,v0);
        y3 = _mm_xor_si128(y3,v0);

        /* AddRoundKey */
        x0 = _mm_xor_si128(y0,rcon[0]);
        x1 = _mm_xor_si128(y1,rcon[1]);
        x2 = _mm_xor_si128(y2,rcon[2]);
        x3 = _mm_xor_si128(y3,rcon[3]);
        rcon += 4;

        //PRINTSSE(x0,x1,x2,x3);
    }

    /* unslice going out */
    TRANSPOSE(y,x);

    _mm_storeu_si128((__m128i*)(&s512->b[ 0]),y0);
    _mm_storeu_si128((__m128i*)(&s512->b[16]),y1);
    _mm_storeu_si128((__m128i*)(&s512->b[32]),y2);
    _mm_storeu_si128((__m128i*)(&s512->b[48]),y3);
}

// Assembly:
vmovdqu (%rdi), %xmm1
vmovdqu 0x10(%rdi), %xmm2
vmovdqu 0x20(%rdi), %xmm3
vmovdqu 0x30(%rdi), %xmm4
vmovdqa64 0xa13(%rip), %xmm22 # 0x2000
vpshufb %xmm22, %xmm1, %xmm1
vpshufb %xmm22, %xmm2, %xmm2
vpshufb %xmm22, %xmm3, %xmm3
vpshufb %xmm22, %xmm4, %xmm4
vpunpcklwd %xmm2, %xmm1, %xmm5 # xmm5 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
vpunpckhwd %xmm2, %xmm1, %xmm1 # xmm1 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
vpunpcklwd %xmm4, %xmm3, %xmm2 # xmm2 = xmm3[0],xmm4[0],xmm3[1],xmm4[1],xmm3[2],xmm4[2],xmm3[3],xmm4[3]
vpunpckhwd %xmm4, %xmm3, %xmm3 # xmm3 = xmm3[4],xmm4[4],xmm3[5],xmm4[5],xmm3[6],xmm4[6],xmm3[7],xmm4[7]
vpunpckldq %xmm2, %xmm5, %xmm17 # xmm17 = xmm5[0],xmm2[0],xmm5[1],xmm2[1]
vpunpckhdq %xmm2, %xmm5, %xmm16 # xmm16 = xmm5[2],xmm2[2],xmm5[3],xmm2[3]
vpunpckldq %xmm3, %xmm1, %xmm14 # xmm14 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
vpunpckhdq %xmm3, %xmm1, %xmm12 # xmm12 = xmm1[2],xmm3[2],xmm1[3],xmm3[3]
xorl %eax, %eax
vpbroadcastb 0xa4b(%rip), %xmm30 # 0x2080
vmovdqa 0x9d3(%rip), %xmm2      # 0x2010
vmovdqa 0x9db(%rip), %xmm3      # 0x2020
vmovdqa64 0x9e1(%rip), %xmm27 # 0x2030
vmovdqa64 0x9e7(%rip), %xmm23 # 0x2040
vmovdqa64 0x9ed(%rip), %xmm24 # 0x2050
vmovdqa64 0x9f3(%rip), %xmm25 # 0x2060
vmovdqa64 0x9f9(%rip), %xmm26 # 0x2070
vpxor %xmm9, %xmm9, %xmm9
vpbroadcastq 0xe0b(%rip), %xmm10 # 0x2490
vpbroadcastb 0x9f2(%rip), %xmm28 # 0x2081
leaq 0x9fa(%rip), %rcx       # 0x2090
cmpl $0x300, %eax            # imm = 0x300
je 0x1978
vpsrlq $0x4, %xmm17, %xmm13
vpandq %xmm30, %xmm17, %xmm15
vpshufb %xmm15, %xmm2, %xmm15
vpandq %xmm30, %xmm13, %xmm13
vpshufb %xmm13, %xmm3, %xmm13
vpxorq %xmm15, %xmm13, %xmm17
vpshufb %xmm17, %xmm27, %xmm17
vpxorq %xmm15, %xmm17, %xmm15
vpxorq %xmm13, %xmm17, %xmm13
vpshufb %xmm15, %xmm2, %xmm15
vpshufb %xmm13, %xmm3, %xmm13
vpsllq $0x4, %xmm13, %xmm13
vporq %xmm13, %xmm15, %xmm17
vpsrlq $0x4, %xmm16, %xmm13
vpandq %xmm30, %xmm16, %xmm15
vpshufb %xmm15, %xmm2, %xmm15
vpandq %xmm30, %xmm13, %xmm13
vpshufb %xmm13, %xmm3, %xmm13
vpxorq %xmm15, %xmm13, %xmm16
vpshufb %xmm16, %xmm27, %xmm16
vpxorq %xmm15, %xmm16, %xmm15
vpxorq %xmm13, %xmm16, %xmm13
vpshufb %xmm15, %xmm2, %xmm16
vpshufb %xmm13, %xmm3, %xmm13
vpsllq $0x4, %xmm13, %xmm13
vpsrlq $0x4, %xmm14, %xmm15
vpandq %xmm30, %xmm14, %xmm14
vpshufb %xmm14, %xmm2, %xmm14
vpandq %xmm30, %xmm15, %xmm15
vpshufb %xmm15, %xmm3, %xmm15
vpxorq %xmm14, %xmm15, %xmm18
vpshufb %xmm18, %xmm27, %xmm18
vpxorq %xmm14, %xmm18, %xmm14
vpxorq %xmm15, %xmm18, %xmm15
vpshufb %xmm14, %xmm2, %xmm18
vpshufb %xmm15, %xmm3, %xmm14
vpsllq $0x4, %xmm14, %xmm19
vpsrlq $0x4, %xmm12, %xmm14
vpandq %xmm30, %xmm12, %xmm12
vpshufb %xmm12, %xmm2, %xmm12
vpandq %xmm30, %xmm14, %xmm14
vpshufb %xmm14, %xmm3, %xmm14
vpxor %xmm12, %xmm14, %xmm15
vpshufb %xmm15, %xmm27, %xmm15
vpxor %xmm12, %xmm15, %xmm12
vpxor %xmm14, %xmm15, %xmm14
vpshufb %xmm12, %xmm2, %xmm20
vpshufb %xmm14, %xmm3, %xmm12
vpsllq $0x4, %xmm12, %xmm21
vpshufb %xmm23, %xmm17, %xmm15
vpshufb %xmm24, %xmm16, %xmm12
vpshufb %xmm24, %xmm13, %xmm13
vpor %xmm13, %xmm12, %xmm14
vpshufb %xmm25, %xmm18, %xmm12
vpshufb %xmm25, %xmm19, %xmm13
vpor %xmm13, %xmm12, %xmm12
vpshufb %xmm26, %xmm20, %xmm13
vpshufb %xmm26, %xmm21, %xmm16
vporq %xmm16, %xmm13, %xmm13
valignq $0x1, %xmm14, %xmm12, %xmm16 # xmm16 = xmm14[1],xmm12[0]
valignq $0x1, %xmm12, %xmm13, %xmm18 # xmm18 = xmm12[1],xmm13[0]
valignq $0x1, %xmm13, %xmm17, %xmm17 # xmm17 = xmm13[1],xmm17[0]
valignq $0x1, %xmm15, %xmm14, %xmm19 # xmm19 = xmm15[1],xmm14[0]
vpxorq %xmm16, %xmm13, %xmm0
vpxorq %xmm15, %xmm18, %xmm5
vpxorq %xmm14, %xmm17, %xmm6
vpxorq %xmm19, %xmm12, %xmm7
vpcmpgtb %xmm7, %xmm9, %xmm8
vpand %xmm10, %xmm8, %xmm8
vpaddb %xmm7, %xmm7, %xmm20
vpcmpgtb %xmm0, %xmm9, %xmm4
vpand %xmm4, %xmm10, %xmm4
vpaddb %xmm0, %xmm0, %xmm21
vpcmpgtb %xmm5, %xmm9, %xmm11
vpand %xmm10, %xmm11, %xmm11
vpaddb %xmm5, %xmm5, %xmm29
vpcmpgtb %xmm6, %xmm9, %xmm1
vpand %xmm1, %xmm10, %xmm1
vpaddb %xmm6, %xmm6, %xmm31
vpternlogq $0x96, %xmm8, %xmm0, %xmm20
vpternlogq $0x96, %xmm4, %xmm5, %xmm21
vpternlogq $0x96, %xmm11, %xmm6, %xmm29
vpternlogq $0x96, %xmm1, %xmm7, %xmm31
vpaddb %xmm20, %xmm20, %xmm0
vpaddb %xmm21, %xmm21, %xmm1
vpaddb %xmm29, %xmm29, %xmm4
vpaddb %xmm31, %xmm31, %xmm5
vpmovb2m %xmm20, %k1
vpxorq %xmm28, %xmm0, %xmm6
vmovdqu8 %xmm6, %xmm0 {%k1}
vpxor %xmm0, %xmm14, %xmm0
vpcmpgtb %xmm0, %xmm9, %xmm6
vpaddb %xmm0, %xmm0, %xmm0
vpmovb2m %xmm21, %k1
vpxorq %xmm28, %xmm1, %xmm7
vmovdqu8 %xmm7, %xmm1 {%k1}
vpxor %xmm1, %xmm12, %xmm1
vpcmpgtb %xmm1, %xmm9, %xmm7
vpaddb %xmm1, %xmm1, %xmm1
vpmovb2m %xmm29, %k1
vpxorq %xmm28, %xmm4, %xmm8
vmovdqu8 %xmm8, %xmm4 {%k1}
vpxor %xmm4, %xmm13, %xmm4
vpcmpgtb %xmm4, %xmm9, %xmm8
vpaddb %xmm4, %xmm4, %xmm4
vpmovb2m %xmm31, %k1
vpxorq %xmm28, %xmm5, %xmm11
vmovdqu8 %xmm11, %xmm5 {%k1}
vpxor %xmm5, %xmm15, %xmm5
vpcmpgtb %xmm5, %xmm9, %xmm11
vpaddb %xmm5, %xmm5, %xmm5
vpxorq %xmm19, %xmm16, %xmm19
vpternlogq $0x96, %xmm17, %xmm18, %xmm19
vpxorq (%rax,%rcx), %xmm0, %xmm17
vpternlogq $0x78, %xmm10, %xmm6, %xmm17
vpxorq 0x10(%rax,%rcx), %xmm1, %xmm16
vpternlogq $0x96, %xmm15, %xmm19, %xmm17
vpternlogq $0x78, %xmm10, %xmm7, %xmm16
vpternlogq $0x96, %xmm14, %xmm19, %xmm16
vpxor 0x20(%rax,%rcx), %xmm4, %xmm14
vpternlogq $0x78, %xmm10, %xmm8, %xmm14
vpternlogq $0x96, %xmm12, %xmm19, %xmm14
vpxor 0x30(%rax,%rcx), %xmm5, %xmm12
vpternlogq $0x78, %xmm10, %xmm11, %xmm12
vpternlogq $0x96, %xmm13, %xmm19, %xmm12
addq $0x40, %rax
jmp 0x1696
vpshufb %xmm22, %xmm17, %xmm0
vpshufb %xmm22, %xmm16, %xmm1
vpshufb %xmm22, %xmm14, %xmm2
vpshufb %xmm22, %xmm12, %xmm3
vpunpcklwd %xmm1, %xmm0, %xmm4 # xmm4 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
vpunpckhwd %xmm1, %xmm0, %xmm0 # xmm0 = xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
vpunpcklwd %xmm3, %xmm2, %xmm1 # xmm1 = xmm2[0],xmm3[0],xmm2[1],xmm3[1],xmm2[2],xmm3[2],xmm2[3],xmm3[3]
vpunpckhwd %xmm3, %xmm2, %xmm2 # xmm2 = xmm2[4],xmm3[4],xmm2[5],xmm3[5],xmm2[6],xmm3[6],xmm2[7],xmm3[7]
vpunpckldq %xmm1, %xmm4, %xmm3 # xmm3 = xmm4[0],xmm1[0],xmm4[1],xmm1[1]
vpunpckhdq %xmm1, %xmm4, %xmm1 # xmm1 = xmm4[2],xmm1[2],xmm4[3],xmm1[3]
vpunpckldq %xmm2, %xmm0, %xmm4 # xmm4 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
vpunpckhdq %xmm2, %xmm0, %xmm0 # xmm0 = xmm0[2],xmm2[2],xmm0[3],xmm2[3]
vmovdqu %xmm3, (%rdi)
vmovdqu %xmm1, 0x10(%rdi)
vmovdqu %xmm4, 0x20(%rdi)
vmovdqu %xmm0, 0x30(%rdi)
retq