@@ -420,6 +420,129 @@ namespace lsp
420
420
421
421
#undef SEL_NONE
422
422
#undef SEL_ABS
423
+ #undef MINMAX2_SEARCH_CORE
424
+
425
+ void sign_minmax (const float *src, size_t count, float *min, float *max)
426
+ {
427
+ ARCH_ARM_ASM (
428
+ __ASM_EMIT (" veor q0, q0" ) \
429
+ __ASM_EMIT (" veor q1, q0" ) \
430
+ __ASM_EMIT (" cmp %[count], #0" ) \
431
+ __ASM_EMIT (" bls 8f" ) \
432
+ __ASM_EMIT (" vld1.32 {d0[], d1[]}, [%[src]]" ) /* q0 = min */ \
433
+ __ASM_EMIT (" vabs.f32 q2, q0" ) /* q2 = abs(min) */ \
434
+ __ASM_EMIT (" vmov q1, q0" ) /* q1 = max */ \
435
+ __ASM_EMIT (" vmov q3, q2" ) /* q3 = abs(max) */ \
436
+ __ASM_EMIT (" subs %[count], #16" ) \
437
+ __ASM_EMIT (" blt 2f" ) \
438
+ /* x16 blocks */ \
439
+ __ASM_EMIT (" 1:" ) \
440
+ __ASM_EMIT (" vldm %[src]!, {q8-q11}" ) /* q8 = x0, q9 = x1, q10 = x2, q11 = x3 */ \
441
+ __ASM_EMIT (" vabs.f32 q12, q8" ) /* q12 = abs(x0) */ \
442
+ __ASM_EMIT (" vabs.f32 q13, q9" ) /* q13 = abs(x1) */ \
443
+ __ASM_EMIT (" vabs.f32 q14, q10" ) /* q14 = abs(x2) */ \
444
+ __ASM_EMIT (" vabs.f32 q15, q11" ) /* q15 = abs(x3) */ \
445
+ __ASM_EMIT (" vclt.f32 q4, q2, q12" ) /* q4 = [abs(min) < abs(x0) ] */ \
446
+ __ASM_EMIT (" vcgt.f32 q5, q3, q12" ) /* q4 = [abs(max) > abs(x0) ] */ \
447
+ __ASM_EMIT (" vbif q0, q8, q4" ) /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
448
+ __ASM_EMIT (" vbif q1, q8, q5" ) /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
449
+ __ASM_EMIT (" vbif q2, q12, q4" ) /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
450
+ __ASM_EMIT (" vbif q3, q12, q5" ) /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
451
+ __ASM_EMIT (" vclt.f32 q4, q2, q13" ) /* q4 = [abs(min) < abs(x1) ] */ \
452
+ __ASM_EMIT (" vcgt.f32 q5, q3, q13" ) /* q4 = [abs(max) > abs(x1) ] */ \
453
+ __ASM_EMIT (" vbif q0, q9, q4" ) /* q0 = [abs(min) < abs(x1) ] ? min : x1 */ \
454
+ __ASM_EMIT (" vbif q1, q9, q5" ) /* q1 = [abs(max) > abs(x1) ] ? res : x1 */ \
455
+ __ASM_EMIT (" vbif q2, q13, q4" ) /* q12 = [abs(min) < abs(x1) ] ? abs(min) : abs(x1) */ \
456
+ __ASM_EMIT (" vbif q3, q13, q5" ) /* q13 = [abs(max) > abs(x1) ] ? abs(max) : abs(x1) */ \
457
+ __ASM_EMIT (" vclt.f32 q4, q2, q14" ) /* q4 = [abs(min) < abs(x1) ] */ \
458
+ __ASM_EMIT (" vcgt.f32 q5, q3, q14" ) /* q4 = [abs(max) > abs(x1) ] */ \
459
+ __ASM_EMIT (" vbif q0, q10, q4" ) /* q0 = [abs(min) < abs(x2) ] ? min : x2 */ \
460
+ __ASM_EMIT (" vbif q1, q10, q5" ) /* q1 = [abs(max) > abs(x2) ] ? res : x2 */ \
461
+ __ASM_EMIT (" vbif q2, q14, q4" ) /* q12 = [abs(min) < abs(x2) ] ? abs(min) : abs(x2) */ \
462
+ __ASM_EMIT (" vbif q3, q14, q5" ) /* q13 = [abs(max) > abs(x2) ] ? abs(max) : abs(x2) */ \
463
+ __ASM_EMIT (" vclt.f32 q4, q2, q15" ) /* q4 = [abs(min) < abs(x1) ] */ \
464
+ __ASM_EMIT (" vcgt.f32 q5, q3, q15" ) /* q4 = [abs(max) > abs(x1) ] */ \
465
+ __ASM_EMIT (" vbif q0, q11, q4" ) /* q0 = [abs(min) < abs(x3) ] ? min : x3 */ \
466
+ __ASM_EMIT (" vbif q1, q11, q5" ) /* q1 = [abs(max) > abs(x3) ] ? res : x3 */ \
467
+ __ASM_EMIT (" vbif q2, q15, q4" ) /* q12 = [abs(min) < abs(x3) ] ? abs(min) : abs(x3) */ \
468
+ __ASM_EMIT (" vbif q3, q15, q5" ) /* q13 = [abs(max) > abs(x3) ] ? abs(max) : abs(x3) */ \
469
+ __ASM_EMIT (" subs %[count], #16" ) \
470
+ __ASM_EMIT (" bhs 1b" ) \
471
+ __ASM_EMIT (" 2:" ) \
472
+ /* x8 block */ \
473
+ __ASM_EMIT (" adds %[count], #8" ) \
474
+ __ASM_EMIT (" blt 4f" ) \
475
+ __ASM_EMIT (" vldm %[src]!, {q8-q9}" ) /* q8 = x0, q9 = x1 */ \
476
+ __ASM_EMIT (" vabs.f32 q12, q8" ) /* q12 = abs(x0) */ \
477
+ __ASM_EMIT (" vabs.f32 q13, q9" ) /* q13 = abs(x1) */ \
478
+ __ASM_EMIT (" vclt.f32 q4, q2, q12" ) /* q4 = [abs(min) < abs(x0) ] */ \
479
+ __ASM_EMIT (" vcgt.f32 q5, q3, q12" ) /* q4 = [abs(max) > abs(x0) ] */ \
480
+ __ASM_EMIT (" vbif q0, q8, q4" ) /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
481
+ __ASM_EMIT (" vbif q1, q8, q5" ) /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
482
+ __ASM_EMIT (" vbif q2, q12, q4" ) /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
483
+ __ASM_EMIT (" vbif q3, q12, q5" ) /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
484
+ __ASM_EMIT (" vclt.f32 q4, q2, q13" ) /* q4 = [abs(min) < abs(x1) ] */ \
485
+ __ASM_EMIT (" vcgt.f32 q5, q3, q13" ) /* q4 = [abs(max) > abs(x1) ] */ \
486
+ __ASM_EMIT (" vbif q0, q9, q4" ) /* q0 = [abs(min) < abs(x1) ] ? min : x1 */ \
487
+ __ASM_EMIT (" vbif q1, q9, q5" ) /* q1 = [abs(max) > abs(x1) ] ? res : x1 */ \
488
+ __ASM_EMIT (" vbif q2, q13, q4" ) /* q12 = [abs(min) < abs(x1) ] ? abs(min) : abs(x1) */ \
489
+ __ASM_EMIT (" vbif q3, q13, q5" ) /* q13 = [abs(max) > abs(x1) ] ? abs(max) : abs(x1) */ \
490
+ __ASM_EMIT (" sub %[count], #8" ) \
491
+ __ASM_EMIT (" 4:" ) \
492
+ /* x4 block */ \
493
+ __ASM_EMIT (" adds %[count], #4" ) \
494
+ __ASM_EMIT (" blt 6f" ) \
495
+ __ASM_EMIT (" vldm %[src]!, {q8}" ) /* q8 = x0, q9 = x1 */ \
496
+ __ASM_EMIT (" vabs.f32 q12, q8" ) /* q12 = abs(x0) */ \
497
+ __ASM_EMIT (" vclt.f32 q4, q2, q12" ) /* q4 = [abs(min) < abs(x0) ] */ \
498
+ __ASM_EMIT (" vcgt.f32 q5, q3, q12" ) /* q4 = [abs(max) > abs(x0) ] */ \
499
+ __ASM_EMIT (" vbif q0, q8, q4" ) /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
500
+ __ASM_EMIT (" vbif q1, q8, q5" ) /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
501
+ __ASM_EMIT (" vbif q2, q12, q4" ) /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
502
+ __ASM_EMIT (" vbif q3, q12, q5" ) /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
503
+ __ASM_EMIT (" sub %[count], #4" ) \
504
+ __ASM_EMIT (" 6:" ) \
505
+ __ASM_EMIT (" vext.32 q8, q0, q0, #2" ) /* q8 = x0 */ \
506
+ __ASM_EMIT (" vext.32 q12, q2, q2, #2" ) /* q12 = abs(x0) */ \
507
+ __ASM_EMIT (" vclt.f32 q4, q2, q12" ) /* q4 = [abs(min) < abs(x0) ] */ \
508
+ __ASM_EMIT (" vcgt.f32 q5, q3, q12" ) /* q4 = [abs(max) > abs(x0) ] */ \
509
+ __ASM_EMIT (" vbif q0, q8, q4" ) /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
510
+ __ASM_EMIT (" vbif q1, q8, q5" ) /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
511
+ __ASM_EMIT (" vbif q2, q12, q4" ) /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
512
+ __ASM_EMIT (" vbif q3, q12, q5" ) /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
513
+ __ASM_EMIT (" vext.32 q8, q0, q0, #1" ) /* q8 = x0 */ \
514
+ __ASM_EMIT (" vext.32 q12, q2, q2, #1" ) /* q12 = abs(x0) */ \
515
+ __ASM_EMIT (" vclt.f32 q4, q2, q12" ) /* q4 = [abs(min) < abs(x0) ] */ \
516
+ __ASM_EMIT (" vcgt.f32 q5, q3, q12" ) /* q4 = [abs(max) > abs(x0) ] */ \
517
+ __ASM_EMIT (" vbif q0, q8, q4" ) /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
518
+ __ASM_EMIT (" vbif q1, q8, q5" ) /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
519
+ __ASM_EMIT (" vbif q2, q12, q4" ) /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
520
+ __ASM_EMIT (" vbif q3, q12, q5" ) /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
521
+ /* x1 block */ \
522
+ __ASM_EMIT (" adds %[count], #3" ) \
523
+ __ASM_EMIT (" blt 8f" ) \
524
+ __ASM_EMIT (" 7:" ) \
525
+ __ASM_EMIT (" vld1.32 {d16[], d17[]}, [%[src]]!" ) \
526
+ __ASM_EMIT (" vabs.f32 q12, q8" ) /* q12 = abs(x0) */ \
527
+ __ASM_EMIT (" vclt.f32 q4, q2, q12" ) /* q4 = [abs(min) < abs(x0) ] */ \
528
+ __ASM_EMIT (" vcgt.f32 q5, q3, q12" ) /* q4 = [abs(max) > abs(x0) ] */ \
529
+ __ASM_EMIT (" vbif q0, q8, q4" ) /* q0 = [abs(min) < abs(x0) ] ? min : x0 */ \
530
+ __ASM_EMIT (" vbif q1, q8, q5" ) /* q1 = [abs(max) > abs(x0) ] ? res : x0 */ \
531
+ __ASM_EMIT (" vbif q2, q12, q4" ) /* q12 = [abs(min) < abs(x0) ] ? abs(min) : abs(x0) */ \
532
+ __ASM_EMIT (" vbif q3, q12, q5" ) /* q13 = [abs(max) > abs(x0) ] ? abs(max) : abs(x0) */ \
533
+ __ASM_EMIT (" subs %[count], #1" ) \
534
+ __ASM_EMIT (" bge 7b" ) \
535
+ __ASM_EMIT (" 8:" ) \
536
+ /* end */ \
537
+ __ASM_EMIT (" vst1.32 {d0[0]}, [%[min]]" ) \
538
+ __ASM_EMIT (" vst1.32 {d2[0]}, [%[max]]" )
539
+ : [count] " +r" (count), [src] " +r" (src)
540
+ : [min] " r" (min), [max] " r" (max)
541
+ : " cc" ,
542
+ " q1" , " q2" , " q3" , " q4" , " q5" ,
543
+ " q8" , " q9" , " q10" , " q11" , " q12" , " q13" , " q14" , " q15"
544
+ );
545
+ }
423
546
} /* namespace neon_d32 */
424
547
} /* namespace lsp */
425
548
0 commit comments