1 /*
2 
3    BLIS
4    An object-based framework for developing high-performance BLAS-like
5    libraries.
6 
7    Copyright (C) 2014, The University of Texas at Austin
8 
9    Redistribution and use in source and binary forms, with or without
10    modification, are permitted provided that the following conditions are
11    met:
12     - Redistributions of source code must retain the above copyright
13       notice, this list of conditions and the following disclaimer.
14     - Redistributions in binary form must reproduce the above copyright
15       notice, this list of conditions and the following disclaimer in the
16       documentation and/or other materials provided with the distribution.
17     - Neither the name(s) of the copyright holder(s) nor the names of its
18       contributors may be used to endorse or promote products derived
19       from this software without specific prior written permission.
20 
21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 */
34 
35 #include "blis.h"
36 
37 #include "bli_avx512_macros.h"
38 
39 extern int32_t offsets[16];
40 
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)41 void bli_dgemm_knl_asm_12x16
42      (
43        dim_t               k,
44        double*    restrict alpha,
45        double*    restrict a,
46        double*    restrict b,
47        double*    restrict beta,
48        double*    restrict c, inc_t rs_c, inc_t cs_c,
49        auxinfo_t* restrict data,
50        cntx_t*    restrict cntx
51      )
52 {
53 	//const void* a_next = bli_auxinfo_next_a( data );
54 	//const void* b_next = bli_auxinfo_next_b( data );
55 
56     const int32_t * offsetPtr = &offsets[0];
57 
58 	__asm__ volatile
59 	(
60 
61     VPXORD(ZMM(8), ZMM(8), ZMM(8))  MOV(RAX, VAR(a))
62     VMOVAPD(ZMM( 9), ZMM(8))        MOV(RBX, VAR(b))
63     VMOVAPD(ZMM(10), ZMM(8))        //no ADD(RBX, IMM(4*64))
64     VMOVAPD(ZMM(11), ZMM(8))        //maybe? PREFETCH(0, MEM(RAX, 0))
65     VMOVAPD(ZMM(12), ZMM(8))        //maybe? PREFETCH(0, MEM(RAX,64))
66     VMOVAPD(ZMM(13), ZMM(8))        VMOVAPD(ZMM(0), MEM(RBX,0*64))
67     VMOVAPD(ZMM(14), ZMM(8))        VMOVAPD(ZMM(1), MEM(RBX,1*64))
68     VMOVAPD(ZMM(15), ZMM(8))        MOV(RCX, VAR(c))
69     VMOVAPD(ZMM(16), ZMM(8))        MOV(RDI, RCX)
70     VMOVAPD(ZMM(17), ZMM(8))        VBROADCASTSS(ZMM(4), VAR(cs_c))
71     VMOVAPD(ZMM(18), ZMM(8))        VMOVAPS(ZMM(5), VAR(offsetPtr))
72     VMOVAPD(ZMM(19), ZMM(8))        VPMULLD(ZMM(4), ZMM(5), ZMM(4))
73     VMOVAPD(ZMM(20), ZMM(8))        MOV(RDX, IMM(0xFFF))
74     VMOVAPD(ZMM(21), ZMM(8))        KMOV(K(1), EDX)
75     VMOVAPD(ZMM(22), ZMM(8))        KMOV(K(2), EDX)
76     VMOVAPD(ZMM(23), ZMM(8))        KMOV(K(3), EDX)
77     VMOVAPD(ZMM(24), ZMM(8))        VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8,   0) MASK_K(1))
78     VMOVAPD(ZMM(25), ZMM(8))        VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8, 8*8) MASK_K(2))
79     VMOVAPD(ZMM(26), ZMM(8))        VSCATTERPFDPS(0, MEM(RCX,ZMM(4),8,15*8) MASK_K(3))
80     VMOVAPD(ZMM(27), ZMM(8))        MOV(RSI, VAR(k))
81     VMOVAPD(ZMM(28), ZMM(8))        SAR(RSI, IMM(2)) // rsi = k/4
82     VMOVAPD(ZMM(29), ZMM(8))
83     VMOVAPD(ZMM(30), ZMM(8))
84     VMOVAPD(ZMM(31), ZMM(8))
85 
86     JZ(.DCONSIDKLEFT)
87 
88     ALIGN16
89     LABEL(.DLOOPKITER)
90 
91     VBROADCASTSD(ZMM(2), MEM(RAX, 0*8)) // Iteration 0
92     VBROADCASTSD(ZMM(3), MEM(RAX, 1*8))
93     VBROADCASTSD(ZMM(4), MEM(RAX, 2*8))
94     VBROADCASTSD(ZMM(5), MEM(RAX, 3*8))
95     VBROADCASTSD(ZMM(6), MEM(RAX, 4*8))
96     VBROADCASTSD(ZMM(7), MEM(RAX, 5*8))
97     VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
98     VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
99     VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
100     VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
101     VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
102     VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
103     VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
104     VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
105     VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
106     VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
107     VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
108     VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
109 
110     VBROADCASTSD(ZMM(2), MEM(RAX,  6*8))
111     VBROADCASTSD(ZMM(3), MEM(RAX,  7*8))
112     VBROADCASTSD(ZMM(4), MEM(RAX,  8*8))
113     VBROADCASTSD(ZMM(5), MEM(RAX,  9*8))
114     VBROADCASTSD(ZMM(6), MEM(RAX, 10*8))
115     VBROADCASTSD(ZMM(7), MEM(RAX, 11*8))
116     VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
117     VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
118     VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
119     VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
120     VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
121     VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
122     VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
123     VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
124     VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
125     VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
126     VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
127     VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
128 
129     VMOVAPD(ZMM(0), MEM(RBX,2*64))
130     VMOVAPD(ZMM(1), MEM(RBX,3*64))
131 
132     PREFETCH(0, MEM(RAX, 64*8))
133     PREFETCH(0, MEM(RAX, 72*8))
134 
135     VBROADCASTSD(ZMM(2), MEM(RAX, 12*8)) // Iteration 1
136     VBROADCASTSD(ZMM(3), MEM(RAX, 13*8))
137     VBROADCASTSD(ZMM(4), MEM(RAX, 14*8))
138     VBROADCASTSD(ZMM(5), MEM(RAX, 15*8))
139     VBROADCASTSD(ZMM(6), MEM(RAX, 16*8))
140     VBROADCASTSD(ZMM(7), MEM(RAX, 17*8))
141     VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
142     VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
143     VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
144     VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
145     VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
146     VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
147     VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
148     VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
149     VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
150     VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
151     VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
152     VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
153 
154     VBROADCASTSD(ZMM(2), MEM(RAX, 18*8))
155     VBROADCASTSD(ZMM(3), MEM(RAX, 19*8))
156     VBROADCASTSD(ZMM(4), MEM(RAX, 20*8))
157     VBROADCASTSD(ZMM(5), MEM(RAX, 21*8))
158     VBROADCASTSD(ZMM(6), MEM(RAX, 22*8))
159     VBROADCASTSD(ZMM(7), MEM(RAX, 23*8))
160     VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
161     VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
162     VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
163     VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
164     VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
165     VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
166     VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
167     VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
168     VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
169     VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
170     VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
171     VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
172 
173     VMOVAPD(ZMM(0), MEM(RBX,4*64))
174     VMOVAPD(ZMM(1), MEM(RBX,5*64))
175 
176     PREFETCH(0, MEM(RAX, 80*8))
177     PREFETCH(0, MEM(RAX, 88*8))
178 
179     VBROADCASTSD(ZMM(2), MEM(RAX, 24*8)) // Iteration 2
180     VBROADCASTSD(ZMM(3), MEM(RAX, 25*8))
181     VBROADCASTSD(ZMM(4), MEM(RAX, 26*8))
182     VBROADCASTSD(ZMM(5), MEM(RAX, 27*8))
183     VBROADCASTSD(ZMM(6), MEM(RAX, 28*8))
184     VBROADCASTSD(ZMM(7), MEM(RAX, 29*8))
185     VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
186     VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
187     VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
188     VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
189     VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
190     VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
191     VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
192     VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
193     VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
194     VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
195     VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
196     VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
197 
198     VBROADCASTSD(ZMM(2), MEM(RAX, 30*8))
199     VBROADCASTSD(ZMM(3), MEM(RAX, 31*8))
200     VBROADCASTSD(ZMM(4), MEM(RAX, 32*8))
201     VBROADCASTSD(ZMM(5), MEM(RAX, 33*8))
202     VBROADCASTSD(ZMM(6), MEM(RAX, 34*8))
203     VBROADCASTSD(ZMM(7), MEM(RAX, 35*8))
204     VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
205     VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
206     VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
207     VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
208     VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
209     VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
210     VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
211     VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
212     VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
213     VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
214     VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
215     VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
216 
217     VMOVAPD(ZMM(0), MEM(RBX,6*64))
218     VMOVAPD(ZMM(1), MEM(RBX,7*64))
219 
220     ADD(RBX, IMM(4*8*16))
221     PREFETCH(0, MEM(RAX, 96*8))
222     PREFETCH(0, MEM(RAX, 104*8))
223 
224     VBROADCASTSD(ZMM(2), MEM(RAX, 36*8)) // Iteration 3
225     VBROADCASTSD(ZMM(3), MEM(RAX, 37*8))
226     VBROADCASTSD(ZMM(4), MEM(RAX, 38*8))
227     VBROADCASTSD(ZMM(5), MEM(RAX, 39*8))
228     VBROADCASTSD(ZMM(6), MEM(RAX, 40*8))
229     VBROADCASTSD(ZMM(7), MEM(RAX, 41*8))
230     VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
231     VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
232     VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
233     VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
234     VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
235     VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
236     VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
237     VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
238     VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
239     VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
240     VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
241     VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
242 
243     VBROADCASTSD(ZMM(2), MEM(RAX, 42*8))
244     VBROADCASTSD(ZMM(3), MEM(RAX, 43*8))
245     VBROADCASTSD(ZMM(4), MEM(RAX, 44*8))
246     VBROADCASTSD(ZMM(5), MEM(RAX, 45*8))
247     VBROADCASTSD(ZMM(6), MEM(RAX, 46*8))
248     VBROADCASTSD(ZMM(7), MEM(RAX, 47*8))
249     VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
250     VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
251     VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
252     VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
253     VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
254     VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
255     VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
256     VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
257     VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
258     VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
259     VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
260     VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
261 
262     ADD(RAX, IMM(4*8*12))
263     SUB(RSI, IMM(1))
264 
265     VMOVAPD(ZMM(0), MEM(RBX,0*64))
266     VMOVAPD(ZMM(1), MEM(RBX,1*64))
267 
268     JNZ(.DLOOPKITER)
269 
270     LABEL(.DCONSIDKLEFT)
271 
272     MOV(RSI, VAR(k))
273     AND(RSI, IMM(3)) // rsi = k%4
274     JZ(.DPOSTACCUM)
275 
276     ALIGN16
277     LABEL(.DLOOPKLEFT)
278 
279     VBROADCASTSD(ZMM(2), MEM(RAX, 0*8))
280     VBROADCASTSD(ZMM(3), MEM(RAX, 1*8))
281     VBROADCASTSD(ZMM(4), MEM(RAX, 2*8))
282     VBROADCASTSD(ZMM(5), MEM(RAX, 3*8))
283     VBROADCASTSD(ZMM(6), MEM(RAX, 4*8))
284     VBROADCASTSD(ZMM(7), MEM(RAX, 5*8))
285     VFMADD231PD(ZMM( 8), ZMM(0), ZMM(2))
286     VFMADD231PD(ZMM( 9), ZMM(1), ZMM(2))
287     VFMADD231PD(ZMM(10), ZMM(0), ZMM(3))
288     VFMADD231PD(ZMM(11), ZMM(1), ZMM(3))
289     VFMADD231PD(ZMM(12), ZMM(0), ZMM(4))
290     VFMADD231PD(ZMM(13), ZMM(1), ZMM(4))
291     VFMADD231PD(ZMM(14), ZMM(0), ZMM(5))
292     VFMADD231PD(ZMM(15), ZMM(1), ZMM(5))
293     VFMADD231PD(ZMM(16), ZMM(0), ZMM(6))
294     VFMADD231PD(ZMM(17), ZMM(1), ZMM(6))
295     VFMADD231PD(ZMM(18), ZMM(0), ZMM(7))
296     VFMADD231PD(ZMM(19), ZMM(1), ZMM(7))
297 
298     VBROADCASTSD(ZMM(2), MEM(RAX,  6*8))
299     VBROADCASTSD(ZMM(3), MEM(RAX,  7*8))
300     VBROADCASTSD(ZMM(4), MEM(RAX,  8*8))
301     VBROADCASTSD(ZMM(5), MEM(RAX,  9*8))
302     VBROADCASTSD(ZMM(6), MEM(RAX, 10*8))
303     VBROADCASTSD(ZMM(7), MEM(RAX, 11*8))
304     VFMADD231PD(ZMM(20), ZMM(0), ZMM(2))
305     VFMADD231PD(ZMM(21), ZMM(1), ZMM(2))
306     VFMADD231PD(ZMM(22), ZMM(0), ZMM(3))
307     VFMADD231PD(ZMM(23), ZMM(1), ZMM(3))
308     VFMADD231PD(ZMM(24), ZMM(0), ZMM(4))
309     VFMADD231PD(ZMM(25), ZMM(1), ZMM(4))
310     VFMADD231PD(ZMM(26), ZMM(0), ZMM(5))
311     VFMADD231PD(ZMM(27), ZMM(1), ZMM(5))
312     VFMADD231PD(ZMM(28), ZMM(0), ZMM(6))
313     VFMADD231PD(ZMM(29), ZMM(1), ZMM(6))
314     VFMADD231PD(ZMM(30), ZMM(0), ZMM(7))
315     VFMADD231PD(ZMM(31), ZMM(1), ZMM(7))
316 
317     ADD(RAX, IMM(12*8))
318     ADD(RBX, IMM(16*8))
319     SUB(RSI, IMM(1))
320 
321     VMOVAPD(ZMM(0), MEM(RBX,0*64))
322     VMOVAPD(ZMM(1), MEM(RBX,1*64))
323 
324     JNZ(.DLOOPKLEFT)
325 
326     LABEL(.DPOSTACCUM)
327 
328     MOV(RAX, VAR(alpha))
329     MOV(RBX, VAR(beta))
330     VBROADCASTSD(ZMM(0), MEM(RAX))
331     VBROADCASTSD(ZMM(1), MEM(RBX))
332 
333     VMULPD(ZMM( 8), ZMM( 8), ZMM(0))
334     VMULPD(ZMM( 9), ZMM( 9), ZMM(0))
335     VMULPD(ZMM(10), ZMM(10), ZMM(0))
336     VMULPD(ZMM(11), ZMM(11), ZMM(0))
337     VMULPD(ZMM(12), ZMM(12), ZMM(0))
338     VMULPD(ZMM(13), ZMM(13), ZMM(0))
339     VMULPD(ZMM(14), ZMM(14), ZMM(0))
340     VMULPD(ZMM(15), ZMM(15), ZMM(0))
341     VMULPD(ZMM(16), ZMM(16), ZMM(0))
342     VMULPD(ZMM(17), ZMM(17), ZMM(0))
343     VMULPD(ZMM(18), ZMM(18), ZMM(0))
344     VMULPD(ZMM(19), ZMM(19), ZMM(0))
345     VMULPD(ZMM(20), ZMM(20), ZMM(0))
346     VMULPD(ZMM(21), ZMM(21), ZMM(0))
347     VMULPD(ZMM(22), ZMM(22), ZMM(0))
348     VMULPD(ZMM(23), ZMM(23), ZMM(0))
349     VMULPD(ZMM(24), ZMM(24), ZMM(0))
350     VMULPD(ZMM(25), ZMM(25), ZMM(0))
351     VMULPD(ZMM(26), ZMM(26), ZMM(0))
352     VMULPD(ZMM(27), ZMM(27), ZMM(0))
353     VMULPD(ZMM(28), ZMM(28), ZMM(0))
354     VMULPD(ZMM(29), ZMM(29), ZMM(0))
355     VMULPD(ZMM(30), ZMM(30), ZMM(0))
356     VMULPD(ZMM(31), ZMM(31), ZMM(0))
357 
358     MOV(RDI, VAR(rs_c))
359     SUB(RDI, IMM(1))
360     JNZ(.DGENSTORED)
361 
362     LABEL(.ROWSTORED)
363 
364     MOV(RSI, VAR(cs_c))
365     MOV(R(8), MEM(RBX))
366     LEA(RSI, MEM(,RSI,8))
367     LEA(RDX, MEM(RCX,RSI,4))
368     LEA(RDI, MEM(RCX,RSI,8))
369     LEA(R(13), MEM(RSI,RSI,2))
370     SAL1(R(8)) // shift out the sign bit to check for +/- zero
371     JZ(.DROWSTORBZ)
372 
373     VFMADD231PD(ZMM( 8), ZMM(1), MEM(RCX))
374     VFMADD231PD(ZMM( 9), ZMM(1), MEM(RCX,64))
375     VMOVUPD(MEM(RCX), ZMM( 8))
376     VMOVUPD(MEM(RCX,64), ZMM( 9))
377 
378     VFMADD231PD(ZMM(10), ZMM(1), MEM(RCX,RSI,1))
379     VFMADD231PD(ZMM(11), ZMM(1), MEM(RCX,RSI,1,64))
380     VMOVUPD(MEM(RCX,RSI,1), ZMM(10))
381     VMOVUPD(MEM(RCX,RSI,1,64), ZMM(11))
382 
383     VFMADD231PD(ZMM(12), ZMM(1), MEM(RCX,RSI,2))
384     VFMADD231PD(ZMM(13), ZMM(1), MEM(RCX,RSI,2,64))
385     VMOVUPD(MEM(RCX,RSI,2), ZMM(12))
386     VMOVUPD(MEM(RCX,RSI,2,64), ZMM(13))
387 
388     VFMADD231PD(ZMM(14), ZMM(1), MEM(RCX,R(13),1))
389     VFMADD231PD(ZMM(15), ZMM(1), MEM(RCX,R(13),1,64))
390     VMOVUPD(MEM(RCX,R(13),1), ZMM(14))
391     VMOVUPD(MEM(RCX,R(13),1,64), ZMM(15))
392 
393     VFMADD231PD(ZMM(16), ZMM(1), MEM(RDX))
394     VFMADD231PD(ZMM(17), ZMM(1), MEM(RDX,64))
395     VMOVUPD(MEM(RDX), ZMM(16))
396     VMOVUPD(MEM(RDX,64), ZMM(17))
397 
398     VFMADD231PD(ZMM(18), ZMM(1), MEM(RDX,RSI,1))
399     VFMADD231PD(ZMM(19), ZMM(1), MEM(RDX,RSI,1,64))
400     VMOVUPD(MEM(RDX,RSI,1), ZMM(18))
401     VMOVUPD(MEM(RDX,RSI,1,64), ZMM(19))
402 
403     VFMADD231PD(ZMM(20), ZMM(1), MEM(RDX,RSI,2))
404     VFMADD231PD(ZMM(21), ZMM(1), MEM(RDX,RSI,2,64))
405     VMOVUPD(MEM(RDX,RSI,2), ZMM(20))
406     VMOVUPD(MEM(RDX,RSI,2,64), ZMM(21))
407 
408     VFMADD231PD(ZMM(22), ZMM(1), MEM(RDX,R(13),1))
409     VFMADD231PD(ZMM(23), ZMM(1), MEM(RDX,R(13),1,64))
410     VMOVUPD(MEM(RDX,R(13),1), ZMM(22))
411     VMOVUPD(MEM(RDX,R(13),1,64), ZMM(23))
412 
413     VFMADD231PD(ZMM(24), ZMM(1), MEM(RDI))
414     VFMADD231PD(ZMM(25), ZMM(1), MEM(RDI,64))
415     VMOVUPD(MEM(RDI), ZMM(24))
416     VMOVUPD(MEM(RDI,64), ZMM(25))
417 
418     VFMADD231PD(ZMM(26), ZMM(1), MEM(RDI,RSI,1))
419     VFMADD231PD(ZMM(27), ZMM(1), MEM(RDI,RSI,1,64))
420     VMOVUPD(MEM(RDI,RSI,1), ZMM(26))
421     VMOVUPD(MEM(RDI,RSI,1,64), ZMM(27))
422 
423     VFMADD231PD(ZMM(28), ZMM(1), MEM(RDI,RSI,2))
424     VFMADD231PD(ZMM(29), ZMM(1), MEM(RDI,RSI,2,64))
425     VMOVUPD(MEM(RDI,RSI,2), ZMM(28))
426     VMOVUPD(MEM(RDI,RSI,2,64), ZMM(29))
427 
428     VFMADD231PD(ZMM(30), ZMM(1), MEM(RDI,R(13),1))
429     VFMADD231PD(ZMM(31), ZMM(1), MEM(RDI,R(13),1,64))
430     VMOVUPD(MEM(RDI,R(13),1), ZMM(30))
431     VMOVUPD(MEM(RDI,R(13),1,64), ZMM(31))
432 
433     JMP(.DDONE)
434 
435     LABEL(.DROWSTORBZ)
436 
437     VMOVUPD(MEM(RCX), ZMM( 8))
438     VMOVUPD(MEM(RCX,64), ZMM( 9))
439     VMOVUPD(MEM(RCX,RSI,1), ZMM(10))
440     VMOVUPD(MEM(RCX,RSI,1,64), ZMM(11))
441     VMOVUPD(MEM(RCX,RSI,2), ZMM(12))
442     VMOVUPD(MEM(RCX,RSI,2,64), ZMM(13))
443     VMOVUPD(MEM(RCX,R(13),1), ZMM(14))
444     VMOVUPD(MEM(RCX,R(13),1,64), ZMM(15))
445     VMOVUPD(MEM(RDX), ZMM(16))
446     VMOVUPD(MEM(RDX,64), ZMM(17))
447     VMOVUPD(MEM(RDX,RSI,1), ZMM(18))
448     VMOVUPD(MEM(RDX,RSI,1,64), ZMM(19))
449     VMOVUPD(MEM(RDX,RSI,2), ZMM(20))
450     VMOVUPD(MEM(RDX,RSI,2,64), ZMM(21))
451     VMOVUPD(MEM(RDX,R(13),1), ZMM(22))
452     VMOVUPD(MEM(RDX,R(13),1,64), ZMM(23))
453     VMOVUPD(MEM(RDI), ZMM(24))
454     VMOVUPD(MEM(RDI,64), ZMM(25))
455     VMOVUPD(MEM(RDI,RSI,1), ZMM(26))
456     VMOVUPD(MEM(RDI,RSI,1,64), ZMM(27))
457     VMOVUPD(MEM(RDI,RSI,2), ZMM(28))
458     VMOVUPD(MEM(RDI,RSI,2,64), ZMM(29))
459     VMOVUPD(MEM(RDI,R(13),1), ZMM(30))
460     VMOVUPD(MEM(RDI,R(13),1,64), ZMM(31))
461 
462     JMP(.DDONE)
463 
464     LABEL(.DGENSTORED)
465 
466     MOV(RDI, VAR(cs_c))
467     MOV(RAX, VAR(rs_c))
468     LEA(RDI, MEM(,RDI,8))
469     MOV(R(8), MEM(RBX))
470     VBROADCASTSS(YMM(4), VAR(rs_c))
471     VMOVAPS(YMM(5), VAR(offsetPtr))
472     VPMULLD(YMM(4), YMM(5), YMM(4))
473     LEA(RDX, MEM(RCX,RAX,8))
474     MOV(RSI, 0x3F)
475     SAL1(R(8)) // shift out the sign bit to check for +/- zero
476     JZ(.DGENSTORBZ)
477 
478     KMOV(K(1), ESI)
479     KMOV(K(2), ESI)
480     VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
481     VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
482     VFMADD231PD(ZMM(2), ZMM(1), ZMM( 8))
483     VFMADD231PD(ZMM(3), ZMM(1), ZMM( 9))
484     KMOV(K(1), ESI)
485     KMOV(K(2), ESI)
486     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM( 8))
487     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM( 9))
488     ADD(RCX, RDI)
489     ADD(RDX, RDI)
490 
491     KMOV(K(3), ESI)
492     KMOV(K(4), ESI)
493     VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
494     VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
495     VFMADD231PD(ZMM(2), ZMM(1), ZMM(10))
496     VFMADD231PD(ZMM(3), ZMM(1), ZMM(11))
497     KMOV(K(3), ESI)
498     KMOV(K(4), ESI)
499     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(10))
500     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(11))
501     ADD(RCX, RDI)
502     ADD(RDX, RDI)
503 
504     KMOV(K(1), ESI)
505     KMOV(K(2), ESI)
506     VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
507     VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
508     VFMADD231PD(ZMM(2), ZMM(1), ZMM(12))
509     VFMADD231PD(ZMM(3), ZMM(1), ZMM(13))
510     KMOV(K(1), ESI)
511     KMOV(K(2), ESI)
512     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(12))
513     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(13))
514     ADD(RCX, RDI)
515     ADD(RDX, RDI)
516 
517     KMOV(K(3), ESI)
518     KMOV(K(4), ESI)
519     VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
520     VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
521     VFMADD231PD(ZMM(2), ZMM(1), ZMM(14))
522     VFMADD231PD(ZMM(3), ZMM(1), ZMM(15))
523     KMOV(K(3), ESI)
524     KMOV(K(4), ESI)
525     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(14))
526     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(15))
527     ADD(RCX, RDI)
528     ADD(RDX, RDI)
529 
530     KMOV(K(1), ESI)
531     KMOV(K(2), ESI)
532     VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
533     VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
534     VFMADD231PD(ZMM(2), ZMM(1), ZMM(16))
535     VFMADD231PD(ZMM(3), ZMM(1), ZMM(17))
536     KMOV(K(1), ESI)
537     KMOV(K(2), ESI)
538     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(16))
539     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(17))
540     ADD(RCX, RDI)
541     ADD(RDX, RDI)
542 
543     KMOV(K(3), ESI)
544     KMOV(K(4), ESI)
545     VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
546     VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
547     VFMADD231PD(ZMM(2), ZMM(1), ZMM(18))
548     VFMADD231PD(ZMM(3), ZMM(1), ZMM(19))
549     KMOV(K(3), ESI)
550     KMOV(K(4), ESI)
551     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(18))
552     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(19))
553     ADD(RCX, RDI)
554     ADD(RDX, RDI)
555 
556     KMOV(K(1), ESI)
557     KMOV(K(2), ESI)
558     VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
559     VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
560     VFMADD231PD(ZMM(2), ZMM(1), ZMM(20))
561     VFMADD231PD(ZMM(3), ZMM(1), ZMM(21))
562     KMOV(K(1), ESI)
563     KMOV(K(2), ESI)
564     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(20))
565     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(21))
566     ADD(RCX, RDI)
567     ADD(RDX, RDI)
568 
569     KMOV(K(3), ESI)
570     KMOV(K(4), ESI)
571     VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
572     VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
573     VFMADD231PD(ZMM(2), ZMM(1), ZMM(22))
574     VFMADD231PD(ZMM(3), ZMM(1), ZMM(23))
575     KMOV(K(3), ESI)
576     KMOV(K(4), ESI)
577     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(22))
578     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(23))
579     ADD(RCX, RDI)
580     ADD(RDX, RDI)
581 
582     KMOV(K(1), ESI)
583     KMOV(K(2), ESI)
584     VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
585     VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
586     VFMADD231PD(ZMM(2), ZMM(1), ZMM(24))
587     VFMADD231PD(ZMM(3), ZMM(1), ZMM(25))
588     KMOV(K(1), ESI)
589     KMOV(K(2), ESI)
590     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(24))
591     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(25))
592     ADD(RCX, RDI)
593     ADD(RDX, RDI)
594 
595     KMOV(K(3), ESI)
596     KMOV(K(4), ESI)
597     VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
598     VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
599     VFMADD231PD(ZMM(2), ZMM(1), ZMM(26))
600     VFMADD231PD(ZMM(3), ZMM(1), ZMM(27))
601     KMOV(K(3), ESI)
602     KMOV(K(4), ESI)
603     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(26))
604     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(27))
605     ADD(RCX, RDI)
606     ADD(RDX, RDI)
607 
608     KMOV(K(1), ESI)
609     KMOV(K(2), ESI)
610     VGATHERDPD(ZMM(2) MASK_K(1), MEM(RCX,YMM(4),8))
611     VGATHERDPD(ZMM(3) MASK_K(2), MEM(RDX,YMM(4),8))
612     VFMADD231PD(ZMM(2), ZMM(1), ZMM(28))
613     VFMADD231PD(ZMM(3), ZMM(1), ZMM(29))
614     KMOV(K(1), ESI)
615     KMOV(K(2), ESI)
616     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(28))
617     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(29))
618     ADD(RCX, RDI)
619     ADD(RDX, RDI)
620 
621     KMOV(K(3), ESI)
622     KMOV(K(4), ESI)
623     VGATHERDPD(ZMM(2) MASK_K(3), MEM(RCX,YMM(4),8))
624     VGATHERDPD(ZMM(3) MASK_K(4), MEM(RDX,YMM(4),8))
625     VFMADD231PD(ZMM(2), ZMM(1), ZMM(30))
626     VFMADD231PD(ZMM(3), ZMM(1), ZMM(31))
627     KMOV(K(3), ESI)
628     KMOV(K(4), ESI)
629     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(3), ZMM(30))
630     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(4), ZMM(31))
631     ADD(RCX, RDI)
632     ADD(RDX, RDI)
633 
634     JMP(.DDONE)
635 
636     LABEL(.DGENSTORBZ)
637 
638     KMOV(K(1), ESI)
639     KMOV(K(2), ESI)
640     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM( 8))
641     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM( 9))
642     ADD(RCX, RDI)
643     ADD(RDX, RDI)
644 
645     KMOV(K(1), ESI)
646     KMOV(K(2), ESI)
647     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(10))
648     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(11))
649     ADD(RCX, RDI)
650     ADD(RDX, RDI)
651 
652     KMOV(K(1), ESI)
653     KMOV(K(2), ESI)
654     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(12))
655     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(13))
656     ADD(RCX, RDI)
657     ADD(RDX, RDI)
658 
659     KMOV(K(1), ESI)
660     KMOV(K(2), ESI)
661     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(14))
662     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(15))
663     ADD(RCX, RDI)
664     ADD(RDX, RDI)
665 
666     KMOV(K(1), ESI)
667     KMOV(K(2), ESI)
668     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(16))
669     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(17))
670     ADD(RCX, RDI)
671     ADD(RDX, RDI)
672 
673     KMOV(K(1), ESI)
674     KMOV(K(2), ESI)
675     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(18))
676     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(19))
677     ADD(RCX, RDI)
678     ADD(RDX, RDI)
679 
680     KMOV(K(1), ESI)
681     KMOV(K(2), ESI)
682     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(20))
683     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(21))
684     ADD(RCX, RDI)
685     ADD(RDX, RDI)
686 
687     KMOV(K(1), ESI)
688     KMOV(K(2), ESI)
689     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(22))
690     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(23))
691     ADD(RCX, RDI)
692     ADD(RDX, RDI)
693 
694     KMOV(K(1), ESI)
695     KMOV(K(2), ESI)
696     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(24))
697     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(25))
698     ADD(RCX, RDI)
699     ADD(RDX, RDI)
700 
701     KMOV(K(1), ESI)
702     KMOV(K(2), ESI)
703     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(26))
704     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(27))
705     ADD(RCX, RDI)
706     ADD(RDX, RDI)
707 
708     KMOV(K(1), ESI)
709     KMOV(K(2), ESI)
710     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(28))
711     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(29))
712     ADD(RCX, RDI)
713     ADD(RDX, RDI)
714 
715     KMOV(K(1), ESI)
716     KMOV(K(2), ESI)
717     VSCATTERDPD(MEM(RCX,YMM(4),8) MASK_K(1), ZMM(30))
718     VSCATTERDPD(MEM(RDX,YMM(4),8) MASK_K(2), ZMM(31))
719     ADD(RCX, RDI)
720     ADD(RDX, RDI)
721 
722     LABEL(.DDONE)
723 
724 	: // output operands (none)
725     : // input operands
726       [k]         "m" (k),
727       [a]         "m" (a),
728       [b]         "m" (b),
729       [alpha]     "m" (alpha),
730       [beta]      "m" (beta),
731       [c]         "m" (c),
732       [rs_c]      "m" (rs_c),
733       [cs_c]      "m" (cs_c),
734       //[a_next]    "m" (a_next),
735       //[b_next]    "m" (b_next),
736       [offsetPtr] "m" (offsetPtr)
737     : // register clobber list
738       "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12",
739       "r13", "r14", "r15", "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5",
740       "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13",
741       "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21",
742       "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29",
743       "zmm30", "zmm31", "memory"
744 	);
745 }
746