text: /*
  
     BLIS    
     An object-based framework for developing high-performance BLAS-like
     libraries.
  
     Copyright (C) 2014, The University of Texas at Austin
  
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions are
     met:
      - Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      - Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
      - Neither the name of The University of Texas at Austin nor the names
        of its contributors may be used to endorse or promote products
        derived from this software without specific prior written permission.
  
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  */
  
  #include "blis.h"
  
  #include "bli_avx512_macros.h"
  
  extern int32_t offsets[16];
  
  void bli_dgemm_knl_asm_12x16
       (
         dim_t               k,
         double*    restrict alpha,
         double*    restrict a,
         double*    restrict b,
         double*    restrict beta,
         double*    restrict c, inc_t rs_c, inc_t cs_c,
         auxinfo_t* restrict data,
         cntx_t*    restrict cntx
       )
  {
  	//const void* a_next = bli_auxinfo_next_a( data );
  	//const void* b_next = bli_auxinfo_next_b( data );
  
      const int32_t * offsetPtr = &offsets[0];
  
  	__asm__ volatile
  	(
  
      VPXORD(ZMM(8), ZMM(8), ZMM(8))  MOV(RAX, VAR(a))
      VMOVAPD(ZMM( 9), ZMM(8))        MOV(RBX, VAR(b))
      VMOVAPD(ZMM(10), ZMM(8))        //no ADD(RBX, IMM(4*64))
      VMOVAPD(ZMM(11), ZMM(8))        //maybe? PREFETCH(0, MEM(RAX, 0))
      VMOVAPD(ZMM(12), ZMM(8))        //maybe? PREFETCH(0, MEM(RAX,64))
      VMOVAPD(ZMM(13), ZMM(8))        VMOVAPD(ZMM(0), MEM(RBX,0*64))
      VMOVAPD(ZMM(14), ZMM(8))        VMOVAPD(ZMM(1), MEM(RBX,1*64))
      VMOVAPD(ZMM(15), ZMM(8))        MOV(RCX, VAR(c))
      VMOVAPD(ZMM(16), ZMM(8))        MOV(RDI, RCX)
      VMOVAPD(ZMM(17), ZMM(8))        VBROADCASTSS(ZMM(4), VAR(cs_c))
      VMOVAPD(ZMM(18), ZMM(8))        VMOVAPS(ZMM(5), VAR(offsetPtr))
      VMOVAPD(ZMM(19), ZMM(8))        VPMULLD(ZMM(4), ZMM(5), ZMM(4))
      VMOVAPD(ZMM(20), ZMM(8))        MOV(RDX, IMM(0xFFF))
      VMOVAPD(ZMM(21), ZMM(8))        KMOV(K(1), EDX)
      VMOVAPD(ZMM(22), ZMM(8))        KMOV(K(2), EDX)
      VMOVAPD(ZMM(23), ZMM(8))        KMOV(K(3), EDX)
      VMOVAPD(ZMM(24), ZMM(8))        VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8,   0) MASK_K(1))
      VMOVAPD(ZMM(25), ZMM(8))        VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8, 8*8) MASK_K(2))
      VMOVAPD(ZMM(26), ZMM(8))        VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8,15*8) MASK_K(3))
      VMOVAPD(ZMM(27), ZMM(8))        MOV(RSI, VAR(k))
      VMOVAPD(ZMM(28), ZMM(8))        SAR(RSI, IMM(2)) // rsi = k/4
      VMOVAPD(ZMM(29), ZMM(8))
      VMOVAPD(ZMM(30), ZMM(8))
      VMOVAPD(ZMM(31), ZMM(8))
  
      JZ(.DCONSIDKLEFT)
  
      ALIGN16
      LABEL(.DLOOPKITER)
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 0*8)) // Iteration 0
      VBROADCASTSD(ZMM(3), MEM(RAX, 1*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 2*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 3*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 4*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 5*8))
      VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
  
      VBROADCASTSD(ZMM(2), MEM(RAX,  6*8))
      VBROADCASTSD(ZMM(3), MEM(RAX,  7*8))
      VBROADCASTSD(ZMM(4), MEM(RAX,  8*8))
      VBROADCASTSD(ZMM(5), MEM(RAX,  9*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 10*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 11*8))
      VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
  
      VMOVAPD(ZMM(0), MEM(RBX,2*64))
      VMOVAPD(ZMM(1), MEM(RBX,3*64))
  
      PREFETCH(0, MEM(RAX, 64*8))
      PREFETCH(0, MEM(RAX, 72*8))
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 12*8)) // Iteration 1
      VBROADCASTSD(ZMM(3), MEM(RAX, 13*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 14*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 15*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 16*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 17*8))
      VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 18*8))
      VBROADCASTSD(ZMM(3), MEM(RAX, 19*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 20*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 21*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 22*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 23*8))
      VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
  
      VMOVAPD(ZMM(0), MEM(RBX,4*64))
      VMOVAPD(ZMM(1), MEM(RBX,5*64))
  
      PREFETCH(0, MEM(RAX, 80*8))
      PREFETCH(0, MEM(RAX, 88*8))
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 24*8)) // Iteration 2
      VBROADCASTSD(ZMM(3), MEM(RAX, 25*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 26*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 27*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 28*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 29*8))
      VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 30*8))
      VBROADCASTSD(ZMM(3), MEM(RAX, 31*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 32*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 33*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 34*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 35*8))
      VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
  
      VMOVAPD(ZMM(0), MEM(RBX,6*64))
      VMOVAPD(ZMM(1), MEM(RBX,7*64))
  
      ADD(RBX, IMM(4*8*16))
      PREFETCH(0, MEM(RAX, 96*8))
      PREFETCH(0, MEM(RAX, 104*8))
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 36*8)) // Iteration 3
      VBROADCASTSD(ZMM(3), MEM(RAX, 37*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 38*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 39*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 40*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 41*8))
      VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 42*8))
      VBROADCASTSD(ZMM(3), MEM(RAX, 43*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 44*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 45*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 46*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 47*8))
      VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
  
      ADD(RAX, IMM(4*8*12))
      SUB(RSI, IMM(1))
  
      VMOVAPD(ZMM(0), MEM(RBX,0*64))
      VMOVAPD(ZMM(1), MEM(RBX,1*64))
  
      JNZ(.DLOOPKITER)
  
      LABEL(.DCONSIDKLEFT)
  
      MOV(RSI, VAR(k))
      AND(RSI, IMM(3)) // rsi = k%4
      JZ(.DPOSTACCUM)
  
      ALIGN16
      LABEL(.DLOOPKLEFT)
  
      VBROADCASTSD(ZMM(2), MEM(RAX, 0*8))
      VBROADCASTSD(ZMM(3), MEM(RAX, 1*8))
      VBROADCASTSD(ZMM(4), MEM(RAX, 2*8))
      VBROADCASTSD(ZMM(5), MEM(RAX, 3*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 4*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 5*8))
      VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
  
      VBROADCASTSD(ZMM(2), MEM(RAX,  6*8))
      VBROADCASTSD(ZMM(3), MEM(RAX,  7*8))
      VBROADCASTSD(ZMM(4), MEM(RAX,  8*8))
      VBROADCASTSD(ZMM(5), MEM(RAX,  9*8))
      VBROADCASTSD(ZMM(6), MEM(RAX, 10*8))
      VBROADCASTSD(ZMM(7), MEM(RAX, 11*8))
      VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
      VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
      VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
      VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
      VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
      VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
      VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
      VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
      VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
      VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
      VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
      VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
  
      ADD(RAX, IMM(12*8))
      ADD(RBX, IMM(16*8))
      SUB(RSI, IMM(1))
  
      VMOVAPD(ZMM(0), MEM(RBX,0*64))
      VMOVAPD(ZMM(1), MEM(RBX,1*64))
  
      JNZ(.DLOOPKLEFT)
  
      LABEL(.DPOSTACCUM)
  
      MOV(RAX, VAR(alpha))
      MOV(RBX, VAR(beta))
      VBROADCASTSD(ZMM(0), MEM(RAX))
      VBROADCASTSD(ZMM(1), MEM(RBX))
  
      VMULPD(ZMM( 8), ZMM( 8), ZMM(0))
      VMULPD(ZMM( 9), ZMM( 9), ZMM(0))
      VMULPD(ZMM(10), ZMM(10), ZMM(0))
      VMULPD(ZMM(11), ZMM(11), ZMM(0))
      VMULPD(ZMM(12), ZMM(12), ZMM(0))
      VMULPD(ZMM(13), ZMM(13), ZMM(0))
      VMULPD(ZMM(14), ZMM(14), ZMM(0))
      VMULPD(ZMM(15), ZMM(15), ZMM(0))
      VMULPD(ZMM(16), ZMM(16), ZMM(0))
      VMULPD(ZMM(17), ZMM(17), ZMM(0))
      VMULPD(ZMM(18), ZMM(18), ZMM(0))
      VMULPD(ZMM(19), ZMM(19), ZMM(0))
      VMULPD(ZMM(20), ZMM(20), ZMM(0))
      VMULPD(ZMM(21), ZMM(21), ZMM(0))
      VMULPD(ZMM(22), ZMM(22), ZMM(0))
      VMULPD(ZMM(23), ZMM(23), ZMM(0))
      VMULPD(ZMM(24), ZMM(24), ZMM(0))
      VMULPD(ZMM(25), ZMM(25), ZMM(0))
      VMULPD(ZMM(26), ZMM(26), ZMM(0))
      VMULPD(ZMM(27), ZMM(27), ZMM(0))
      VMULPD(ZMM(28), ZMM(28), ZMM(0))
      VMULPD(ZMM(29), ZMM(29), ZMM(0))
      VMULPD(ZMM(30), ZMM(30), ZMM(0))
      VMULPD(ZMM(31), ZMM(31), ZMM(0))
  
      MOV(RDI, VAR(rs_c))
      SUB(RDI, IMM(1))
      JNZ(.DGENSTORED)
  
      LABEL(.ROWSTORED)
  
      MOV(RSI, VAR(cs_c))
      MOV(R(8), MEM(RBX))
      LEA(RSI, MEM(,RSI,8))
      LEA(RDX, MEM(RCX,RSI,4))
      LEA(RDI, MEM(RCX,RSI,8))
      LEA(R(13), MEM(RSI,RSI,2))
      SAL1(R(8)) // shift out the sign bit to check for +/- zero
      JZ(.DROWSTORBZ)
  
      VFMADD231PD(ZMM( 8), ZMM(1), MEM(RCX))
      VFMADD231PD(ZMM( 9), ZMM(1), MEM(RCX,64))
      VMOVUPD(MEM(RCX), ZMM( 8))
      VMOVUPD(MEM(RCX,64), ZMM( 9))
  
      VFMADD231PD(ZMM(10), ZMM(1), MEM(RCX,RSI,1))
      VFMADD231PD(ZMM(11), ZMM(1), MEM(RCX,RSI,1,64))
      VMOVUPD(MEM(RCX,RSI,1), ZMM(10))
      VMOVUPD(MEM(RCX,RSI,1,64), ZMM(11))
  
      VFMADD231PD(ZMM(12), ZMM(1), MEM(RCX,RSI,2))
      VFMADD231PD(ZMM(13), ZMM(1), MEM(RCX,RSI,2,64))
      VMOVUPD(MEM(RCX,RSI,2), ZMM(12))
      VMOVUPD(MEM(RCX,RSI,2,64), ZMM(13))
  
      VFMADD231PD(ZMM(14), ZMM(1), MEM(RCX,R(13),1))
      VFMADD231PD(ZMM(15), ZMM(1), MEM(RCX,R(13),1,64))
      VMOVUPD(MEM(RCX,R(13),1), ZMM(14))
      VMOVUPD(MEM(RCX,R(13),1,64), ZMM(15))
  
      VFMADD231PD(ZMM(16), ZMM(1), MEM(RDX))
      VFMADD231PD(ZMM(17), ZMM(1), MEM(RDX,64))
      VMOVUPD(MEM(RDX), ZMM(16))
      VMOVUPD(MEM(RDX,64), ZMM(17))
  
      VFMADD231PD(ZMM(18), ZMM(1), MEM(RDX,RSI,1))
      VFMADD231PD(ZMM(19), ZMM(1), MEM(RDX,RSI,1,64))
      VMOVUPD(MEM(RDX,RSI,1), ZMM(18))
      VMOVUPD(MEM(RDX,RSI,1,64), ZMM(19))
  
      VFMADD231PD(ZMM(20), ZMM(1), MEM(RDX,RSI,2))
      VFMADD231PD(ZMM(21), ZMM(1), MEM(RDX,RSI,2,64))
      VMOVUPD(MEM(RDX,RSI,2), ZMM(20))
      VMOVUPD(MEM(RDX,RSI,2,64), ZMM(21))
  
      VFMADD231PD(ZMM(22), ZMM(1), MEM(RDX,R(13),1))
      VFMADD231PD(ZMM(23), ZMM(1), MEM(RDX,R(13),1,64))
      VMOVUPD(MEM(RDX,R(13),1), ZMM(22))
      VMOVUPD(MEM(RDX,R(13),1,64), ZMM(23))
  
      VFMADD231PD(ZMM(24), ZMM(1), MEM(RDI))
      VFMADD231PD(ZMM(25), ZMM(1), MEM(RDI,64))
      VMOVUPD(MEM(RDI), ZMM(24))
      VMOVUPD(MEM(RDI,64), ZMM(25))
  
      VFMADD231PD(ZMM(26), ZMM(1), MEM(RDI,RSI,1))
      VFMADD231PD(ZMM(27), ZMM(1), MEM(RDI,RSI,1,64))
      VMOVUPD(MEM(RDI,RSI,1), ZMM(26))
      VMOVUPD(MEM(RDI,RSI,1,64), ZMM(27))
  
      VFMADD231PD(ZMM(28), ZMM(1), MEM(RDI,RSI,2))
      VFMADD231PD(ZMM(29), ZMM(1), MEM(RDI,RSI,2,64))
      VMOVUPD(MEM(RDI,RSI,2), ZMM(28))
      VMOVUPD(MEM(RDI,RSI,2,64), ZMM(29))
  
      VFMADD231PD(ZMM(30), ZMM(1), MEM(RDI,R(13),1))
      VFMADD231PD(ZMM(31), ZMM(1), MEM(RDI,R(13),1,64))
      VMOVUPD(MEM(RDI,R(13),1), ZMM(30))
      VMOVUPD(MEM(RDI,R(13),1,64), ZMM(31))
  
      JMP(.DDONE)
  
      LABEL(.DROWSTORBZ)
  
      VMOVUPD(MEM(RCX), ZMM( 8))
      VMOVUPD(MEM(RCX,64), ZMM( 9))
      VMOVUPD(MEM(RCX,RSI,1), ZMM(10))
      VMOVUPD(MEM(RCX,RSI,1,64), ZMM(11))
      VMOVUPD(MEM(RCX,RSI,2), ZMM(12))
      VMOVUPD(MEM(RCX,RSI,2,64), ZMM(13))
      VMOVUPD(MEM(RCX,R(13),1), ZMM(14))
      VMOVUPD(MEM(RCX,R(13),1,64), ZMM(15))
      VMOVUPD(MEM(RDX), ZMM(16))
      VMOVUPD(MEM(RDX,64), ZMM(17))
      VMOVUPD(MEM(RDX,RSI,1), ZMM(18))
      VMOVUPD(MEM(RDX,RSI,1,64), ZMM(19))
      VMOVUPD(MEM(RDX,RSI,2), ZMM(20))
      VMOVUPD(MEM(RDX,RSI,2,64), ZMM(21))
      VMOVUPD(MEM(RDX,R(13),1), ZMM(22))
      VMOVUPD(MEM(RDX,R(13),1,64), ZMM(23))
      VMOVUPD(MEM(RDI), ZMM(24))
      VMOVUPD(MEM(RDI,64), ZMM(25))
      VMOVUPD(MEM(RDI,RSI,1), ZMM(26))
      VMOVUPD(MEM(RDI,RSI,1,64), ZMM(27))
      VMOVUPD(MEM(RDI,RSI,2), ZMM(28))
      VMOVUPD(MEM(RDI,RSI,2,64), ZMM(29))
      VMOVUPD(MEM(RDI,R(13),1), ZMM(30))
      VMOVUPD(MEM(RDI,R(13),1,64), ZMM(31))
  
      JMP(.DDONE)
  
      LABEL(.DGENSTORED)
  
      MOV(RDI, VAR(cs_c))
      MOV(RAX, VAR(rs_c))
      LEA(RDI, MEM(,RDI,8))
      MOV(R(8), MEM(RBX))
      VBROADCASTSS(YMM(4), VAR(rs_c))
      VMOVAPS(YMM(5), VAR(offsetPtr))
      VPMULLD(YMM(4), YMM(5), YMM(4))
      LEA(RDX, MEM(RCX,RAX,8))
      MOV(RSI, 0x3F)
      SAL1(R(8)) // shift out the sign bit to check for +/- zero
      JZ(.DGENSTORBZ)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM( 8))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM( 9))
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM( 8))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM( 9))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(10))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(11))
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(10))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(11))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(12))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(13))
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(12))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(13))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(14))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(15))
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(14))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(15))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(16))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(17))
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(16))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(17))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(18))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(19))
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(18))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(19))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(20))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(21))
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(20))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(21))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(22))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(23))
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(22))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(23))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(24))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(25))
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(24))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(25))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(26))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(27))
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(26))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(27))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(28))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(29))
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(28))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(29))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
      VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
      VFMADD231PD(ZMM(2), ZMM(1), ZMM(30))
      VFMADD231PD(ZMM(3), ZMM(1), ZMM(31))
      KMOV(K(3), ESI)
      KMOV(K(4), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(30))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(31))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      JMP(.DDONE)
  
      LABEL(.DGENSTORBZ)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM( 8))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM( 9))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(10))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(11))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(12))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(13))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(14))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(15))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(16))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(17))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(18))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(19))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(20))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(21))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(22))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(23))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(24))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(25))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(26))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(27))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(28))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(29))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      KMOV(K(1), ESI)
      KMOV(K(2), ESI)
      VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(30))
      VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(31))
      ADD(RCX, RDI)
      ADD(RDX, RDI)
  
      LABEL(.DDONE)
  
  	: // output operands (none)
      : // input operands
        [k]         "m" (k),
        [a]         "m" (a),
        [b]         "m" (b),
        [alpha]     "m" (alpha),
        [beta]      "m" (beta),
        [c]         "m" (c),
        [rs_c]      "m" (rs_c),
        [cs_c]      "m" (cs_c),
        //[a_next]    "m" (a_next),
        //[b_next]    "m" (b_next),
        [offsetPtr] "m" (offsetPtr)
      : // register clobber list
        "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12",
        "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5",
        "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13",
        "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21",
        "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29",
        "zmm30", "zmm31", "memory"
  	);
  }
  