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