/*******************************************************************************
* Copyright 2019-2021 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include "cpu/x64/jit_generator.hpp"

#include "cpu/x64/gemm/f32/common_f32.hpp"
#include "cpu/x64/gemm/f32/jit_avx512_core_f32_copy_at_kern_autogen.hpp"

namespace dnnl {
namespace impl {
namespace cpu {
namespace x64 {

void jit_avx512_core_f32_copy_at_kern::generate_part2(Xbyak::Label l4000,
        Xbyak::Label l2a5c, Xbyak::Label l22b8, Xbyak::Label l1f80) {
    std::vector<Xbyak::Label> labels(62);
    L(l1f80);
    test(M, 0x2);
    jle(labels[61], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vpxorq(zmm0, zmm6, zmm0);
    vpxorq(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B], zmm1);
    vmovsd(xmm0, qword[A2]);
    vmovsd(xmm1, qword[A2 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A2 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vpxorq(zmm0, zmm6, zmm0);
    vpxorq(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x40], zmm0);
    vmovups(zword[B + 0x40], zmm1);
    sub(A1, -8);
    sub(B, -256);
    align(4);

    L(labels[61]);
    test(M, 0x1);
    jle(labels[60], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vxorps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x80], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vxorps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x60], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vxorps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x40], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vxorps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x20], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    sub(A1, -4);
    sub(B, -128);
    align(4);

    L(labels[60]);
    sub(N, 0x20);
    align(4);

    L(l22b8);
    cmp(N, 0x10);
    jl(labels[55], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x10);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[58], T_NEAR);
    align(4);

    L(labels[59]);
    vmovups(xmm4, xword[A1]);
    vmovups(xmm5, xword[A1 + LDA * 4]);
    vperm2f128(ymm0, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A1 + LDA * 8]);
    vmovups(xmm5, xword[A1 + LDA3 * 4]);
    lea(A2, ptr[A1 + LDA * 1]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm1, zmm1, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm2, zmm2, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm3, zmm3, zmm4, 0x44);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA3 * 4]);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm5, zmm0, zmm1);
    vunpcklps(zmm1, zmm2, zmm3);
    vunpckhps(zmm3, zmm2, zmm3);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vunpcklpd(zmm2, zmm5, zmm3);
    vunpckhpd(zmm3, zmm5, zmm3);
    vpxorq(zmm0, zmm6, zmm0);
    vpxorq(zmm1, zmm6, zmm1);
    vpxorq(zmm2, zmm6, zmm2);
    vpxorq(zmm3, zmm6, zmm3);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B - 0x40], zmm1);
    vmovups(zword[B], zmm2);
    vmovups(zword[B + 0x40], zmm3);
    sub(A1, -16);
    sub(B, -256);
    dec(I);
    jg(labels[59], T_NEAR);
    align(4);

    L(labels[58]);
    test(M, 0x2);
    jle(labels[57], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vpxorq(zmm0, zmm6, zmm0);
    vpxorq(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B - 0x40], zmm1);
    sub(A1, -8);
    sub(B, -128);
    align(4);

    L(labels[57]);
    test(M, 0x1);
    jle(labels[56], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vxorps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x80], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vxorps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x60], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    sub(A1, -4);
    sub(B, -64);
    align(4);

    L(labels[56]);
    sub(N, 0x10);
    align(4);

    L(labels[55]);
    cmp(N, 0x8);
    jl(labels[50], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x8);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[53], T_NEAR);
    align(4);

    L(labels[54]);
    vmovups(xmm0, xword[A1]);
    vmovups(xmm4, xword[A1 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm4, 0x20);
    lea(A2, ptr[A1 + LDA * 1]);
    vmovups(xmm1, xword[A2]);
    vmovups(xmm4, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm1, ymm4, 0x20);
    add(A2, LDA);
    vmovups(xmm2, xword[A2]);
    vmovups(xmm4, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    add(A2, LDA);
    vmovups(xmm3, xword[A2]);
    vmovups(xmm4, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm3, ymm4, 0x20);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA * 4]);
    vunpcklps(ymm4, ymm0, ymm1);
    vunpckhps(ymm5, ymm0, ymm1);
    vunpcklps(ymm1, ymm2, ymm3);
    vunpckhps(ymm3, ymm2, ymm3);
    vunpcklpd(ymm0, ymm4, ymm1);
    vunpckhpd(ymm1, ymm4, ymm1);
    vunpcklpd(ymm2, ymm5, ymm3);
    vunpckhpd(ymm3, ymm5, ymm3);
    vxorps(ymm0, ymm6, ymm0);
    vxorps(ymm1, ymm6, ymm1);
    vxorps(ymm2, ymm6, ymm2);
    vxorps(ymm3, ymm6, ymm3);
    vmovups(yword[B - 0x80], ymm0);
    vmovups(yword[B - 0x60], ymm1);
    vmovups(yword[B - 0x40], ymm2);
    vmovups(yword[B - 0x20], ymm3);
    sub(A1, -16);
    sub(B, -128);
    dec(I);
    jg(labels[54], T_NEAR);
    align(4);

    L(labels[53]);
    test(M, 0x2);
    jle(labels[52], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vunpcklps(ymm4, ymm0, ymm1);
    vunpckhps(ymm1, ymm0, ymm1);
    vunpcklpd(ymm0, ymm4, ymm1);
    vunpckhpd(ymm1, ymm4, ymm1);
    vxorps(ymm0, ymm6, ymm0);
    vxorps(ymm1, ymm6, ymm1);
    vmovups(yword[B - 0x80], ymm0);
    vmovups(yword[B - 0x60], ymm1);
    sub(A1, -8);
    sub(B, -64);
    align(4);

    L(labels[52]);
    test(M, 0x1);
    jle(labels[51], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vxorps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x80], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    sub(A1, -4);
    sub(B, -32);
    align(4);

    L(labels[51]);
    sub(N, 0x8);
    align(4);

    L(labels[50]);
    cmp(N, 0x4);
    jl(labels[45], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x4);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[48], T_NEAR);
    align(4);

    L(labels[49]);
    vmovups(xmm0, xword[A1]);
    vmovups(xmm1, xword[A1 + LDA * 1]);
    vmovups(xmm2, xword[A1 + LDA * 2]);
    vmovups(xmm3, xword[A1 + LDA3 * 1]);
    vunpcklps(xmm4, xmm0, xmm1);
    vunpckhps(xmm5, xmm0, xmm1);
    vunpcklps(xmm1, xmm2, xmm3);
    vunpckhps(xmm3, xmm2, xmm3);
    vunpcklpd(xmm0, xmm4, xmm1);
    vunpckhpd(xmm1, xmm4, xmm1);
    vunpcklpd(xmm2, xmm5, xmm3);
    vunpckhpd(xmm3, xmm5, xmm3);
    vxorps(xmm0, xmm6, xmm0);
    vxorps(xmm1, xmm6, xmm1);
    vxorps(xmm2, xmm6, xmm2);
    vxorps(xmm3, xmm6, xmm3);
    vmovups(xword[B - 0x80], xmm0);
    vmovups(xword[B - 0x70], xmm1);
    vmovups(xword[B - 0x60], xmm2);
    vmovups(xword[B - 0x50], xmm3);
    lea(A2, ptr[A1 + LDA * 4]);
    sub(A1, -16);
    sub(B, -64);
    dec(I);
    jg(labels[49], T_NEAR);
    align(4);

    L(labels[48]);
    test(M, 0x2);
    jle(labels[47], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    vunpcklps(xmm4, xmm0, xmm1);
    vunpckhps(xmm1, xmm0, xmm1);
    vunpcklpd(xmm0, xmm4, xmm1);
    vunpckhpd(xmm1, xmm4, xmm1);
    vxorps(xmm0, xmm6, xmm0);
    vxorps(xmm1, xmm6, xmm1);
    vmovups(xword[B - 0x80], xmm0);
    vmovups(xword[B - 0x70], xmm1);
    lea(A2, ptr[A1 + LDA * 4]);
    sub(A1, -8);
    sub(B, -32);
    align(4);

    L(labels[47]);
    test(M, 0x1);
    jle(labels[46], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vxorps(xmm0, xmm6, xmm0);
    vmovups(xword[B - 0x80], xmm0);
    lea(A2, ptr[A1 + LDA * 4]);
    sub(A1, -4);
    sub(B, -16);
    align(4);

    L(labels[46]);
    sub(N, 0x4);
    align(4);

    L(labels[45]);
    cmp(N, 0x2);
    jl(labels[40], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x2);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[43], T_NEAR);
    align(4);

    L(labels[44]);
    vmovups(xmm0, xword[A1]);
    vmovups(xmm1, xword[A1 + LDA * 1]);
    vunpcklps(xmm4, xmm0, xmm1);
    vunpckhps(xmm1, xmm0, xmm1);
    vmovaps(xmm0, xmm4);
    vxorps(xmm0, xmm6, xmm0);
    vxorps(xmm1, xmm6, xmm1);
    vmovlps(qword[B - 0x80], xmm0);
    vmovhps(qword[B - 0x78], xmm0);
    vmovlps(qword[B - 0x70], xmm1);
    vmovhps(qword[B - 0x68], xmm1);
    lea(A2, ptr[A1 + LDA * 2]);
    sub(A1, -16);
    sub(B, -32);
    dec(I);
    jg(labels[44], T_NEAR);
    align(4);

    L(labels[43]);
    test(M, 0x2);
    jle(labels[42], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vxorps(xmm0, xmm6, xmm0);
    vmovlps(qword[B - 0x80], xmm0);
    vmovhps(qword[B - 0x78], xmm0);
    lea(A2, ptr[A1 + LDA * 2]);
    sub(A1, -8);
    sub(B, -16);
    align(4);

    L(labels[42]);
    test(M, 0x1);
    jle(labels[41], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vxorps(xmm0, xmm6, xmm0);
    vmovlps(qword[B - 0x80], xmm0);
    lea(A2, ptr[A1 + LDA * 2]);
    sub(A1, -4);
    sub(B, -8);
    align(4);

    L(labels[41]);
    sub(N, 0x2);
    align(4);

    L(labels[40]);
    cmp(N, 0x1);
    jl(labels[35], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x1);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[38], T_NEAR);
    align(4);

    L(labels[39]);
    vmovups(xmm0, xword[A1]);
    vxorps(xmm0, xmm6, xmm0);
    vpshufd(xmm1, xmm0, 0x55);
    vpshufd(xmm2, xmm0, 0xaa);
    vpshufd(xmm3, xmm0, 0xff);
    vmovss(dword[B - 0x80], xmm0);
    vmovss(dword[B - 0x7c], xmm1);
    vmovss(dword[B - 0x78], xmm2);
    vmovss(dword[B - 0x74], xmm3);
    lea(A2, ptr[A1 + LDA * 1]);
    sub(A1, -16);
    sub(B, -16);
    dec(I);
    jg(labels[39], T_NEAR);
    align(4);

    L(labels[38]);
    test(M, 0x2);
    jle(labels[37], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vxorps(xmm0, xmm6, xmm0);
    vpshufd(xmm1, xmm0, 0x55);
    vmovss(dword[B - 0x80], xmm0);
    vmovss(dword[B - 0x7c], xmm1);
    lea(A2, ptr[A1 + LDA * 1]);
    sub(A1, -8);
    sub(B, -8);
    align(4);

    L(labels[37]);
    test(M, 0x1);
    jle(labels[36], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vxorps(xmm0, xmm6, xmm0);
    vmovss(dword[B - 0x80], xmm0);
    lea(A2, ptr[A1 + LDA * 1]);
    sub(A1, -4);
    sub(B, -4);
    align(4);

    L(labels[36]);
    sub(N, 0x1);
    align(4);

    L(labels[35]);
    jmp(l4000, T_NEAR);
    align(4);

    L(l2a5c);
    cmp(N, 0x30);
    jl(labels[29], T_NEAR);
    align(4);

    L(labels[34]);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x30);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[32], T_NEAR);
    align(4);

    L(labels[33]);
    vmovups(xmm4, xword[A1]);
    vmovups(xmm5, xword[A1 + LDA * 4]);
    vperm2f128(ymm0, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A1 + LDA * 8]);
    vmovups(xmm5, xword[A1 + LDA3 * 4]);
    lea(A2, ptr[A1 + LDA * 1]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm1, zmm1, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm2, zmm2, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm3, zmm3, zmm4, 0x44);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA3 * 4]);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm5, zmm0, zmm1);
    vunpcklps(zmm1, zmm2, zmm3);
    vunpckhps(zmm3, zmm2, zmm3);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vunpcklpd(zmm2, zmm5, zmm3);
    vunpckhpd(zmm3, zmm5, zmm3);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmulps(zmm2, zmm6, zmm2);
    vmulps(zmm3, zmm6, zmm3);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B + 0x40], zmm1);
    vmovups(zword[B + 0x100], zmm2);
    vmovups(zword[B + 0x1c0], zmm3);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    lea(A2, ptr[A2 + LDA * 1]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm1, zmm1, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm2, zmm2, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm3, zmm3, zmm4, 0x44);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA3 * 4]);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm5, zmm0, zmm1);
    vunpcklps(zmm1, zmm2, zmm3);
    vunpckhps(zmm3, zmm2, zmm3);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vunpcklpd(zmm2, zmm5, zmm3);
    vunpckhpd(zmm3, zmm5, zmm3);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmulps(zmm2, zmm6, zmm2);
    vmulps(zmm3, zmm6, zmm3);
    vmovups(zword[B - 0x40], zmm0);
    vmovups(zword[B + 0x80], zmm1);
    vmovups(zword[B + 0x140], zmm2);
    vmovups(zword[B + 0x200], zmm3);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    lea(A2, ptr[A2 + LDA * 1]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm1, zmm1, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm2, zmm2, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm3, zmm3, zmm4, 0x44);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA3 * 4]);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm5, zmm0, zmm1);
    vunpcklps(zmm1, zmm2, zmm3);
    vunpckhps(zmm3, zmm2, zmm3);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vunpcklpd(zmm2, zmm5, zmm3);
    vunpckhpd(zmm3, zmm5, zmm3);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmulps(zmm2, zmm6, zmm2);
    vmulps(zmm3, zmm6, zmm3);
    vmovups(zword[B], zmm0);
    vmovups(zword[B + 0xc0], zmm1);
    vmovups(zword[B + 0x180], zmm2);
    vmovups(zword[B + 0x240], zmm3);
    sub(A1, -16);
    sub(B, -768);
    dec(I);
    jg(labels[33], T_NEAR);
    align(4);

    L(labels[32]);
    test(M, 0x2);
    jle(labels[31], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B + 0x40], zmm1);
    vmovsd(xmm0, qword[A2]);
    vmovsd(xmm1, qword[A2 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A2 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x40], zmm0);
    vmovups(zword[B + 0x80], zmm1);
    vmovsd(xmm0, qword[A2]);
    vmovsd(xmm1, qword[A2 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A2 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmovups(zword[B], zmm0);
    vmovups(zword[B + 0xc0], zmm1);
    sub(A1, -8);
    sub(B, -384);
    align(4);

    L(labels[31]);
    test(M, 0x1);
    jle(labels[30], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x80], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x60], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x40], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x20], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B + 0x20], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    sub(A1, -4);
    sub(B, -192);
    align(4);

    L(labels[30]);
    sub(N, 0x30);
    cmp(N, 0x30);
    jge(labels[34], T_NEAR);
    align(4);

    L(labels[29]);
    cmp(N, 0x20);
    jl(labels[24], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x20);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[27], T_NEAR);
    align(4);

    L(labels[28]);
    vmovups(xmm4, xword[A1]);
    vmovups(xmm5, xword[A1 + LDA * 4]);
    vperm2f128(ymm0, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A1 + LDA * 8]);
    vmovups(xmm5, xword[A1 + LDA3 * 4]);
    lea(A2, ptr[A1 + LDA * 1]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm1, zmm1, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm2, zmm2, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm3, zmm3, zmm4, 0x44);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA3 * 4]);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm5, zmm0, zmm1);
    vunpcklps(zmm1, zmm2, zmm3);
    vunpckhps(zmm3, zmm2, zmm3);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vunpcklpd(zmm2, zmm5, zmm3);
    vunpckhpd(zmm3, zmm5, zmm3);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmulps(zmm2, zmm6, zmm2);
    vmulps(zmm3, zmm6, zmm3);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B], zmm1);
    vmovups(zword[B + 0x80], zmm2);
    vmovups(zword[B + 0x100], zmm3);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    lea(A2, ptr[A2 + LDA * 1]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm1, zmm1, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm2, zmm2, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm3, zmm3, zmm4, 0x44);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA3 * 4]);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm5, zmm0, zmm1);
    vunpcklps(zmm1, zmm2, zmm3);
    vunpckhps(zmm3, zmm2, zmm3);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vunpcklpd(zmm2, zmm5, zmm3);
    vunpckhpd(zmm3, zmm5, zmm3);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmulps(zmm2, zmm6, zmm2);
    vmulps(zmm3, zmm6, zmm3);
    vmovups(zword[B - 0x40], zmm0);
    vmovups(zword[B + 0x40], zmm1);
    vmovups(zword[B + 0xc0], zmm2);
    vmovups(zword[B + 0x140], zmm3);
    sub(A1, -16);
    sub(B, -512);
    dec(I);
    jg(labels[28], T_NEAR);
    align(4);

    L(labels[27]);
    test(M, 0x2);
    jle(labels[26], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B], zmm1);
    vmovsd(xmm0, qword[A2]);
    vmovsd(xmm1, qword[A2 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A2 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x40], zmm0);
    vmovups(zword[B + 0x40], zmm1);
    sub(A1, -8);
    sub(B, -256);
    align(4);

    L(labels[26]);
    test(M, 0x1);
    jle(labels[25], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x80], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x60], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x40], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x20], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    sub(A1, -4);
    sub(B, -128);
    align(4);

    L(labels[25]);
    sub(N, 0x20);
    align(4);

    L(labels[24]);
    cmp(N, 0x10);
    jl(labels[19], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x10);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[22], T_NEAR);
    align(4);

    L(labels[23]);
    vmovups(xmm4, xword[A1]);
    vmovups(xmm5, xword[A1 + LDA * 4]);
    vperm2f128(ymm0, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A1 + LDA * 8]);
    vmovups(xmm5, xword[A1 + LDA3 * 4]);
    lea(A2, ptr[A1 + LDA * 1]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm1, zmm1, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    add(A2, LDA);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm2, zmm2, zmm4, 0x44);
    vmovups(xmm4, xword[A2]);
    vmovups(xmm5, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm4, ymm5, 0x20);
    vmovups(xmm4, xword[A2 + LDA * 8]);
    vmovups(xmm5, xword[A2 + LDA3 * 4]);
    vperm2f128(ymm4, ymm4, ymm5, 0x20);
    vshuff32x4(zmm3, zmm3, zmm4, 0x44);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA3 * 4]);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm5, zmm0, zmm1);
    vunpcklps(zmm1, zmm2, zmm3);
    vunpckhps(zmm3, zmm2, zmm3);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vunpcklpd(zmm2, zmm5, zmm3);
    vunpckhpd(zmm3, zmm5, zmm3);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmulps(zmm2, zmm6, zmm2);
    vmulps(zmm3, zmm6, zmm3);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B - 0x40], zmm1);
    vmovups(zword[B], zmm2);
    vmovups(zword[B + 0x40], zmm3);
    sub(A1, -16);
    sub(B, -256);
    dec(I);
    jg(labels[23], T_NEAR);
    align(4);

    L(labels[22]);
    test(M, 0x2);
    jle(labels[21], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovsd(xmm4, qword[A2]);
    vmovsd(xmm5, qword[A2 + LDA * 1]);
    vmovhps(xmm4, xmm4, qword[A2 + LDA * 2]);
    vmovhps(xmm5, xmm5, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    vperm2f128(ymm3, ymm3, ymm5, 0x20);
    vshuff32x4(zmm0, zmm0, zmm2, 0x44);
    vshuff32x4(zmm1, zmm1, zmm3, 0x44);
    vunpcklps(zmm4, zmm0, zmm1);
    vunpckhps(zmm1, zmm0, zmm1);
    vunpcklpd(zmm0, zmm4, zmm1);
    vunpckhpd(zmm1, zmm4, zmm1);
    vmulps(zmm0, zmm6, zmm0);
    vmulps(zmm1, zmm6, zmm1);
    vmovups(zword[B - 0x80], zmm0);
    vmovups(zword[B - 0x40], zmm1);
    sub(A1, -8);
    sub(B, -128);
    align(4);

    L(labels[21]);
    test(M, 0x1);
    jle(labels[20], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x80], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A2 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x60], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    sub(A1, -4);
    sub(B, -64);
    align(4);

    L(labels[20]);
    sub(N, 0x10);
    align(4);

    L(labels[19]);
    cmp(N, 0x8);
    jl(labels[14], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x8);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[17], T_NEAR);
    align(4);

    L(labels[18]);
    vmovups(xmm0, xword[A1]);
    vmovups(xmm4, xword[A1 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm4, 0x20);
    lea(A2, ptr[A1 + LDA * 1]);
    vmovups(xmm1, xword[A2]);
    vmovups(xmm4, xword[A2 + LDA * 4]);
    vperm2f128(ymm1, ymm1, ymm4, 0x20);
    add(A2, LDA);
    vmovups(xmm2, xword[A2]);
    vmovups(xmm4, xword[A2 + LDA * 4]);
    vperm2f128(ymm2, ymm2, ymm4, 0x20);
    add(A2, LDA);
    vmovups(xmm3, xword[A2]);
    vmovups(xmm4, xword[A2 + LDA * 4]);
    vperm2f128(ymm3, ymm3, ymm4, 0x20);
    add(A2, LDA);
    lea(A2, ptr[A2 + LDA * 4]);
    vunpcklps(ymm4, ymm0, ymm1);
    vunpckhps(ymm5, ymm0, ymm1);
    vunpcklps(ymm1, ymm2, ymm3);
    vunpckhps(ymm3, ymm2, ymm3);
    vunpcklpd(ymm0, ymm4, ymm1);
    vunpckhpd(ymm1, ymm4, ymm1);
    vunpcklpd(ymm2, ymm5, ymm3);
    vunpckhpd(ymm3, ymm5, ymm3);
    vmulps(ymm0, ymm6, ymm0);
    vmulps(ymm1, ymm6, ymm1);
    vmulps(ymm2, ymm6, ymm2);
    vmulps(ymm3, ymm6, ymm3);
    vmovups(yword[B - 0x80], ymm0);
    vmovups(yword[B - 0x60], ymm1);
    vmovups(yword[B - 0x40], ymm2);
    vmovups(yword[B - 0x20], ymm3);
    sub(A1, -16);
    sub(B, -128);
    dec(I);
    jg(labels[18], T_NEAR);
    align(4);

    L(labels[17]);
    test(M, 0x2);
    jle(labels[16], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovsd(xmm2, qword[A2]);
    vmovsd(xmm3, qword[A2 + LDA * 1]);
    vmovhps(xmm2, xmm2, qword[A2 + LDA * 2]);
    vmovhps(xmm3, xmm3, qword[A2 + LDA3 * 1]);
    lea(A2, ptr[A2 + LDA * 4]);
    vperm2f128(ymm0, ymm0, ymm2, 0x20);
    vperm2f128(ymm1, ymm1, ymm3, 0x20);
    vunpcklps(ymm4, ymm0, ymm1);
    vunpckhps(ymm1, ymm0, ymm1);
    vunpcklpd(ymm0, ymm4, ymm1);
    vunpckhpd(ymm1, ymm4, ymm1);
    vmulps(ymm0, ymm6, ymm0);
    vmulps(ymm1, ymm6, ymm1);
    vmovups(yword[B - 0x80], ymm0);
    vmovups(yword[B - 0x60], ymm1);
    sub(A1, -8);
    sub(B, -64);
    align(4);

    L(labels[16]);
    test(M, 0x1);
    jle(labels[15], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm4, xmm0, xmm2);
    lea(A2, ptr[A1 + LDA * 4]);
    vmovss(xmm0, dword[A2]);
    vmovss(xmm1, dword[A2 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A2 + LDA * 2]);
    vmovss(xmm3, dword[A2 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vperm2f128(ymm0, ymm0, ymm4, 0x2);
    vmulps(ymm0, ymm6, ymm0);
    vmovups(yword[B - 0x80], ymm0);
    lea(A2, ptr[A2 + LDA * 4]);
    sub(A1, -4);
    sub(B, -32);
    align(4);

    L(labels[15]);
    sub(N, 0x8);
    align(4);

    L(labels[14]);
    cmp(N, 0x4);
    jl(labels[9], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x4);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[12], T_NEAR);
    align(4);

    L(labels[13]);
    vmovups(xmm0, xword[A1]);
    vmovups(xmm1, xword[A1 + LDA * 1]);
    vmovups(xmm2, xword[A1 + LDA * 2]);
    vmovups(xmm3, xword[A1 + LDA3 * 1]);
    vunpcklps(xmm4, xmm0, xmm1);
    vunpckhps(xmm5, xmm0, xmm1);
    vunpcklps(xmm1, xmm2, xmm3);
    vunpckhps(xmm3, xmm2, xmm3);
    vunpcklpd(xmm0, xmm4, xmm1);
    vunpckhpd(xmm1, xmm4, xmm1);
    vunpcklpd(xmm2, xmm5, xmm3);
    vunpckhpd(xmm3, xmm5, xmm3);
    vmulps(xmm0, xmm6, xmm0);
    vmulps(xmm1, xmm6, xmm1);
    vmulps(xmm2, xmm6, xmm2);
    vmulps(xmm3, xmm6, xmm3);
    vmovups(xword[B - 0x80], xmm0);
    vmovups(xword[B - 0x70], xmm1);
    vmovups(xword[B - 0x60], xmm2);
    vmovups(xword[B - 0x50], xmm3);
    lea(A2, ptr[A1 + LDA * 4]);
    sub(A1, -16);
    sub(B, -64);
    dec(I);
    jg(labels[13], T_NEAR);
    align(4);

    L(labels[12]);
    test(M, 0x2);
    jle(labels[11], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vmovhps(xmm0, xmm0, qword[A1 + LDA * 2]);
    vmovhps(xmm1, xmm1, qword[A1 + LDA3 * 1]);
    vunpcklps(xmm4, xmm0, xmm1);
    vunpckhps(xmm1, xmm0, xmm1);
    vunpcklpd(xmm0, xmm4, xmm1);
    vunpckhpd(xmm1, xmm4, xmm1);
    vmulps(xmm0, xmm6, xmm0);
    vmulps(xmm1, xmm6, xmm1);
    vmovups(xword[B - 0x80], xmm0);
    vmovups(xword[B - 0x70], xmm1);
    lea(A2, ptr[A1 + LDA * 4]);
    sub(A1, -8);
    sub(B, -32);
    align(4);

    L(labels[11]);
    test(M, 0x1);
    jle(labels[10], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmovss(xmm2, dword[A1 + LDA * 2]);
    vmovss(xmm3, dword[A1 + LDA3 * 1]);
    vunpcklps(xmm2, xmm2, xmm3);
    vunpcklpd(xmm0, xmm0, xmm2);
    vmulps(xmm0, xmm6, xmm0);
    vmovups(xword[B - 0x80], xmm0);
    lea(A2, ptr[A1 + LDA * 4]);
    sub(A1, -4);
    sub(B, -16);
    align(4);

    L(labels[10]);
    sub(N, 0x4);
    align(4);

    L(labels[9]);
    cmp(N, 0x2);
    jl(labels[4], T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x2);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[7], T_NEAR);
    align(4);

    L(labels[8]);
    vmovups(xmm0, xword[A1]);
    vmovups(xmm1, xword[A1 + LDA * 1]);
    vunpcklps(xmm4, xmm0, xmm1);
    vunpckhps(xmm1, xmm0, xmm1);
    vmovaps(xmm0, xmm4);
    vmulps(xmm0, xmm6, xmm0);
    vmulps(xmm1, xmm6, xmm1);
    vmovlps(qword[B - 0x80], xmm0);
    vmovhps(qword[B - 0x78], xmm0);
    vmovlps(qword[B - 0x70], xmm1);
    vmovhps(qword[B - 0x68], xmm1);
    lea(A2, ptr[A1 + LDA * 2]);
    sub(A1, -16);
    sub(B, -32);
    dec(I);
    jg(labels[8], T_NEAR);
    align(4);

    L(labels[7]);
    test(M, 0x2);
    jle(labels[6], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmovsd(xmm1, qword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmulps(xmm0, xmm6, xmm0);
    vmovlps(qword[B - 0x80], xmm0);
    vmovhps(qword[B - 0x78], xmm0);
    lea(A2, ptr[A1 + LDA * 2]);
    sub(A1, -8);
    sub(B, -16);
    align(4);

    L(labels[6]);
    test(M, 0x1);
    jle(labels[5], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmovss(xmm1, dword[A1 + LDA * 1]);
    vunpcklps(xmm0, xmm0, xmm1);
    vmulps(xmm0, xmm6, xmm0);
    vmovlps(qword[B - 0x80], xmm0);
    lea(A2, ptr[A1 + LDA * 2]);
    sub(A1, -4);
    sub(B, -8);
    align(4);

    L(labels[5]);
    sub(N, 0x2);
    align(4);

    L(labels[4]);
    cmp(N, 0x1);
    jl(l4000, T_NEAR);
    mov(A1, A);
    mov(I, LDA);
    imul(I, I, 0x1);
    add(A, I);
    mov(I, M);
    sar(I, 0x2);
    jle(labels[2], T_NEAR);
    align(4);

    L(labels[3]);
    vmovups(xmm0, xword[A1]);
    vmulps(xmm0, xmm6, xmm0);
    vpshufd(xmm1, xmm0, 0x55);
    vpshufd(xmm2, xmm0, 0xaa);
    vpshufd(xmm3, xmm0, 0xff);
    vmovss(dword[B - 0x80], xmm0);
    vmovss(dword[B - 0x7c], xmm1);
    vmovss(dword[B - 0x78], xmm2);
    vmovss(dword[B - 0x74], xmm3);
    lea(A2, ptr[A1 + LDA * 1]);
    sub(A1, -16);
    sub(B, -16);
    dec(I);
    jg(labels[3], T_NEAR);
    align(4);

    L(labels[2]);
    test(M, 0x2);
    jle(labels[1], T_NEAR);
    vmovsd(xmm0, qword[A1]);
    vmulps(xmm0, xmm6, xmm0);
    vpshufd(xmm1, xmm0, 0x55);
    vmovss(dword[B - 0x80], xmm0);
    vmovss(dword[B - 0x7c], xmm1);
    lea(A2, ptr[A1 + LDA * 1]);
    sub(A1, -8);
    sub(B, -8);
    align(4);

    L(labels[1]);
    test(M, 0x1);
    jle(labels[0], T_NEAR);
    vmovss(xmm0, dword[A1]);
    vmulps(xmm0, xmm6, xmm0);
    vmovss(dword[B - 0x80], xmm0);
    lea(A2, ptr[A1 + LDA * 1]);
    sub(A1, -4);
    sub(B, -4);
    align(4);

    L(labels[0]);
    sub(N, 0x1);
    align(4);

    L(l4000);
}

} // namespace x64
} // namespace cpu
} // namespace impl
} // namespace dnnl
