@@ -392,6 +392,82 @@ namespace lsp
392392 );
393393 }
394394
395+ void lerp_kvk (float *dst, float a, const float *b, float k, size_t count)
396+ {
397+ ARCH_ARM_ASM
398+ (
399+ // x16 blocks
400+ __ASM_EMIT (" subs %[count], #16" )
401+ __ASM_EMIT (" vld1.32 {d16[], d17[]}, [%[a]]" ) // q8 = a
402+ __ASM_EMIT (" vld1.32 {d18[], d19[]}, [%[k]]" ) // q9 = k
403+ __ASM_EMIT (" blo 2f" )
404+ __ASM_EMIT (" 1:" )
405+ __ASM_EMIT (" vldm %[b]!, {q12-q15}" ) // q12 = b
406+ __ASM_EMIT (" vmov q0, q8" ) // q0 = a
407+ __ASM_EMIT (" vmov q1, q8" )
408+ __ASM_EMIT (" vmov q2, q8" )
409+ __ASM_EMIT (" vmov q3, q8" )
410+ __ASM_EMIT (" vsub.f32 q12, q12, q0" ) // q12 = b-a
411+ __ASM_EMIT (" vsub.f32 q13, q13, q1" )
412+ __ASM_EMIT (" vsub.f32 q14, q14, q2" )
413+ __ASM_EMIT (" vsub.f32 q15, q15, q3" )
414+ __ASM_EMIT (" vmla.f32 q0, q12, q9" ) // q0 = a + (b-a)*k
415+ __ASM_EMIT (" vmla.f32 q1, q13, q9" )
416+ __ASM_EMIT (" vmla.f32 q2, q14, q9" )
417+ __ASM_EMIT (" vmla.f32 q3, q15, q9" )
418+ __ASM_EMIT (" subs %[count], #16" )
419+ __ASM_EMIT (" vstm %[dst]!, {q0-q3}" )
420+ __ASM_EMIT (" bhs 1b" )
421+ // x8 block
422+ __ASM_EMIT (" 2:" )
423+ __ASM_EMIT (" adds %[count], #8" )
424+ __ASM_EMIT (" blt 4f" )
425+ __ASM_EMIT (" vldm %[b]!, {q12-q13}" ) // q12 = b
426+ __ASM_EMIT (" vmov q0, q8" ) // q0 = a
427+ __ASM_EMIT (" vmov q1, q8" )
428+ __ASM_EMIT (" vsub.f32 q12, q12, q0" ) // q12 = b-a
429+ __ASM_EMIT (" vsub.f32 q13, q13, q1" )
430+ __ASM_EMIT (" vmla.f32 q0, q12, q9" ) // q0 = a + (b-a)*k
431+ __ASM_EMIT (" vmla.f32 q1, q13, q9" )
432+ __ASM_EMIT (" sub %[count], #8" )
433+ __ASM_EMIT (" vstm %[dst]!, {q0-q1}" )
434+ // x4 blocks
435+ __ASM_EMIT (" 4:" )
436+ __ASM_EMIT (" adds %[count], #4" )
437+ __ASM_EMIT (" blt 6f" )
438+ __ASM_EMIT (" vldm %[b]!, {q12}" ) // q12 = b
439+ __ASM_EMIT (" vmov q0, q8" ) // q0 = a
440+ __ASM_EMIT (" vsub.f32 q12, q12, q0" ) // q12 = b-a
441+ __ASM_EMIT (" vmla.f32 q0, q12, q9" ) // q0 = a + (b-a)*k
442+ __ASM_EMIT (" sub %[count], #4" )
443+ __ASM_EMIT (" vstm %[dst]!, {q0}" )
444+ // x1 blocks
445+ __ASM_EMIT (" 6:" )
446+ __ASM_EMIT (" adds %[count], #3" )
447+ __ASM_EMIT (" blt 8f" )
448+ __ASM_EMIT (" 7:" )
449+ __ASM_EMIT (" vld1.32 {d24[], d25[]}, [%[b]]!" ) // q12 = b
450+ __ASM_EMIT (" vmov q0, q8" ) // q0 = a
451+ __ASM_EMIT (" vsub.f32 q12, q12, q0" ) // q12 = b-a
452+ __ASM_EMIT (" vmla.f32 q0, q12, q9" ) // q0 = a + (b-a)*k
453+ __ASM_EMIT (" subs %[count], #1" )
454+ __ASM_EMIT (" vst1.32 {d0[0]}, [%[dst]]!" )
455+ __ASM_EMIT (" bge 7b" )
456+ // end
457+ __ASM_EMIT (" 8:" )
458+
459+ : [dst] " +r" (dst), [b] " +r" (b),
460+ [count] " +r" (count)
461+ : [a] " r" (&a),
462+ [k] " r" (&k)
463+ : " cc" , " memory" ,
464+ " q0" , " q1" , " q2" , " q3" ,
465+ " q4" , " q5" , " q6" , " q7" ,
466+ " q8" ,
467+ " q12" , " q13" , " q14" , " q15"
468+ );
469+ }
470+
395471 } /* namespace neon_d32 */
396472} /* namespace lsp */
397473
0 commit comments