1/**************************************************************************************************
2*                                                                                                 *
3* This file is part of BLASFEO.                                                                   *
4*                                                                                                 *
5* BLASFEO -- BLAS For Embedded Optimization.                                                      *
6* Copyright (C) 2019 by Gianluca Frison.                                                          *
7* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl.              *
8* All rights reserved.                                                                            *
9*                                                                                                 *
10* The 2-Clause BSD License                                                                        *
11*                                                                                                 *
12* Redistribution and use in source and binary forms, with or without                              *
13* modification, are permitted provided that the following conditions are met:                     *
14*                                                                                                 *
15* 1. Redistributions of source code must retain the above copyright notice, this                  *
16*    list of conditions and the following disclaimer.                                             *
17* 2. Redistributions in binary form must reproduce the above copyright notice,                    *
18*    this list of conditions and the following disclaimer in the documentation                    *
19*    and/or other materials provided with the distribution.                                       *
20*                                                                                                 *
21* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND                 *
22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED                   *
23* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                          *
24* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR                 *
25* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES                  *
26* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;                    *
27* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND                     *
28* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT                      *
29* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS                   *
30* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                    *
31*                                                                                                 *
32* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de                             *
33*                                                                                                 *
34**************************************************************************************************/
35
36//	// prologue
37//	stmdb	sp!, {r4 - r10, fp, lr} // save GP registers
38//	add		fp, sp, #36 // fp to old sp position
39//	fstmfdd	sp!, {d8-d15} // save FP registers
40#define PROLOGUE \
41	stmdb	sp!, {r4 - r10, fp, lr}; \
42	add		fp, sp, #36; \
43	fstmfdd	sp!, {d8-d15};
44//	// epilogue
45//	fldmfdd	sp!, {d8-d15} // load FP registers
46//	ldmia	sp!, {r4 - r10, fp, pc} // load GP registers and return
47#define EPILOGUE \
48	fldmfdd	sp!, {d8-d15}; \
49	ldmia	sp!, {r4 - r10, fp, pc};
50
51
52
53#if defined(OS_LINUX)
54	.text
55#elif defined(OS_MAC)
56	.section	__TEXT,__text,regular,pure_instructions
57#endif
58
59
60
61
62
63// subroutine
64//
65// input arguments:
66// r4   <- k
67// r5   <- A
68// r6   <- sda*ps*sizeof(float)
69// r7   <- B
70//
71// output arguments:
72
73#if MACRO_LEVEL>=2
74	.macro INNER_KERNEL_GEMM_ADD_NT_8X4_LIB4
75#else
76//	.p2align 4,,15
77#if defined(OS_LINUX)
78	.type inner_kernel_gemm_add_nt_8x4_lib4, %function
79inner_kernel_gemm_add_nt_8x4_lib4:
80#elif defined(OS_MAC)
81_inner_kernel_gemm_add_nt_8x4_lib4:
82#endif
83#endif
84
85	// early return
86	cmp		r4, #0
87	ble		2f // return
88
89	add		r8, r5, r6 // A1
90
91	// prefetch
92	pld		[r7, #0]
93	pld		[r5, #0]
94	pld		[r8, #0]
95#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
96	pld		[r7, #32]
97	pld		[r5, #32]
98	pld		[r8, #32]
99#endif
100	pld		[r7, #64]
101#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
102	pld		[r5, #64]
103	pld		[r8, #64]
104#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
105	pld		[r7, #96]
106	pld		[r5, #96]
107	pld		[r8, #96]
108#endif
109#else // cortex a15
110	// preload
111	vld1.64		{d0, d1}, [r7:128]! // B // TODO preload B in d0-d3 too ?????
112	vld1.64		{d2, d3}, [r7:128]! // B
113	vld1.64		{d4, d5}, [r7:128]! // B // TODO preload B in d0-d3 too ?????
114	vld1.64		{d6, d7}, [r7:128]! // B
115	vld1.64		{d24, d25}, [r5:128]! // A0
116	vld1.64		{d28, d29}, [r5:128]! // A0
117	vld1.64		{d26, d27}, [r8:128] // A1
118
119	sub		r7, r7, #64
120	sub		r5, r5, #32
121#endif
122
123	cmp		r4, #4
124	ble		0f // consider clean up loop
125
126	// main loop
1271:
128
129#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
130
131	vld1.64		{d0, d1}, [r7:128]! // B
132	vld1.64		{d24, d25}, [r5:128]! // A0
133	vld1.64		{d28, d29}, [r8:128]! // A1
134
135	vld1.64		{d2, d3}, [r7:128]! // B
136	vld1.64		{d26, d27}, [r5:128]! // A0
137	vld1.64		{d30, d31}, [r8:128]! // A1
138
139	// prefetch
140
141	// unroll 0
142	vmla.f32	q4, q12, d0[0]
143	pld		[r7, #96]
144	vmla.f32	q5, q12, d0[1]
145	pld		[r5, #96]
146	vmla.f32	q6, q12, d1[0]
147	pld		[r8, #96]
148	vmla.f32	q7, q12, d1[1]
149	vmla.f32	q8, q14, d0[0]
150	vmla.f32	q9, q14, d0[1]
151	vmla.f32	q10, q14, d1[0]
152	vmla.f32	q11, q14, d1[1]
153
154	// unroll 1
155	vmla.f32	q4, q13, d2[0]
156	vmla.f32	q5, q13, d2[1]
157	vmla.f32	q6, q13, d3[0]
158	vmla.f32	q7, q13, d3[1]
159	vmla.f32	q8, q15, d2[0]
160	vmla.f32	q9, q15, d2[1]
161	vmla.f32	q10, q15, d3[0]
162	vmla.f32	q11, q15, d3[1]
163
164	vld1.64		{d0, d1}, [r7:128]! // B
165	vld1.64		{d24, d25}, [r5:128]! // A0
166	vld1.64		{d28, d29}, [r8:128]! // A1
167
168	vld1.64		{d2, d3}, [r7:128]! // B
169	vld1.64		{d26, d27}, [r5:128]! // A0
170	vld1.64		{d30, d31}, [r8:128]! // A1
171
172	// unroll 2
173	vmla.f32	q4, q12, d0[0]
174#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
175	pld		[r7, #96]
176#endif
177	vmla.f32	q5, q12, d0[1]
178#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
179	pld		[r5, #96]
180#endif
181	vmla.f32	q6, q12, d1[0]
182#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
183	pld		[r8, #96]
184#endif
185	vmla.f32	q7, q12, d1[1]
186	vmla.f32	q8, q14, d0[0]
187	vmla.f32	q9, q14, d0[1]
188	vmla.f32	q10, q14, d1[0]
189	vmla.f32	q11, q14, d1[1]
190
191	// unroll 3
192	vmla.f32	q4, q13, d2[0]
193	vmla.f32	q5, q13, d2[1]
194	vmla.f32	q6, q13, d3[0]
195	vmla.f32	q7, q13, d3[1]
196	vmla.f32	q8, q15, d2[0]
197	vmla.f32	q9, q15, d2[1]
198	vmla.f32	q10, q15, d3[0]
199	vmla.f32	q11, q15, d3[1]
200
201	sub		r4, r4, #4
202
203#else // cortex a15
204
205	// unroll 0
206	pld		[r5, #64] // A0
207	vmla.f32	q4, q12, d0[0]
208	vldr		d30, [r8, #16] // A1
209	vmla.f32	q5, q12, d0[1]
210	vldr		d31, [r8, #24] // A1
211	vmla.f32	q6, q12, d1[0]
212	pld		[r7, #128] // B
213	vmla.f32	q7, q12, d1[1]
214	vldr		d24, [r5, #32]
215	vmla.f32	q8, q13, d0[0]
216	vldr		d25, [r5, #40]
217	vmla.f32	q9, q13, d0[1]
218	vldr		d0, [r7, #64]
219	vmla.f32	q10, q13, d1[0]
220	pld		[r8, #64] // A1
221	vmla.f32	q11, q13, d1[1]
222	vldr		d1, [r7, #72]
223
224	// unroll 1
225	vmla.f32	q4, q14, d2[0]
226	vldr		d26, [r8, #32] // A1
227	vmla.f32	q5, q14, d2[1]
228	vldr		d27, [r8, #40] // A1
229	vmla.f32	q6, q14, d3[0]
230	vmla.f32	q7, q14, d3[1]
231	vldr		d28, [r5, #48]
232	vmla.f32	q8, q15, d2[0]
233	vldr		d29, [r5, #56]
234	vmla.f32	q9, q15, d2[1]
235	vldr		d2, [r7, #80]
236	vmla.f32	q10, q15, d3[0]
237	add		r5, r5, #64
238	vmla.f32	q11, q15, d3[1]
239	vldr		d3, [r7, #88]
240
241	// unroll 2
242	vmla.f32	q4, q12, d4[0]
243	vldr		d30, [r8, #48] // A1
244	vmla.f32	q5, q12, d4[1]
245	vldr		d31, [r8, #56] // A1
246	vmla.f32	q6, q12, d5[0]
247	add		r7, r7, #64
248	vmla.f32	q7, q12, d5[1]
249	vldr		d24, [r5, #0]
250	vmla.f32	q8, q13, d4[0]
251	vldr		d25, [r5, #8]
252	vmla.f32	q9, q13, d4[1]
253	vldr		d4, [r7, #32]
254	vmla.f32	q10, q13, d5[0]
255	add		r8, r8, #64
256	vmla.f32	q11, q13, d5[1]
257	vldr		d5, [r7, #40]
258
259	// unroll 3
260	vmla.f32	q4, q14, d6[0]
261	vldr		d26, [r8, #0] // A1
262	vmla.f32	q5, q14, d6[1]
263	vldr		d27, [r8, #8] // A1
264	vmla.f32	q6, q14, d7[0]
265	sub		r4, r4, #4
266	vmla.f32	q7, q14, d7[1]
267	vldr		d28, [r5, #16]
268	vmla.f32	q8, q15, d6[0]
269	vldr		d29, [r5, #24]
270	vmla.f32	q9, q15, d6[1]
271	vldr		d6, [r7, #48]
272	vmla.f32	q10, q15, d7[0]
273	vmla.f32	q11, q15, d7[1]
274	vldr		d7, [r7, #56]
275
276#endif
277
278	cmp		r4, #4
279	bgt		1b
280
2810:
282
283	cmp		r4, #3
284	ble		4f
285
286
287#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
288
289	vld1.64		{d0, d1}, [r7:128]! // B
290	vld1.64		{d24, d25}, [r5:128]! // A0
291	vld1.64		{d28, d29}, [r8:128]! // A1
292
293	vld1.64		{d2, d3}, [r7:128]! // B
294	vld1.64		{d26, d27}, [r5:128]! // A0
295	vld1.64		{d30, d31}, [r8:128]! // A1
296
297	// prefetch
298
299	// unroll 0
300	vmla.f32	q4, q12, d0[0]
301//	pld		[r7, #64]
302	vmla.f32	q5, q12, d0[1]
303//	pld		[r5, #64]
304	vmla.f32	q6, q12, d1[0]
305//	pld		[r8, #64]
306	vmla.f32	q7, q12, d1[1]
307	vmla.f32	q8, q14, d0[0]
308	vmla.f32	q9, q14, d0[1]
309	vmla.f32	q10, q14, d1[0]
310	vmla.f32	q11, q14, d1[1]
311
312	// unroll 1
313	vmla.f32	q4, q13, d2[0]
314	vmla.f32	q5, q13, d2[1]
315	vmla.f32	q6, q13, d3[0]
316	vmla.f32	q7, q13, d3[1]
317	vmla.f32	q8, q15, d2[0]
318	vmla.f32	q9, q15, d2[1]
319	vmla.f32	q10, q15, d3[0]
320	vmla.f32	q11, q15, d3[1]
321
322	vld1.64		{d0, d1}, [r7:128]! // B
323	vld1.64		{d24, d25}, [r5:128]! // A0
324	vld1.64		{d28, d29}, [r8:128]! // A1
325
326	vld1.64		{d2, d3}, [r7:128]! // B
327	vld1.64		{d26, d27}, [r5:128]! // A0
328	vld1.64		{d30, d31}, [r8:128]! // A1
329
330	// unroll 2
331	vmla.f32	q4, q12, d0[0]
332	vmla.f32	q5, q12, d0[1]
333	vmla.f32	q6, q12, d1[0]
334	vmla.f32	q7, q12, d1[1]
335	vmla.f32	q8, q14, d0[0]
336	vmla.f32	q9, q14, d0[1]
337	vmla.f32	q10, q14, d1[0]
338	vmla.f32	q11, q14, d1[1]
339
340	// unroll 3
341	vmla.f32	q4, q13, d2[0]
342	vmla.f32	q5, q13, d2[1]
343	vmla.f32	q6, q13, d3[0]
344	vmla.f32	q7, q13, d3[1]
345	vmla.f32	q8, q15, d2[0]
346	vmla.f32	q9, q15, d2[1]
347	vmla.f32	q10, q15, d3[0]
348	vmla.f32	q11, q15, d3[1]
349
350	sub		r4, r4, #4
351
352#else // cortex a15
353
354	// unroll 0
355	vmla.f32	q4, q12, d0[0]
356	vldr		d30, [r8, #16] // A1
357	vmla.f32	q5, q12, d0[1]
358	vldr		d31, [r8, #24] // A1
359	vmla.f32	q6, q12, d1[0]
360	vmla.f32	q7, q12, d1[1]
361	vldr		d24, [r5, #32]
362	vmla.f32	q8, q13, d0[0]
363	vldr		d25, [r5, #40]
364	vmla.f32	q9, q13, d0[1]
365//	vldr		d4, [r7, #64]
366	vmla.f32	q10, q13, d1[0]
367	vmla.f32	q11, q13, d1[1]
368//	vldr		d5, [r7, #72]
369
370	// unroll 1
371	vmla.f32	q4, q14, d2[0]
372	vldr		d26, [r8, #32] // A1
373	vmla.f32	q5, q14, d2[1]
374	vldr		d27, [r8, #40] // A1
375	vmla.f32	q6, q14, d3[0]
376	vmla.f32	q7, q14, d3[1]
377	vldr		d28, [r5, #48]
378	vmla.f32	q8, q15, d2[0]
379	vldr		d29, [r5, #56]
380	vmla.f32	q9, q15, d2[1]
381//	vldr		d6, [r7, #80]
382	vmla.f32	q10, q15, d3[0]
383//	add		r5, r5, #64
384	vmla.f32	q11, q15, d3[1]
385//	vldr		d7, [r7, #88]
386
387	// unroll 2
388	vmla.f32	q4, q12, d4[0]
389	vldr		d30, [r8, #48] // A1
390	vmla.f32	q5, q12, d4[1]
391	vldr		d31, [r8, #56] // A1
392	vmla.f32	q6, q12, d5[0]
393//	add		r7, r7, #64
394	vmla.f32	q7, q12, d5[1]
395//	vldr		d24, [r5, #0]
396	vmla.f32	q8, q13, d4[0]
397//	vldr		d25, [r5, #8]
398	vmla.f32	q9, q13, d4[1]
399//	vldr		d4, [r7, #32]
400	vmla.f32	q10, q13, d5[0]
401//	add		r8, r8, #64
402	vmla.f32	q11, q13, d5[1]
403//	vldr		d5, [r7, #40]
404
405	// unroll 3
406	vmla.f32	q4, q14, d6[0]
407//	vldr		d26, [r8, #0] // A1
408	vmla.f32	q5, q14, d6[1]
409//	vldr		d27, [r8, #8] // A1
410	vmla.f32	q6, q14, d7[0]
411	sub		r4, r4, #4
412	vmla.f32	q7, q14, d7[1]
413//	vldr		d28, [r5, #16]
414	vmla.f32	q8, q15, d6[0]
415//	vldr		d29, [r5, #24]
416	vmla.f32	q9, q15, d6[1]
417//	vldr		d6, [r7, #48]
418	vmla.f32	q10, q15, d7[0]
419	vmla.f32	q11, q15, d7[1]
420//	vldr		d7, [r7, #56]
421
422#endif
423
424	b		2f // return
425
4264: // consider clean1-up loop
427
428	cmp		r4, #0
429	ble		2f // return
430
431//	sub		r5, r5, #32 // A0
432//	sub		r7, r7, #32 // B
433//	sub		r8, r8, #16 // A1
434
4353: // clean1-up loop
436
437#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
438
439	// unroll 0
440	vld1.64		{d4, d5}, [r7:128]! // B
441	vld1.64		{d0, d1}, [r5:128]! // A0
442	vld1.64		{d2, d3}, [r8:128]! // A1
443	vmla.f32	q4, q0, d4[0]
444	vmla.f32	q5, q0, d4[1]
445	vmla.f32	q6, q0, d5[0]
446	vmla.f32	q7, q0, d5[1]
447	vmla.f32	q8, q1, d4[0]
448	vmla.f32	q9, q1, d4[1]
449	vmla.f32	q10, q1, d5[0]
450	vmla.f32	q11, q1, d5[1]
451
452#else // cortex a15
453
454	// unroll 0
455	vld1.64		{d4, d5}, [r7:128]! // B
456	vld1.64		{d0, d1}, [r5:128]! // A0
457	vmla.f32	q4, q0, d4[0]
458	vmla.f32	q5, q0, d4[1]
459	vmla.f32	q6, q0, d5[0]
460	vmla.f32	q7, q0, d5[1]
461	vld1.64		{d0, d1}, [r8:128]! // A1
462	vmla.f32	q8, q0, d4[0]
463	vmla.f32	q9, q0, d4[1]
464	vmla.f32	q10, q0, d5[0]
465	vmla.f32	q11, q0, d5[1]
466
467#endif
468
469	sub		r4, r4, #1
470	cmp		r4, #0
471	bgt		3b
472
4732: // return
474
475
476#if MACRO_LEVEL>=2
477	.endm
478#else
479	mov		pc, lr // return
480
481#if defined(OS_LINUX)
482	.size	inner_kernel_gemm_add_nt_8x4_lib4, .-inner_kernel_gemm_add_nt_8x4_lib4
483#endif
484#endif
485
486
487
488
489
490// subroutine
491//
492// input arguments:
493// r4   <- k
494// r5   <- A
495// r6   <- sda*ps*sizeof(float)
496// r7   <- B
497// r8   <- sdb*ps*sizeof(float)
498//
499// output arguments:
500
501#if MACRO_LEVEL>=2
502	.macro INNER_KERNEL_GEMM_ADD_NN_8X4_LIB4
503#else
504//	.p2align 4,,15
505#if defined(OS_LINUX)
506	.type inner_kernel_gemm_add_nn_8x4_lib4, %function
507inner_kernel_gemm_add_nn_8x4_lib4:
508#elif defined(OS_MAC)
509_inner_kernel_gemm_add_nn_8x4_lib4:
510#endif
511#endif
512
513	// early return
514	cmp		r4, #0
515	ble		2f // return
516
517	add		r9, r5, r6 // A1
518
519//	add		r11, r8, #32
520
521	// prefetch
522	pld		[r7, #0] // B
523	pld		[r5, #0] // A0
524	pld		[r9, #0] // A1
525#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
526	pld		[r7, #32]
527	pld		[r5, #32]
528	pld		[r9, #32]
529#endif
530	pld		[r7, r8] // B
531#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
532	pld		[r5, #64] // A0
533	pld		[r9, #64] // A1
534#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
535//	pld		[r7, r11]
536	pld		[r5, #96]
537	pld		[r9, #96]
538#endif
539#else // cortex a15
540	// TODO prefetch???
541
542	// preload
543	vldr		d0, [r7, #0] // B
544	vldr		d1, [r7, #8] // B
545	vldr		d2, [r7, #16] // B
546	vldr		d3, [r7, #24] // B
547	vldr		d4, [r7, #32] // B
548//	vldr		d5, [r7, #40] // B
549	vldr		d6, [r7, #48] // B
550//	vldr		d7, [r7, #56] // B
551	vldr		d24, [r5, #0] // A0
552	vldr		d25, [r5, #8] // A0
553	vldr		d28, [r5, #16] // A0
554	vldr		d29, [r5, #24] // A0
555	vldr		d26, [r9, #0] // A1
556	vldr		d27, [r9, #8] // A1
557#endif
558
559	add		r10, r8, r8
560//	add		r11, r11, r8
561
562	cmp		r4, #4
563	ble		0f // consider clean up loop
564
565	// main loop
5661:
567
568#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
569
570	vld1.64		{d0, d1, d2, d3}, [r7:128]! // B
571
572	vld1.64		{d24, d25}, [r5:128]! // A0
573	vld1.64		{d28, d29}, [r9:128]! // A1
574
575	vld1.64		{d4, d5, d6, d7}, [r7:128]! // B
576
577	vld1.64		{d26, d27}, [r5:128]! // A0
578	vld1.64		{d30, d31}, [r9:128]! // A1
579
580	sub		r7, r7, #64
581
582	// prefetch
583
584	// unroll 0
585	vmla.f32	q4, q12, d0[0]
586	pld		[r7, r10]
587	vmla.f32	q5, q12, d2[0]
588	pld		[r5, #96]
589	vmla.f32	q6, q12, d4[0]
590	pld		[r9, #96]
591	vmla.f32	q7, q12, d6[0]
592	add		r10, r10, #32
593	vmla.f32	q8, q14, d0[0]
594	vmla.f32	q9, q14, d2[0]
595	vmla.f32	q10, q14, d4[0]
596	vmla.f32	q11, q14, d6[0]
597
598	// unroll 1
599	vmla.f32	q4, q13, d0[1]
600	vmla.f32	q5, q13, d2[1]
601	vmla.f32	q6, q13, d4[1]
602	vmla.f32	q7, q13, d6[1]
603	vmla.f32	q8, q15, d0[1]
604	vmla.f32	q9, q15, d2[1]
605	vmla.f32	q10, q15, d4[1]
606	vmla.f32	q11, q15, d6[1]
607
608	vld1.64		{d24, d25}, [r5:128]! // A0
609	vld1.64		{d28, d29}, [r9:128]! // A1
610
611	vld1.64		{d26, d27}, [r5:128]! // A0
612	vld1.64		{d30, d31}, [r9:128]! // A1
613
614	// unroll 2
615	vmla.f32	q4, q12, d1[0]
616#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
617//	pld		[r7, r11]
618	pld		[r7, r10]
619#endif
620	vmla.f32	q5, q12, d3[0]
621#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
622	pld		[r5, #96]
623#endif
624	vmla.f32	q6, q12, d5[0]
625#if defined(TARGET_ARMV7A_ARM_CORTEX_A9)
626	pld		[r9, #96]
627#endif
628	vmla.f32	q7, q12, d7[0]
629	add		r10, r8, r8
630	vmla.f32	q8, q14, d1[0]
631	vmla.f32	q9, q14, d3[0]
632	vmla.f32	q10, q14, d5[0]
633	vmla.f32	q11, q14, d7[0]
634
635	// unroll 3
636	vmla.f32	q4, q13, d1[1]
637	vmla.f32	q5, q13, d3[1]
638	vmla.f32	q6, q13, d5[1]
639	vmla.f32	q7, q13, d7[1]
640	vmla.f32	q8, q15, d1[1]
641	vmla.f32	q9, q15, d3[1]
642	vmla.f32	q10, q15, d5[1]
643	vmla.f32	q11, q15, d7[1]
644
645	add		r7, r7, r8
646	sub		r4, r4, #4
647
648#else // cortex a15
649
650	// unroll 0
651
652	vldr		d30, [r9, #16] // A1
653	vmla.f32	q4, q12, d0[0]
654	vldr		d31, [r9, #24] // A1
655	vmla.f32	q5, q12, d2[0]
656	vldr		d5, [r7, #40] // B
657	vmla.f32	q6, q12, d4[0]
658	vldr		d7, [r7, #56] // B
659	vmla.f32	q7, q12, d6[0]
660	vldr		d24, [r5, #32] // A0
661	vmla.f32	q8, q13, d0[0]
662	vldr		d25, [r5, #40] // A0
663	vmla.f32	q9, q13, d2[0]
664	pld		[r7, r10] // B
665	vmla.f32	q10, q13, d4[0]
666	pld		[r5, #64] // A0
667	vmla.f32	q11, q13, d6[0]
668
669	// unroll 1
670	vldr		d26, [r9, #32] // A1
671	vmla.f32	q4, q14, d0[1]
672	vldr		d27, [r9, #40] // A1
673	vmla.f32	q5, q14, d2[1]
674	pld		[r9, #64] // A1
675	vmla.f32	q6, q14, d4[1]
676	add		r7, r7, r8
677	vmla.f32	q7, q14, d6[1]
678	vldr		d28, [r5, #48] // A0
679	vmla.f32	q8, q15, d0[1]
680	vldr		d29, [r5, #56] // A0
681	vmla.f32	q9, q15, d2[1]
682	vldr		d0, [r7, #0] // B
683	vmla.f32	q10, q15, d4[1]
684	vldr		d2, [r7, #16] // B
685	vmla.f32	q11, q15, d6[1]
686
687
688	// unroll 2
689	vldr		d30, [r9, #48] // A1
690	vmla.f32	q4, q12, d1[0]
691	vldr		d31, [r9, #56] // A1
692	vmla.f32	q5, q12, d3[0]
693	vldr		d4, [r7, #32] // B
694	vmla.f32	q6, q12, d5[0]
695	vldr		d6, [r7, #48] // B
696	vmla.f32	q7, q12, d7[0]
697	vldr		d24, [r5, #64] // A0
698	vmla.f32	q8, q13, d1[0]
699	vldr		d25, [r5, #72] // A0
700	vmla.f32	q9, q13, d3[0]
701	add		r5, r5, #64
702	vmla.f32	q10, q13, d5[0]
703	add		r9, r9, #64
704	vmla.f32	q11, q13, d7[0]
705
706	// unroll 3
707	vldr		d26, [r9, #0] // A1
708	vmla.f32	q4, q14, d1[1]
709	vldr		d27, [r9, #8] // A1
710	vmla.f32	q5, q14, d3[1]
711	vmla.f32	q6, q14, d5[1]
712	sub		r4, r4, #4
713	vmla.f32	q7, q14, d7[1]
714	vldr		d28, [r5, #16] // A0
715	vmla.f32	q8, q15, d1[1]
716	vldr		d29, [r5, #24] // A0
717	vmla.f32	q9, q15, d3[1]
718	vldr		d1, [r7, #8] // B
719	vmla.f32	q10, q15, d5[1]
720	vldr		d3, [r7, #24] // B
721	vmla.f32	q11, q15, d7[1]
722
723#endif
724
725	cmp		r4, #4
726	bgt		1b
727
7280:
729
730	cmp		r4, #3
731	ble		4f
732
733
734#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
735
736	vld1.64		{d0, d1, d2, d3}, [r7:128]! // B
737
738	vld1.64		{d24, d25}, [r5:128]! // A0
739	vld1.64		{d28, d29}, [r9:128]! // A1
740
741	vld1.64		{d4, d5, d6, d7}, [r7:128]! // B
742
743	vld1.64		{d26, d27}, [r5:128]! // A0
744	vld1.64		{d30, d31}, [r9:128]! // A1
745
746	sub		r7, r7, #64
747
748	// prefetch
749
750	// unroll 0
751	vmla.f32	q4, q12, d0[0]
752//	pld		[r7, r10]
753	vmla.f32	q5, q12, d2[0]
754//	pld		[r5, #96]
755	vmla.f32	q6, q12, d4[0]
756//	pld		[r8, #96]
757	vmla.f32	q7, q12, d6[0]
758	vmla.f32	q8, q14, d0[0]
759	vmla.f32	q9, q14, d2[0]
760	vmla.f32	q10, q14, d4[0]
761	vmla.f32	q11, q14, d6[0]
762
763	// unroll 1
764	vmla.f32	q4, q13, d0[1]
765	vmla.f32	q5, q13, d2[1]
766	vmla.f32	q6, q13, d4[1]
767	vmla.f32	q7, q13, d6[1]
768	vmla.f32	q8, q15, d0[1]
769	vmla.f32	q9, q15, d2[1]
770	vmla.f32	q10, q15, d4[1]
771	vmla.f32	q11, q15, d6[1]
772
773	vld1.64		{d24, d25}, [r5:128]! // A0
774	vld1.64		{d28, d29}, [r9:128]! // A1
775
776	vld1.64		{d26, d27}, [r5:128]! // A0
777	vld1.64		{d30, d31}, [r9:128]! // A1
778
779	// unroll 2
780	vmla.f32	q4, q12, d1[0]
781	vmla.f32	q5, q12, d3[0]
782	vmla.f32	q6, q12, d5[0]
783	vmla.f32	q7, q12, d7[0]
784	vmla.f32	q8, q14, d1[0]
785	vmla.f32	q9, q14, d3[0]
786	vmla.f32	q10, q14, d5[0]
787	vmla.f32	q11, q14, d7[0]
788
789	// unroll 3
790	vmla.f32	q4, q13, d1[1]
791	vmla.f32	q5, q13, d3[1]
792	vmla.f32	q6, q13, d5[1]
793	vmla.f32	q7, q13, d7[1]
794	vmla.f32	q8, q15, d1[1]
795	vmla.f32	q9, q15, d3[1]
796	vmla.f32	q10, q15, d5[1]
797	vmla.f32	q11, q15, d7[1]
798
799	add		r7, r7, r8
800	sub		r4, r4, #4
801
802#else // cortex a15
803
804	// unroll 0
805
806	vldr		d30, [r9, #16] // A1
807	vmla.f32	q4, q12, d0[0]
808	vldr		d31, [r9, #24] // A1
809	vmla.f32	q5, q12, d2[0]
810	vldr		d5, [r7, #40] // B
811	vmla.f32	q6, q12, d4[0]
812	vldr		d7, [r7, #56] // B
813	vmla.f32	q7, q12, d6[0]
814	vldr		d24, [r5, #32] // A0
815	vmla.f32	q8, q13, d0[0]
816	vldr		d25, [r5, #40] // A0
817	vmla.f32	q9, q13, d2[0]
818//	pld		[r7, r10] // B
819	vmla.f32	q10, q13, d4[0]
820//	pld		[r5, #64] // A0
821	vmla.f32	q11, q13, d6[0]
822
823	// unroll 1
824	vldr		d26, [r9, #32] // A1
825	vmla.f32	q4, q14, d0[1]
826	vldr		d27, [r9, #40] // A1
827	vmla.f32	q5, q14, d2[1]
828//	pld		[r9, #64] // A1
829	vmla.f32	q6, q14, d4[1]
830	add		r7, r7, r8
831	vmla.f32	q7, q14, d6[1]
832	vldr		d28, [r5, #48] // A0
833	vmla.f32	q8, q15, d0[1]
834	vldr		d29, [r5, #56] // A0
835	vmla.f32	q9, q15, d2[1]
836//	vldr		d0, [r7, #0] // B
837	vmla.f32	q10, q15, d4[1]
838//	vldr		d2, [r7, #16] // B
839	vmla.f32	q11, q15, d6[1]
840
841
842	// unroll 2
843	vldr		d30, [r9, #48] // A1
844	vmla.f32	q4, q12, d1[0]
845	vldr		d31, [r9, #56] // A1
846	vmla.f32	q5, q12, d3[0]
847//	vldr		d4, [r7, #32] // B
848	vmla.f32	q6, q12, d5[0]
849//	vldr		d6, [r7, #48] // B
850	vmla.f32	q7, q12, d7[0]
851//	vldr		d24, [r5, #64] // A0
852	vmla.f32	q8, q13, d1[0]
853//	vldr		d25, [r5, #72] // A0
854	vmla.f32	q9, q13, d3[0]
855	add		r5, r5, #64
856	vmla.f32	q10, q13, d5[0]
857	add		r9, r9, #64
858	vmla.f32	q11, q13, d7[0]
859
860	// unroll 3
861//	vldr		d26, [r9, #0] // A1
862	vmla.f32	q4, q14, d1[1]
863//	vldr		d27, [r9, #8] // A1
864	vmla.f32	q5, q14, d3[1]
865	vmla.f32	q6, q14, d5[1]
866	sub		r4, r4, #4
867	vmla.f32	q7, q14, d7[1]
868//	vldr		d28, [r5, #16] // A0
869	vmla.f32	q8, q15, d1[1]
870//	vldr		d29, [r5, #24] // A0
871	vmla.f32	q9, q15, d3[1]
872//	vldr		d1, [r7, #8] // B
873	vmla.f32	q10, q15, d5[1]
874//	vldr		d3, [r7, #24] // B
875	vmla.f32	q11, q15, d7[1]
876
877#endif
878
879	b		2f // return
880
8814: // consider clean1-up loop
882
883	cmp		r4, #0
884	ble		2f // return
885
886//	sub		r5, r5, #32 // A0
887//	sub		r7, r7, #32 // B
888//	sub		r8, r8, #16 // A1
889
8903: // clean1-up loop
891
892#if defined(TARGET_ARMV7A_ARM_CORTEX_A9) | defined(TARGET_ARMV7A_ARM_CORTEX_A7)
893
894	// unroll 0
895	vld1.64		{d0, d1}, [r5:128]! // A0
896	vld1.64		{d2, d3}, [r9:128]! // A1
897	vldr		s8, [r7, #0]  // B[0]
898	vldr		s9, [r7, #16] // B[4]
899	vldr		s10, [r7, #32] // B[8]
900	vldr		s11, [r7, #48] // B[12]
901	vmla.f32	q4, q0, d4[0]
902	vmla.f32	q5, q0, d4[1]
903	vmla.f32	q6, q0, d5[0]
904	vmla.f32	q7, q0, d5[1]
905	vmla.f32	q8, q1, d4[0]
906	vmla.f32	q9, q1, d4[1]
907	vmla.f32	q10, q1, d5[0]
908	vmla.f32	q11, q1, d5[1]
909
910#else // cortex a15
911
912	// unroll 0
913	vld1.64		{d0, d1}, [r5:128]! // A0
914	vldr		s8, [r7, #0]  // B[0]
915	vldr		s9, [r7, #16] // B[4]
916	vldr		s10, [r7, #32] // B[8]
917	vldr		s11, [r7, #48] // B[12]
918	vmla.f32	q4, q0, d4[0]
919	vmla.f32	q5, q0, d4[1]
920	vmla.f32	q6, q0, d5[0]
921	vmla.f32	q7, q0, d5[1]
922	vld1.64		{d2, d3}, [r9:128]! // A1
923	vmla.f32	q8, q1, d4[0]
924	vmla.f32	q9, q1, d4[1]
925	vmla.f32	q10, q1, d5[0]
926	vmla.f32	q11, q1, d5[1]
927
928#endif
929
930	sub		r4, r4, #1
931	add		r7, r7, #4
932	cmp		r4, #0
933	bgt		3b
934
9352: // return
936
937
938#if MACRO_LEVEL>=2
939	.endm
940#else
941	mov		pc, lr // return
942
943#if defined(OS_LINUX)
944	.size	inner_kernel_gemm_add_nn_8x4_lib4, .-inner_kernel_gemm_add_nn_8x4_lib4
945#endif
946#endif
947
948
949
950
951
952// subroutine
953//
954// cholesky factorization
955//
956// input arguments:
957// r4   <- inv_diag_D
958//
959// output arguments:
960// r4   <- inv_diag_D
961
962#if MACRO_LEVEL>=1
963	.macro INNER_EDGE_POTRF_8X4_LIB4 lc_zero
964#else
965	.align 3
96699: // 0
967	.word 0
968	.word 0
969
970	.p2align 4,,15
971#if defined(OS_LINUX)
972	.type inner_edge_potrf_8x4_lib4, %function
973inner_edge_potrf_8x4_lib4:
974#elif defined(OS_MAC)
975_inner_edge_potrf_8x4_lib4:
976#endif
977#endif
978
979	fconsts		s1, #112 // 1.0
980#if MACRO_LEVEL>=1
981	flds		s0, \lc_zero // 0.0
982#else
983	flds		s0, 99b // 0.0
984#endif
985
986	// first column
987	fcmpes		s16, s0
988	fmstat
989	ble			1f
990	fsqrts		s2, s16
991	fdivs		s2, s1, s2
992	fsts		s2, [r4, #0]
9932:
994	vmul.f32	q4, q4, d1[0]
995	vmul.f32	q8, q8, d1[0]
996
997	// second column
998	vmls.f32	q5, q4, d8[1]
999	vmls.f32	q9, q8, d8[1]
1000	fcmpes		s21, s0
1001	fmstat
1002	ble			3f
1003	fsqrts		s2, s21
1004	fdivs		s2, s1, s2
1005	fsts		s2, [r4, #4]
10064:
1007	vmul.f32	q5, q5, d1[0]
1008	vmul.f32	q9, q9, d1[0]
1009
1010	// third column
1011	vmls.f32	q6, q4, d9[0]
1012	vmls.f32	q10, q8, d9[0]
1013	vmls.f32	q6, q5, d11[0]
1014	vmls.f32	q10, q9, d11[0]
1015	fcmpes		s16, s0
1016	fmstat
1017	ble			5f
1018	fsqrts		s2, s26
1019	fdivs		s2, s1, s2
1020	fsts		s2, [r4, #8]
10216:
1022	vmul.f32	q6, q6, d1[0]
1023	vmul.f32	q10, q10, d1[0]
1024
1025	// fourth column
1026	vmls.f32	q7, q4, d9[1]
1027	vmls.f32	q11, q8, d9[1]
1028	vmls.f32	q7, q5, d11[1]
1029	vmls.f32	q11, q9, d11[1]
1030	vmls.f32	q7, q6, d13[1]
1031	vmls.f32	q11, q10, d13[1]
1032	fcmpes		s31, s0
1033	fmstat
1034	ble			7f
1035	fsqrts		s31, s31
1036	fdivs		s2, s1, s31
1037	fsts		s2, [r4, #12]
10388:
1039	vmul.f32	q11, q11, d1[0]
1040
1041	b			0f
1042
10431:
1044#if MACRO_LEVEL>=1
1045	flds		s16, \lc_zero // 0.0
1046#else
1047	flds		s16, 99b // 0.0
1048#endif
1049	b			2b
1050
10513:
1052#if MACRO_LEVEL>=1
1053	flds		s21, \lc_zero // 0.0
1054#else
1055	flds		s21, 99b // 0.0
1056#endif
1057	b			4b
1058
10595:
1060#if MACRO_LEVEL>=1
1061	flds		s26, \lc_zero // 0.0
1062#else
1063	flds		s26, 99b // 0.0
1064#endif
1065	b			6b
1066
10677:
1068#if MACRO_LEVEL>=1
1069	flds		s31, \lc_zero // 0.0
1070#else
1071	flds		s31, 99b // 0.0
1072#endif
1073	b			8b
1074
10750:
1076
1077#if MACRO_LEVEL>=1
1078	.endm
1079#else
1080	mov		pc, lr // return
1081
1082#if defined(OS_LINUX)
1083	.size	inner_edge_potrf_8x4_lib4, .-inner_edge_potrf_8x4_lib4
1084#endif
1085#endif
1086
1087
1088
1089
1090
1091
1092// subroutine
1093//
1094// triangular substitution:
1095// side = right
1096// uplo = lower
1097// tran = transposed
1098// requires explicit inverse of diagonal
1099//
1100// input arguments:
1101// r4   <- E
1102// r5   <- inv_diag_E
1103//
1104// output arguments:
1105// r4   <- E
1106// r5   <- inv_diag_E
1107
1108#if MACRO_LEVEL>=1
1109	.macro INNER_EDGE_TRSM_RLT_INV_8X4_LIB4
1110#else
1111	.p2align 4,,15
1112#if defined(OS_LINUX)
1113	.type inner_edge_trsm_rlt_inv_8x4_lib4, %function
1114inner_edge_trsm_rlt_inv_8x4_lib4:
1115#elif defined(OS_MAC)
1116inner_edge_trsm_rlt_inv_8x4_lib4:
1117#endif
1118#endif
1119
1120	// first column
1121	vldr.32		d0, [r5, #0] // E_inv[0]
1122	vmul.f32	q4, q4, d0[0];
1123	vmul.f32	q8, q8, d0[0];
1124
1125	// second column
1126	vldr.32		d0, [r4, #4] // E[1+4*0]
1127	vmls.f32	q5, q4, d0[0];
1128	vmls.f32	q9, q8, d0[0];
1129	vldr.32		d0, [r5, #4] // E_inv[1]
1130	vmul.f32	q5, q5, d0[0];
1131	vmul.f32	q9, q9, d0[0];
1132
1133	// thirs column
1134	vldr.32		d0, [r4, #8] // E[2+4*0]
1135	vmls.f32	q6, q4, d0[0];
1136	vmls.f32	q10, q8, d0[0];
1137	vldr.32		d0, [r4, #24] // E[2+4*1]
1138	vmls.f32	q6, q5, d0[0];
1139	vmls.f32	q10, q9, d0[0];
1140	vldr.32		d0, [r5, #8] // E_inv[2]
1141	vmul.f32	q6, q6, d0[0];
1142	vmul.f32	q10, q10, d0[0];
1143
1144	// fourth column
1145	vldr.32		d0, [r4, #12] // E[3+4*0]
1146	vmls.f32	q7, q4, d0[0];
1147	vmls.f32	q11, q8, d0[0];
1148	vldr.32		d0, [r4, #28] // E[3+4*1]
1149	vmls.f32	q7, q5, d0[0];
1150	vmls.f32	q11, q9, d0[0];
1151	vldr.32		d0, [r4, #44] // E[3+4*2]
1152	vmls.f32	q7, q6, d0[0];
1153	vmls.f32	q11, q10, d0[0];
1154	vldr.32		d0, [r5, #12] // E_inv[3]
1155	vmul.f32	q7, q7, d0[0];
1156	vmul.f32	q11, q11, d0[0];
1157
1158#if MACRO_LEVEL>=1
1159	.endm
1160#else
1161	mov		pc, lr // return
1162
1163#if defined(OS_LINUX)
1164	.size	inner_edge_trsm_rlt_inv_8x4_lib4, .-inner_edge_trsm_rlt_inv_8x4_lib4
1165#endif
1166#endif
1167
1168
1169
1170
1171
1172// subroutine
1173//
1174// input arguments:
1175// r4   <- alpha
1176// r5   <- beta
1177// r6   <- C
1178// r7   <- sdc
1179//
1180// output arguments:
1181
1182#if MACRO_LEVEL>=1
1183	.macro INNER_SCALE_AB_8X4_LIB4 lc_zero
1184#else
1185	.align 3
118699: // 00
1187	.word 0
1188	.word 0
1189
1190//	.p2align 4,,15
1191#if defined(OS_LINUX)
1192	.type inner_scale_ab_8x4_lib4, %function
1193inner_scale_ab_8x4_lib4:
1194#elif defined(OS_MAC)
1195_inner_scale_ab_8x4_lib4:
1196#endif
1197#endif
1198
1199	flds		s8, [r4, #0] // alpha
1200
1201	vmul.f32	q4, q4, d4[0]
1202	flds		s9, [r5, #0] // beta
1203	vmul.f32	q5, q5, d4[0]
1204#if MACRO_LEVEL>=1
1205	flds		s10, \lc_zero // 0.0
1206#else
1207	flds		s10, 99b // 0.0
1208#endif
1209	vmul.f32	q6, q6, d4[0]
1210	vmul.f32	q7, q7, d4[0]
1211	fcmpes		s9, s10
1212	vmul.f32	q8, q8, d4[0]
1213	vmul.f32	q9, q9, d4[0]
1214	vmul.f32	q10, q10, d4[0]
1215	vmul.f32	q11, q11, d4[0]
1216	fmstat
1217
1218	beq		0f // end
1219
1220	add		r8, r6, r7
1221
1222	vld1.64		{d0, d1, d2, d3}, [r6:128]!
1223	vmla.f32	q4, q0, d4[1]
1224	vmla.f32	q5, q1, d4[1]
1225	vld1.64		{d0, d1, d2, d3}, [r6:128]!
1226	vmla.f32	q6, q0, d4[1]
1227	vmla.f32	q7, q1, d4[1]
1228	vld1.64		{d0, d1, d2, d3}, [r8:128]!
1229	vmla.f32	q8, q0, d4[1]
1230	vmla.f32	q9, q1, d4[1]
1231	vld1.64		{d0, d1, d2, d3}, [r8:128]!
1232	vmla.f32	q10, q0, d4[1]
1233	vmla.f32	q11, q1, d4[1]
1234
12350:
1236
1237#if MACRO_LEVEL>=1
1238	.endm
1239#else
1240	mov		pc, lr // return
1241
1242#if defined(OS_LINUX)
1243	.size	inner_scale_ab_8x4_lib4, .-inner_scale_ab_8x4_lib4
1244#endif
1245#endif
1246
1247
1248
1249
1250
1251// subroutine
1252//
1253// input arguments:
1254// r4   <- beta
1255// r5   <- C
1256// r7   <- sdc
1257//
1258// output arguments:
1259
1260#if MACRO_LEVEL>=1
1261	.macro INNER_SCALE_M1B_8X4_LIB4 lc_zero
1262#else
1263	.align 3
126499: // 00
1265	.word 0
1266	.word 0
1267
1268//	.p2align 4,,15
1269#if defined(OS_LINUX)
1270	.type inner_scale_m1b_8x4_lib4, %function
1271inner_scale_m1b_8x4_lib4:
1272#elif defined(OS_MAC)
1273_inner_scale_m1b_8x4_lib4:
1274#endif
1275#endif
1276
1277	vldr	d0, 99b
1278	vldr	d1, 99b
1279
1280	vsub.f32	q4, q0, q4
1281	vsub.f32	q5, q0, q5
1282	vsub.f32	q6, q0, q6
1283	vsub.f32	q7, q0, q7
1284	vsub.f32	q8, q0, q8
1285	vsub.f32	q9, q0, q9
1286	vsub.f32	q10, q0, q10
1287	vsub.f32	q11, q0, q11
1288
1289	flds		s9, [r4, #0] // beta
1290#if MACRO_LEVEL>=1
1291	flds		s10, \lc_zero // 0.0
1292#else
1293	flds		s10, 99b // 0.0
1294#endif
1295	fcmpes		s9, s10
1296	fmstat
1297
1298	beq		0f // end
1299
1300	add		r8, r5, r6
1301
1302	vld1.64		{d0, d1, d2, d3}, [r5:128]!
1303	vmla.f32	q4, q0, d4[1]
1304	vmla.f32	q5, q1, d4[1]
1305	vld1.64		{d0, d1, d2, d3}, [r5:128]!
1306	vmla.f32	q6, q0, d4[1]
1307	vmla.f32	q7, q1, d4[1]
1308	vld1.64		{d0, d1, d2, d3}, [r8:128]!
1309	vmla.f32	q8, q0, d4[1]
1310	vmla.f32	q9, q1, d4[1]
1311	vld1.64		{d0, d1, d2, d3}, [r8:128]!
1312	vmla.f32	q10, q0, d4[1]
1313	vmla.f32	q11, q1, d4[1]
1314
13150:
1316
1317#if MACRO_LEVEL>=1
1318	.endm
1319#else
1320	mov		pc, lr // return
1321
1322#if defined(OS_LINUX)
1323	.size	inner_scale_m1b_8x4_lib4, .-inner_scale_m1b_8x4_lib4
1324#endif
1325#endif
1326
1327
1328
1329
1330
1331// subroutine
1332//
1333// input arguments:
1334// r4   <- C
1335// r5   <- sdc
1336//
1337// output arguments:
1338
1339#if MACRO_LEVEL>=1
1340	.macro INNER_SCALE_M11_8X4_LIB4
1341#else
1342//	.p2align 4,,15
1343#if defined(OS_LINUX)
1344	.type inner_scale_m11_8x4_lib4, %function
1345inner_scale_m11_8x4_lib4:
1346#elif defined(OS_MAC)
1347_inner_scale_m11_8x4_lib4:
1348#endif
1349#endif
1350
1351	add		r6, r4, r5
1352
1353	vld1.64		{d0, d1, d2, d3}, [r4:128]!
1354	vsub.f32	q4, q0, q4
1355	vsub.f32	q5, q1, q5
1356	vld1.64		{d0, d1, d2, d3}, [r4:128]!
1357	vsub.f32	q6, q0, q6
1358	vsub.f32	q7, q1, q7
1359	vld1.64		{d0, d1, d2, d3}, [r6:128]!
1360	vsub.f32	q8, q0, q8
1361	vsub.f32	q9, q1, q9
1362	vld1.64		{d0, d1, d2, d3}, [r6:128]!
1363	vsub.f32	q10, q0, q10
1364	vsub.f32	q11, q1, q11
1365
1366#if MACRO_LEVEL>=1
1367	.endm
1368#else
1369	mov		pc, lr // return
1370
1371#if defined(OS_LINUX)
1372	.size	inner_scale_m11_8x4_lib4, .-inner_scale_m11_8x4_lib4
1373#endif
1374#endif
1375
1376
1377
1378
1379
1380// subroutine
1381//
1382// input arguments:
1383// r4   <- D
1384// r5   <- sdd
1385//
1386// output arguments:
1387
1388#if MACRO_LEVEL>=1
1389	.macro INNER_STORE_8X4_LIB4
1390#else
1391//	.p2align 4,,15
1392#if defined(OS_LINUX)
1393	.type inner_store_8x4_lib4, %function
1394inner_store_8x4_lib4:
1395#elif defined(OS_MAC)
1396_inner_store_8x4_lib4:
1397#endif
1398#endif
1399
1400	add		r6, r4, r5
1401
1402	vst1.64		{d8, d9, d10, d11}, [r4:128]!
1403	vst1.64		{d12, d13, d14, d15}, [r4:128]!
1404	vst1.64		{d16, d17, d18, d19}, [r6:128]!
1405	vst1.64		{d20, d21, d22, d23}, [r6:128]!
1406
1407#if MACRO_LEVEL>=1
1408	.endm
1409#else
1410	mov		pc, lr // return
1411
1412#if defined(OS_LINUX)
1413	.size	inner_store_8x4_lib4, .-inner_store_8x4_lib4
1414#endif
1415#endif
1416
1417
1418
1419
1420
1421// subroutine
1422//
1423// input arguments:
1424// r4   <- D
1425// r5   <- sdd
1426//
1427// output arguments:
1428
1429#if MACRO_LEVEL>=1
1430	.macro INNER_STORE_8X4_L_LIB4
1431#else
1432//	.p2align 4,,15
1433#if defined(OS_LINUX)
1434	.type inner_store_8x4_l_lib4, %function
1435inner_store_8x4_l_lib4:
1436#elif defined(OS_MAC)
1437_inner_store_8x4_l_lib4:
1438#endif
1439#endif
1440
1441	add		r6, r4, r5
1442
1443	// top 4x4
1444	// first column
1445	vstr.64		d8, [r4, #0]
1446	vstr.64		d9, [r4, #8]
1447	// second column
1448	vstr.32		s21, [r4, #20]
1449	vstr.64		d11, [r4, #24]
1450	// third column
1451	vstr.64		d13, [r4, #40]
1452	// fourth column
1453	vstr.64		s31, [r4, #60]
1454	// bottom 4x4
1455	vst1.64		{d16, d17, d18, d19}, [r6:128]!
1456	vst1.64		{d20, d21, d22, d23}, [r6:128]!
1457
1458
1459#if MACRO_LEVEL>=1
1460	.endm
1461#else
1462	mov		pc, lr // return
1463
1464#if defined(OS_LINUX)
1465	.size	inner_store_8x4_l_lib4, .-inner_store_8x4_l_lib4
1466#endif
1467#endif
1468
1469
1470
1471
1472
1473	.align 3
147499: // { 0 }
1475	.word 0
1476	.word 0
1477
1478
1479
1480
1481
1482//                               r0        r1             r2         r3       sp+0       sp+4          sp+8       sp+12    sp+16   sp+20
1483// void kernel_sgemm_nt_8x4_lib4(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd)
1484
1485//	.p2align 4,,15
1486#if defined(OS_LINUX)
1487	.global	kernel_sgemm_nt_8x4_lib4
1488	.type	kernel_sgemm_nt_8x4_lib4, %function
1489kernel_sgemm_nt_8x4_lib4:
1490#elif defined(OS_MAC)
1491	.global	kernel_sgemm_nt_8x4_lib4
1492_kernel_sgemm_nt_8x4_lib4:
1493#endif
1494
1495	PROLOGUE
1496
1497
1498
1499	// zero accumulation registers
1500	vldr	d8, 99b
1501	vldr	d9, 99b
1502	vmov	q5, q4
1503	vmov	q6, q4
1504	vmov	q7, q4
1505	vmov	q8, q4
1506	vmov	q9, q4
1507	vmov	q10, q4
1508	vmov	q11, q4
1509
1510
1511
1512	// call inner kernel dgemm nt
1513	mov		r4, r0 // kmax
1514	mov		r5, r2 // A
1515	mov		r6, r3 // sda
1516	lsl		r6, r6, #4 // 4*sizeof(float)*sda
1517	ldr		r7, [fp, #0] // B
1518
1519#if MACRO_LEVEL>=2
1520	INNER_KERNEL_GEMM_ADD_NT_8X4_LIB4
1521#else
1522#if defined(OS_LINUX)
1523	bl	inner_kernel_gemm_add_nt_8x4_lib4
1524#elif defined(OS_MAC)
1525	bl	_inner_kernel_gemm_add_nt_8x4_lib4
1526#endif
1527#endif
1528
1529
1530
1531	// call inner blend for generic alpha and beta
1532	mov		r4, r1 // alpha
1533	ldr		r5, [fp, #4] // beta
1534	ldr		r6, [fp, #8] // C
1535	ldr		r7, [fp, #12] // sdc
1536	lsl		r7, r7, #4 // 4*sizeof(float)*sdc
1537
1538#if MACRO_LEVEL>=1
1539	INNER_SCALE_AB_8X4_LIB4 99f
1540#else
1541#if defined(OS_LINUX)
1542	bl inner_scale_ab_8x4_lib4
1543#elif defined(OS_MAC)
1544	bl _inner_scale_ab_8x4_lib4
1545#endif
1546#endif
1547
1548
1549
1550	// store n
1551	ldr		r4, [fp, #16] // D
1552	ldr		r5, [fp, #20] // sdd
1553	lsl		r5, r5, #4 // 4*sizeof(float)*sdd
1554
1555#if MACRO_LEVEL>=1
1556	INNER_STORE_8X4_LIB4
1557#else
1558#if defined(OS_LINUX)
1559	bl inner_store_8x4_lib4
1560#elif defined(OS_MAC)
1561	bl _inner_store_8x4_lib4
1562#endif
1563#endif
1564
1565
1566
1567	EPILOGUE
1568
1569#if defined(OS_LINUX)
1570	.size	kernel_sgemm_nt_8x4_lib4, .-kernel_sgemm_nt_8x4_lib4
1571#endif
1572
1573
1574
1575
1576
1577	.align 3
157899: // { 0 }
1579	.word 0
1580	.word 0
1581
1582
1583
1584
1585
1586//                               r0        r1             r2         r3       sp+0         sp+4       sp+8     sp+12         sp+16      sp+20    sp+24      sp+28
1587// void kernel_sgemm_nn_8x4_lib4(int kmax, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd)
1588
1589//	.p2align 4,,15
1590#if defined(OS_LINUX)
1591	.global	kernel_sgemm_nn_8x4_lib4
1592	.type	kernel_sgemm_nn_8x4_lib4, %function
1593kernel_sgemm_nn_8x4_lib4:
1594#elif defined(OS_MAC)
1595	.global	kernel_sgemm_nn_8x4_lib4
1596_kernel_sgemm_nn_8x4_lib4:
1597#endif
1598
1599	PROLOGUE
1600
1601
1602
1603	// zero accumulation registers
1604	vldr	d8, 99b
1605	vldr	d9, 99b
1606	vmov	q5, q4
1607	vmov	q6, q4
1608	vmov	q7, q4
1609	vmov	q8, q4
1610	vmov	q9, q4
1611	vmov	q10, q4
1612	vmov	q11, q4
1613
1614
1615
1616	// call inner kernel dgemm nt
1617	mov		r4, r0 // kmax
1618	mov		r5, r2 // A
1619	mov		r6, r3 // sda
1620	lsl		r6, r6, #4 // 4*sizeof(float)*sda
1621	ldr		r7, [fp, #4] // B
1622	ldr		r8, [fp, #8] // sdb
1623	lsl		r8, r8, #4 // 4*sizeof(float)*sdb
1624	ldr		r9, [fp, #0] // offsetB
1625
1626// TODO edge
1627
1628#if MACRO_LEVEL>=2
1629	INNER_KERNEL_GEMM_ADD_NN_8X4_LIB4
1630#else
1631#if defined(OS_LINUX)
1632	bl	inner_kernel_gemm_add_nn_8x4_lib4
1633#elif defined(OS_MAC)
1634	bl	_inner_kernel_gemm_add_nn_8x4_lib4
1635#endif
1636#endif
1637
1638
1639
1640	// call inner blend for generic alpha and beta
1641	mov		r4, r1 // alpha
1642	ldr		r5, [fp, #12] // beta
1643	ldr		r6, [fp, #16] // C
1644	ldr		r7, [fp, #20] // sdc
1645	lsl		r7, r7, #4 // 4*sizeof(float)*sdc
1646
1647#if MACRO_LEVEL>=1
1648	INNER_SCALE_AB_8X4_LIB4 99f
1649#else
1650#if defined(OS_LINUX)
1651	bl inner_scale_ab_8x4_lib4
1652#elif defined(OS_MAC)
1653	bl _inner_scale_ab_8x4_lib4
1654#endif
1655#endif
1656
1657
1658
1659	// store n
1660	ldr		r4, [fp, #24] // D
1661	ldr		r5, [fp, #28] // sdd
1662	lsl		r5, r5, #4 // 4*sizeof(float)*sdd
1663
1664#if MACRO_LEVEL>=1
1665	INNER_STORE_8X4_LIB4
1666#else
1667#if defined(OS_LINUX)
1668	bl inner_store_8x4_lib4
1669#elif defined(OS_MAC)
1670	bl _inner_store_8x4_lib4
1671#endif
1672#endif
1673
1674
1675
1676	EPILOGUE
1677
1678#if defined(OS_LINUX)
1679	.size	kernel_sgemm_nn_8x4_lib4, .-kernel_sgemm_nn_8x4_lib4
1680#endif
1681
1682
1683
1684
1685
1686	.align 3
168799: // { 0 }
1688	.word 0
1689	.word 0
1690
1691
1692
1693
1694
1695//                                      r0        r1         r2       r3         sp+0       sp+4     rsp+8      rsp+12   rsp+16     rsp+20        rsp+24
1696// void kernel_strsm_nt_rl_inv_8x4_lib4(int kmax, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E);
1697
1698//	.p2align 4,,15
1699#if defined(OS_LINUX)
1700	.globl kernel_strsm_nt_rl_inv_8x4_lib4
1701	.type kernel_strsm_nt_rl_inv_8x4_lib4, %function
1702kernel_strsm_nt_rl_inv_8x4_lib4:
1703#elif defined(OS_MAC)
1704	.globl _kernel_strsm_nt_rl_inv_8x4_lib4
1705_kernel_strsm_nt_rl_inv_8x4_lib4:
1706#endif
1707
1708	PROLOGUE
1709
1710
1711
1712	// zero accumulation registers
1713	vldr	d8, 99b
1714	vldr	d9, 99b
1715	vmov	q5, q4
1716	vmov	q6, q4
1717	vmov	q7, q4
1718	vmov	q8, q4
1719	vmov	q9, q4
1720	vmov	q10, q4
1721	vmov	q11, q4
1722
1723
1724
1725	// call inner kernel dgemm nt
1726	mov		r4, r0 // kmax
1727	mov		r5, r1 // A
1728	mov		r6, r2 // sda
1729	lsl		r6, r6, #4 // 4*sizeof(float)*sda
1730	mov		r7, r3 // B
1731
1732#if MACRO_LEVEL>=2
1733	INNER_KERNEL_GEMM_ADD_NT_8X4_LIB4
1734#else
1735#if defined(OS_LINUX)
1736	bl	inner_kernel_gemm_add_nt_8x4_lib4
1737#elif defined(OS_MAC)
1738	bl	_inner_kernel_gemm_add_nt_8x4_lib4
1739#endif
1740#endif
1741
1742
1743
1744	// call inner blend for alpha=1.0 and beta=1.0
1745	ldr		r4, [fp, #0] // beta
1746	ldr		r5, [fp, #4] // C
1747	ldr		r6, [fp, #8] // sdd
1748	lsl		r6, r6, #4 // 4*sizeof(float)*sdd
1749
1750#if MACRO_LEVEL>=1
1751	INNER_SCALE_M1B_8X4_LIB4 99f
1752#else
1753#if defined(OS_LINUX)
1754	bl inner_scale_m1b_8x4_lib4
1755#elif defined(OS_MAC)
1756	bl _inner_scale_m1b_8x4_lib4
1757#endif
1758#endif
1759
1760
1761
1762	// factorization
1763	ldr		r4, [fp, #20] // E
1764	ldr		r5, [fp, #24] // inv_diag_E
1765
1766#if MACRO_LEVEL>=1
1767	INNER_EDGE_TRSM_RLT_INV_8X4_LIB4
1768#else
1769#if defined(OS_LINUX)
1770	bl inner_edge_trsm_rlt_inv_8x4_lib4
1771#elif defined(OS_MAC)
1772	bl _inner_edge_trsm_rlt_inv_8x4_lib4
1773#endif
1774#endif
1775
1776
1777
1778	// store l
1779	ldr		r4, [fp, #12] // D
1780	ldr		r5, [fp, #16] // sdd
1781	lsl		r5, r5, #4 // 4*sizeof(float)*sdd
1782
1783#if MACRO_LEVEL>=1
1784	INNER_STORE_8X4_LIB4
1785#else
1786#if defined(OS_LINUX)
1787	bl inner_store_8x4_lib4
1788#elif defined(OS_MAC)
1789	bl _inner_store_8x4_lib4
1790#endif
1791#endif
1792
1793
1794
1795	EPILOGUE
1796
1797#if defined(OS_LINUX)
1798	.size	kernel_strsm_nt_rl_inv_8x4_lib4, .-kernel_strsm_nt_rl_inv_8x4_lib4
1799#endif
1800
1801
1802
1803
1804
1805	.align 3
180699: // 0
1807	.word 0
1808	.word 0
1809
1810
1811//                                  r0        r1         r2       r3         sp+0       sp+4     sp+8       sp+12    sp+16
1812// void kernel_spotrf_nt_l_8x4_lib4(int kmax, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D);
1813
1814//	.p2align 4,,15
1815#if defined(OS_LINUX)
1816	.globl kernel_spotrf_nt_l_8x4_lib4
1817	.type kernel_spotrf_nt_l_8x4_lib4, %function
1818kernel_spotrf_nt_l_8x4_lib4:
1819#elif defined(OS_MAC)
1820	.globl _kernel_spotrf_nt_l_8x4_lib4
1821_kernel_spotrf_nt_l_8x4_lib4:
1822#endif
1823
1824	PROLOGUE
1825
1826
1827
1828	// zero accumulation registers
1829	vldr	d8, 99b
1830	vldr	d9, 99b
1831	vmov	q5, q4
1832	vmov	q6, q4
1833	vmov	q7, q4
1834	vmov	q8, q4
1835	vmov	q9, q4
1836	vmov	q10, q4
1837	vmov	q11, q4
1838
1839
1840
1841	// call inner kernel dgemm nt
1842	mov		r4, r0 // kmax
1843	mov		r5, r1 // A
1844	mov		r6, r2 // sda
1845	lsl		r6, r6, #4 // 4*sizeof(float)*sda
1846	mov		r7, r3 // B
1847
1848#if MACRO_LEVEL>=2
1849	INNER_KERNEL_GEMM_ADD_NT_8X4_LIB4
1850#else
1851#if defined(OS_LINUX)
1852	bl	inner_kernel_gemm_add_nt_8x4_lib4
1853#elif defined(OS_MAC)
1854	bl	_inner_kernel_gemm_add_nt_8x4_lib4
1855#endif
1856#endif
1857
1858
1859
1860	// call inner blend for alpha=1.0 and beta=1.0
1861	ldr		r4, [fp, #0] // C
1862	ldr		r5, [fp, #4] // sdd
1863	lsl		r5, r5, #4 // 4*sizeof(float)*sdd
1864
1865#if MACRO_LEVEL>=1
1866	INNER_SCALE_M11_8X4_LIB4
1867#else
1868#if defined(OS_LINUX)
1869	bl inner_scale_m11_8x4_lib4
1870#elif defined(OS_MAC)
1871	bl _inner_scale_m11_8x4_lib4
1872#endif
1873#endif
1874
1875
1876
1877	// factorization
1878	ldr		r4, [fp, #16] // inv_diag_D
1879
1880#if MACRO_LEVEL>=1
1881	INNER_EDGE_POTRF_8X4_LIB4 99f
1882#else
1883#if defined(OS_LINUX)
1884	bl inner_edge_potrf_8x4_lib4
1885#elif defined(OS_MAC)
1886	bl _inner_edge_potrf_8x4_lib4
1887#endif
1888#endif
1889
1890
1891
1892	// store l
1893	ldr		r4, [fp, #8] // D
1894	ldr		r5, [fp, #12] // sdd
1895	lsl		r5, r5, #4 // 4*sizeof(float)*sdd
1896
1897#if MACRO_LEVEL>=1
1898	INNER_STORE_8X4_L_LIB4
1899#else
1900#if defined(OS_LINUX)
1901	bl inner_store_8x4_l_lib4
1902#elif defined(OS_MAC)
1903	bl _inner_store_8x4_l_lib4
1904#endif
1905#endif
1906
1907
1908
1909	EPILOGUE
1910
1911#if defined(OS_LINUX)
1912	.size	kernel_spotrf_nt_l_8x4_lib4, .-kernel_spotrf_nt_l_8x4_lib4
1913#endif
1914
1915
1916
1917
1918
1919	.align 3
192099: // { 0 }
1921	.word 0
1922	.word 0
1923
1924
1925
1926
1927
1928#if defined(BLAS_API)
1929
1930#include "kernel_sgemm_8x4_lib.S"
1931
1932#endif
1933