@@ -465,6 +465,132 @@ namespace lsp
465465 " v28" , " v29" , " v30" , " v31"
466466 );
467467 }
468+
469+ void lerp_kvv (float *dst, float a, const float *b, const float *k, size_t count)
470+ {
471+ ARCH_AARCH64_ASM
472+ (
473+ // x32 blocks
474+ __ASM_EMIT (" subs %[count], %[count], #32" )
475+ __ASM_EMIT (" ld1r {v8.4s}, [%[a]]" ) // v8 = a
476+ __ASM_EMIT (" b.lo 2f" )
477+ __ASM_EMIT (" 1:" )
478+ __ASM_EMIT (" mov v0.16b, v8.16b" ) // v0 = a
479+ __ASM_EMIT (" mov v1.16b, v8.16b" )
480+ __ASM_EMIT (" ldp q16, q17, [%[b]], #0x20" ) // v16 = b
481+ __ASM_EMIT (" ldp q24, q25, [%[k]], #0x20" ) // v24 = k
482+ __ASM_EMIT (" mov v1.16b, v8.16b" )
483+ __ASM_EMIT (" mov v1.16b, v8.16b" )
484+ __ASM_EMIT (" ldp q18, q19, [%[b]], #0x20" )
485+ __ASM_EMIT (" ldp q26, q27, [%[k]], #0x20" )
486+ __ASM_EMIT (" mov v1.16b, v8.16b" )
487+ __ASM_EMIT (" mov v1.16b, v8.16b" )
488+ __ASM_EMIT (" ldp q20, q21, [%[b]], #0x20" )
489+ __ASM_EMIT (" ldp q28, q29, [%[k]], #0x20" )
490+ __ASM_EMIT (" mov v1.16b, v8.16b" )
491+ __ASM_EMIT (" mov v1.16b, v8.16b" )
492+ __ASM_EMIT (" ldp q22, q23, [%[b]], #0x20" )
493+ __ASM_EMIT (" ldp q30, q31, [%[k]], #0x20" )
494+ __ASM_EMIT (" fsub v16.4s, v16.4s, v8.4s" ) // v16 = b-a
495+ __ASM_EMIT (" fsub v17.4s, v17.4s, v8.4s" )
496+ __ASM_EMIT (" fsub v18.4s, v18.4s, v8.4s" )
497+ __ASM_EMIT (" fsub v19.4s, v19.4s, v8.4s" )
498+ __ASM_EMIT (" fsub v20.4s, v20.4s, v8.4s" )
499+ __ASM_EMIT (" fsub v21.4s, v21.4s, v8.4s" )
500+ __ASM_EMIT (" fsub v22.4s, v22.4s, v8.4s" )
501+ __ASM_EMIT (" fsub v23.4s, v23.4s, v8.4s" )
502+ __ASM_EMIT (" fmla v0.4s, v16.4s, v24.4s" ) // v0 = a + (b-a)*k
503+ __ASM_EMIT (" fmla v1.4s, v17.4s, v25.4s" )
504+ __ASM_EMIT (" fmla v2.4s, v18.4s, v26.4s" )
505+ __ASM_EMIT (" fmla v3.4s, v19.4s, v27.4s" )
506+ __ASM_EMIT (" fmla v4.4s, v20.4s, v28.4s" )
507+ __ASM_EMIT (" fmla v5.4s, v21.4s, v29.4s" )
508+ __ASM_EMIT (" fmla v6.4s, v22.4s, v30.4s" )
509+ __ASM_EMIT (" fmla v7.4s, v23.4s, v31.4s" )
510+ __ASM_EMIT (" subs %[count], %[count], #32" )
511+ __ASM_EMIT (" stp q0, q1, [%[dst]], #0x20" )
512+ __ASM_EMIT (" stp q2, q3, [%[dst]], #0x20" )
513+ __ASM_EMIT (" stp q4, q5, [%[dst]], #0x20" )
514+ __ASM_EMIT (" stp q6, q7, [%[dst]], #0x20" )
515+ __ASM_EMIT (" b.hs 1b" )
516+ // x16 block
517+ __ASM_EMIT (" 2:" )
518+ __ASM_EMIT (" adds %[count], %[count], #16" )
519+ __ASM_EMIT (" b.lt 4f" )
520+ __ASM_EMIT (" mov v0.16b, v8.16b" ) // v0 = a
521+ __ASM_EMIT (" mov v1.16b, v8.16b" )
522+ __ASM_EMIT (" ldp q16, q17, [%[b]], #0x20" ) // v16 = b
523+ __ASM_EMIT (" ldp q24, q25, [%[k]], #0x20" ) // v24 = k
524+ __ASM_EMIT (" mov v1.16b, v8.16b" )
525+ __ASM_EMIT (" mov v1.16b, v8.16b" )
526+ __ASM_EMIT (" ldp q18, q19, [%[b]], #0x20" )
527+ __ASM_EMIT (" ldp q26, q27, [%[k]], #0x20" )
528+ __ASM_EMIT (" fsub v16.4s, v16.4s, v8.4s" ) // v16 = b-a
529+ __ASM_EMIT (" fsub v17.4s, v17.4s, v8.4s" )
530+ __ASM_EMIT (" fsub v18.4s, v18.4s, v8.4s" )
531+ __ASM_EMIT (" fsub v19.4s, v19.4s, v8.4s" )
532+ __ASM_EMIT (" fmla v0.4s, v16.4s, v24.4s" ) // v0 = a + (b-a)*k
533+ __ASM_EMIT (" fmla v1.4s, v17.4s, v25.4s" )
534+ __ASM_EMIT (" fmla v2.4s, v18.4s, v26.4s" )
535+ __ASM_EMIT (" fmla v3.4s, v19.4s, v27.4s" )
536+ __ASM_EMIT (" sub %[count], %[count], #16" )
537+ __ASM_EMIT (" stp q0, q1, [%[dst]], #0x20" )
538+ __ASM_EMIT (" stp q2, q3, [%[dst]], #0x20" )
539+ // x8 block
540+ __ASM_EMIT (" 4:" )
541+ __ASM_EMIT (" adds %[count], %[count], #8" )
542+ __ASM_EMIT (" b.lt 6f" )
543+ __ASM_EMIT (" mov v0.16b, v8.16b" ) // v0 = a
544+ __ASM_EMIT (" mov v1.16b, v8.16b" )
545+ __ASM_EMIT (" ldp q16, q17, [%[b]], #0x20" ) // v16 = b
546+ __ASM_EMIT (" ldp q24, q25, [%[k]], #0x20" ) // v24 = k
547+ __ASM_EMIT (" fsub v16.4s, v16.4s, v8.4s" ) // v16 = b-a
548+ __ASM_EMIT (" fsub v17.4s, v17.4s, v8.4s" )
549+ __ASM_EMIT (" fmla v0.4s, v16.4s, v24.4s" ) // v0 = a + (b-a)*k
550+ __ASM_EMIT (" fmla v1.4s, v17.4s, v25.4s" )
551+ __ASM_EMIT (" sub %[count], %[count], #8" )
552+ __ASM_EMIT (" stp q0, q1, [%[dst]], #0x20" )
553+ // x4 blocks
554+ __ASM_EMIT (" 6:" )
555+ __ASM_EMIT (" adds %[count], %[count], #4" )
556+ __ASM_EMIT (" b.lt 8f" )
557+ __ASM_EMIT (" mov v0.16b, v8.16b" ) // v0 = a
558+ __ASM_EMIT (" ldr q16, [%[b]], #0x10" ) // v16 = b
559+ __ASM_EMIT (" ldr q24, [%[k]], #0x10" ) // v24 = k
560+ __ASM_EMIT (" fsub v16.4s, v16.4s, v8.4s" ) // v16 = b-a
561+ __ASM_EMIT (" fmla v0.4s, v16.4s, v24.4s" ) // v0 = a + (b-a)*k
562+ __ASM_EMIT (" sub %[count], %[count], #4" )
563+ __ASM_EMIT (" str q0, [%[dst]], #0x10" )
564+ // x1 blocks
565+ __ASM_EMIT (" 8:" )
566+ __ASM_EMIT (" adds %[count], %[count], #3" )
567+ __ASM_EMIT (" b.lt 10f" )
568+ __ASM_EMIT (" 9:" )
569+ __ASM_EMIT (" mov v0.16b, v8.16b" ) // v0 = a
570+ __ASM_EMIT (" ld1r {v15.4s}, [%[b]], #0x04" ) // v16 = b
571+ __ASM_EMIT (" ld1r {v24.4s}, [%[k]], #0x04" ) // v24 = k
572+ __ASM_EMIT (" fsub v16.4s, v16.4s, v8.4s" ) // v16 = b-a
573+ __ASM_EMIT (" fmla v0.4s, v16.4s, v24.4s" ) // v0 = a + (b-a)*k
574+ __ASM_EMIT (" subs %[count], %[count], #1" )
575+ __ASM_EMIT (" st1 {v0.s}[0], [%[dst]], #0x04" )
576+ __ASM_EMIT (" b.ge 9b" )
577+ // end
578+ __ASM_EMIT (" 10:" )
579+
580+ : [dst] " +r" (dst), [b] " +r" (b), [k] " +r" (k),
581+ [count] " +r" (count)
582+ : [a] " r" (&a)
583+ : " cc" , " memory" ,
584+ " v0" , " v1" , " v2" , " v3" ,
585+ " v4" , " v5" , " v6" , " v7" ,
586+ " v8" ,
587+ " v16" , " v17" , " v18" , " v19" ,
588+ " v20" , " v21" , " v22" , " v23" ,
589+ " v24" , " v25" , " v26" , " v27" ,
590+ " v28" , " v29" , " v30" , " v31"
591+ );
592+ }
593+
468594 } /* namespace asimd */
469595} /* namespace lsp */
470596
0 commit comments