393#if BB_VECTOR_FIELD_SIMD
395namespace vector_field_detail {
413[[gnu::always_inline]]
inline void bb_vf_barrier_sq(uint64_t& s, v128_t& q)
noexcept
415 asm volatile(
"" :
"+r"(s),
"+r"(q));
418[[gnu::always_inline]]
inline void bb_vf_barrier_sqq(uint64_t& s, v128_t& q_lo, v128_t& q_hi)
noexcept
420 asm volatile(
"" :
"+r"(s),
"+r"(q_lo),
"+r"(q_hi));
429[[gnu::always_inline]]
inline void pack_4u64_to_9x29(
const uint64_t in[4], uint32_t
out[9])
noexcept
431 out[0] =
static_cast<uint32_t
>(in[0] & 0x1fffffff);
432 out[1] =
static_cast<uint32_t
>((in[0] >> 29) & 0x1fffffff);
433 out[2] =
static_cast<uint32_t
>(((in[0] >> 58) & 0x3f) | ((in[1] & 0x7fffff) << 6));
434 out[3] =
static_cast<uint32_t
>((in[1] >> 23) & 0x1fffffff);
435 out[4] =
static_cast<uint32_t
>(((in[1] >> 52) & 0xfff) | ((in[2] & 0x1ffff) << 12));
436 out[5] =
static_cast<uint32_t
>((in[2] >> 17) & 0x1fffffff);
437 out[6] =
static_cast<uint32_t
>(((in[2] >> 46) & 0x3ffff) | ((in[3] & 0x7ff) << 18));
438 out[7] =
static_cast<uint32_t
>((in[3] >> 11) & 0x1fffffff);
439 out[8] =
static_cast<uint32_t
>((in[3] >> 40) & 0x1fffffff);
445[[gnu::always_inline]]
inline void unpack_9x29_to_4u64(
const uint32_t in[9], uint64_t
out[4])
noexcept
447 const uint64_t i0 = in[0], i1 = in[1], i2 = in[2], i3 = in[3], i4 = in[4];
448 const uint64_t i5 = in[5], i6 = in[6], i7 = in[7], i8 = in[8];
449 out[0] = i0 | (i1 << 29) | (i2 << 58);
450 out[1] = (i2 >> 6) | (i3 << 23) | (i4 << 52);
451 out[2] = (i4 >> 12) | (i5 << 17) | (i6 << 46);
452 out[3] = (i6 >> 18) | (i7 << 11) | (i8 << 40);
462 vector_field_detail::pack_4u64_to_9x29(in[0].
data, scalar_data);
464 uint32_t limbs[4][9];
465 vector_field_detail::pack_4u64_to_9x29(in[1].
data, limbs[0]);
466 vector_field_detail::pack_4u64_to_9x29(in[2].
data, limbs[1]);
467 vector_field_detail::pack_4u64_to_9x29(in[3].
data, limbs[2]);
468 vector_field_detail::pack_4u64_to_9x29(in[4].
data, limbs[3]);
469 for (
size_t k = 0; k < 9; ++k) {
470 quad_data[k] = wasm_i32x4_make(
static_cast<int32_t
>(limbs[0][k]),
471 static_cast<int32_t
>(limbs[1][k]),
472 static_cast<int32_t
>(limbs[2][k]),
473 static_cast<int32_t
>(limbs[3][k]));
479 vector_field_detail::unpack_9x29_to_4u64(scalar_data,
out[0].
data);
480 uint32_t limbs[4][9];
481 for (
size_t k = 0; k < 9; ++k) {
482 limbs[0][k] =
static_cast<uint32_t
>(wasm_i32x4_extract_lane(quad_data[k], 0));
483 limbs[1][k] =
static_cast<uint32_t
>(wasm_i32x4_extract_lane(quad_data[k], 1));
484 limbs[2][k] =
static_cast<uint32_t
>(wasm_i32x4_extract_lane(quad_data[k], 2));
485 limbs[3][k] =
static_cast<uint32_t
>(wasm_i32x4_extract_lane(quad_data[k], 3));
487 vector_field_detail::unpack_9x29_to_4u64(limbs[0],
out[1].
data);
488 vector_field_detail::unpack_9x29_to_4u64(limbs[1],
out[2].
data);
489 vector_field_detail::unpack_9x29_to_4u64(limbs[2],
out[3].
data);
490 vector_field_detail::unpack_9x29_to_4u64(limbs[3],
out[4].
data);
498template <
class Params>
502 vector_field_detail::pack_4u64_to_9x29(s.data,
result.scalar_data);
503 for (
size_t k = 0; k < 9; ++k) {
504 result.quad_data[k] = wasm_i32x4_splat(
static_cast<int32_t
>(
result.scalar_data[k]));
526namespace vector_field_detail {
537[[gnu::always_inline]]
inline void transpose_4x4_i32x4(
538 v128_t r0, v128_t r1, v128_t r2, v128_t r3, v128_t& c0, v128_t& c1, v128_t& c2, v128_t& c3)
noexcept
540 const v128_t t0 = wasm_i32x4_shuffle(r0, r1, 0, 4, 1, 5);
541 const v128_t t1 = wasm_i32x4_shuffle(r0, r1, 2, 6, 3, 7);
542 const v128_t t2 = wasm_i32x4_shuffle(r2, r3, 0, 4, 1, 5);
543 const v128_t t3 = wasm_i32x4_shuffle(r2, r3, 2, 6, 3, 7);
544 c0 = wasm_i32x4_shuffle(t0, t2, 0, 1, 4, 5);
545 c1 = wasm_i32x4_shuffle(t0, t2, 2, 3, 6, 7);
546 c2 = wasm_i32x4_shuffle(t1, t3, 0, 1, 4, 5);
547 c3 = wasm_i32x4_shuffle(t1, t3, 2, 3, 6, 7);
555 vector_field_detail::pack_4u64_to_9x29(base[0].
data, scalar_data);
558 const uint8_t* p =
reinterpret_cast<const uint8_t*
>(base);
559 const v128_t f1_lo = wasm_v128_load(p + 32);
560 const v128_t f1_hi = wasm_v128_load(p + 48);
561 const v128_t f2_lo = wasm_v128_load(p + 64);
562 const v128_t f2_hi = wasm_v128_load(p + 80);
563 const v128_t f3_lo = wasm_v128_load(p + 96);
564 const v128_t f3_hi = wasm_v128_load(p + 112);
565 const v128_t f4_lo = wasm_v128_load(p + 128);
566 const v128_t f4_hi = wasm_v128_load(p + 144);
570 v128_t IN0, IN1, IN2, IN3, IN4, IN5, IN6, IN7;
571 vector_field_detail::transpose_4x4_i32x4(f1_lo, f2_lo, f3_lo, f4_lo, IN0, IN1, IN2, IN3);
572 vector_field_detail::transpose_4x4_i32x4(f1_hi, f2_hi, f3_hi, f4_hi, IN4, IN5, IN6, IN7);
591 const v128_t MASK29 = wasm_i32x4_splat(0x1fffffff);
592 quad_data[0] = wasm_v128_and(IN0, MASK29);
593 quad_data[1] = wasm_v128_and(wasm_v128_or(wasm_u32x4_shr(IN0, 29), wasm_i32x4_shl(IN1, 3)), MASK29);
594 quad_data[2] = wasm_v128_and(wasm_v128_or(wasm_u32x4_shr(IN1, 26), wasm_i32x4_shl(IN2, 6)), MASK29);
595 quad_data[3] = wasm_v128_and(wasm_v128_or(wasm_u32x4_shr(IN2, 23), wasm_i32x4_shl(IN3, 9)), MASK29);
596 quad_data[4] = wasm_v128_and(wasm_v128_or(wasm_u32x4_shr(IN3, 20), wasm_i32x4_shl(IN4, 12)), MASK29);
597 quad_data[5] = wasm_v128_and(wasm_v128_or(wasm_u32x4_shr(IN4, 17), wasm_i32x4_shl(IN5, 15)), MASK29);
598 quad_data[6] = wasm_v128_and(wasm_v128_or(wasm_u32x4_shr(IN5, 14), wasm_i32x4_shl(IN6, 18)), MASK29);
599 quad_data[7] = wasm_v128_and(wasm_v128_or(wasm_u32x4_shr(IN6, 11), wasm_i32x4_shl(IN7, 21)), MASK29);
603 quad_data[8] = wasm_u32x4_shr(IN7, 8);
606template <
class Params>
609 return VectorField(base);
612template <
class Params>
616 vector_field_detail::unpack_9x29_to_4u64(scalar_data, base[0].
data);
640 const v128_t l0 = quad_data[0], l1 = quad_data[1], l2 = quad_data[2];
641 const v128_t l3 = quad_data[3], l4 = quad_data[4], l5 = quad_data[5];
642 const v128_t l6 = quad_data[6], l7 = quad_data[7], l8 = quad_data[8];
644 const v128_t OUT0 = wasm_v128_or(l0, wasm_i32x4_shl(l1, 29));
645 const v128_t OUT1 = wasm_v128_or(wasm_u32x4_shr(l1, 3), wasm_i32x4_shl(l2, 26));
646 const v128_t OUT2 = wasm_v128_or(wasm_u32x4_shr(l2, 6), wasm_i32x4_shl(l3, 23));
647 const v128_t OUT3 = wasm_v128_or(wasm_u32x4_shr(l3, 9), wasm_i32x4_shl(l4, 20));
648 const v128_t OUT4 = wasm_v128_or(wasm_u32x4_shr(l4, 12), wasm_i32x4_shl(l5, 17));
649 const v128_t OUT5 = wasm_v128_or(wasm_u32x4_shr(l5, 15), wasm_i32x4_shl(l6, 14));
650 const v128_t OUT6 = wasm_v128_or(wasm_u32x4_shr(l6, 18), wasm_i32x4_shl(l7, 11));
651 const v128_t OUT7 = wasm_v128_or(wasm_u32x4_shr(l7, 21), wasm_i32x4_shl(l8, 8));
655 v128_t f1_lo, f2_lo, f3_lo, f4_lo, f1_hi, f2_hi, f3_hi, f4_hi;
656 vector_field_detail::transpose_4x4_i32x4(OUT0, OUT1, OUT2, OUT3, f1_lo, f2_lo, f3_lo, f4_lo);
657 vector_field_detail::transpose_4x4_i32x4(OUT4, OUT5, OUT6, OUT7, f1_hi, f2_hi, f3_hi, f4_hi);
659 uint8_t* dst =
reinterpret_cast<uint8_t*
>(base);
660 wasm_v128_store(dst + 32, f1_lo);
661 wasm_v128_store(dst + 48, f1_hi);
662 wasm_v128_store(dst + 64, f2_lo);
663 wasm_v128_store(dst + 80, f2_hi);
664 wasm_v128_store(dst + 96, f3_lo);
665 wasm_v128_store(dst + 112, f3_hi);
666 wasm_v128_store(dst + 128, f4_lo);
667 wasm_v128_store(dst + 144, f4_hi);
675 store_contiguous(base);
688template <
class Params>
690 const VectorField& other)
const noexcept
692 constexpr uint64_t MASK = 0x1fffffffULL;
693 const v128_t mask_splat = wasm_i32x4_splat(MASK);
698 uint64_t sr0 = scalar_data[0] + other.scalar_data[0];
699 v128_t qr0 = wasm_i32x4_add(quad_data[0], other.quad_data[0]);
700 uint64_t scarry = sr0 >> 29;
701 v128_t qcarry = wasm_u32x4_shr(qr0, 29);
703 qr0 = wasm_v128_and(qr0, mask_splat);
705 uint64_t sr1 = scalar_data[1] + other.scalar_data[1] + scarry;
706 v128_t qr1 = wasm_i32x4_add(wasm_i32x4_add(quad_data[1], other.quad_data[1]), qcarry);
708 qcarry = wasm_u32x4_shr(qr1, 29);
710 qr1 = wasm_v128_and(qr1, mask_splat);
711 vector_field_detail::bb_vf_barrier_sqq(sr1, qr1, qcarry);
712 asm volatile(
"" :
"+r"(scarry));
714 uint64_t sr2 = scalar_data[2] + other.scalar_data[2] + scarry;
715 v128_t qr2 = wasm_i32x4_add(wasm_i32x4_add(quad_data[2], other.quad_data[2]), qcarry);
717 qcarry = wasm_u32x4_shr(qr2, 29);
719 qr2 = wasm_v128_and(qr2, mask_splat);
720 vector_field_detail::bb_vf_barrier_sqq(sr2, qr2, qcarry);
721 asm volatile(
"" :
"+r"(scarry));
723 uint64_t sr3 = scalar_data[3] + other.scalar_data[3] + scarry;
724 v128_t qr3 = wasm_i32x4_add(wasm_i32x4_add(quad_data[3], other.quad_data[3]), qcarry);
726 qcarry = wasm_u32x4_shr(qr3, 29);
728 qr3 = wasm_v128_and(qr3, mask_splat);
729 vector_field_detail::bb_vf_barrier_sqq(sr3, qr3, qcarry);
730 asm volatile(
"" :
"+r"(scarry));
732 uint64_t sr4 = scalar_data[4] + other.scalar_data[4] + scarry;
733 v128_t qr4 = wasm_i32x4_add(wasm_i32x4_add(quad_data[4], other.quad_data[4]), qcarry);
735 qcarry = wasm_u32x4_shr(qr4, 29);
737 qr4 = wasm_v128_and(qr4, mask_splat);
738 vector_field_detail::bb_vf_barrier_sqq(sr4, qr4, qcarry);
739 asm volatile(
"" :
"+r"(scarry));
741 uint64_t sr5 = scalar_data[5] + other.scalar_data[5] + scarry;
742 v128_t qr5 = wasm_i32x4_add(wasm_i32x4_add(quad_data[5], other.quad_data[5]), qcarry);
744 qcarry = wasm_u32x4_shr(qr5, 29);
746 qr5 = wasm_v128_and(qr5, mask_splat);
747 vector_field_detail::bb_vf_barrier_sqq(sr5, qr5, qcarry);
748 asm volatile(
"" :
"+r"(scarry));
750 uint64_t sr6 = scalar_data[6] + other.scalar_data[6] + scarry;
751 v128_t qr6 = wasm_i32x4_add(wasm_i32x4_add(quad_data[6], other.quad_data[6]), qcarry);
753 qcarry = wasm_u32x4_shr(qr6, 29);
755 qr6 = wasm_v128_and(qr6, mask_splat);
756 vector_field_detail::bb_vf_barrier_sqq(sr6, qr6, qcarry);
757 asm volatile(
"" :
"+r"(scarry));
759 uint64_t sr7 = scalar_data[7] + other.scalar_data[7] + scarry;
760 v128_t qr7 = wasm_i32x4_add(wasm_i32x4_add(quad_data[7], other.quad_data[7]), qcarry);
762 qcarry = wasm_u32x4_shr(qr7, 29);
764 qr7 = wasm_v128_and(qr7, mask_splat);
765 vector_field_detail::bb_vf_barrier_sqq(sr7, qr7, qcarry);
766 asm volatile(
"" :
"+r"(scarry));
768 uint64_t sr8 = scalar_data[8] + other.scalar_data[8] + scarry;
769 v128_t qr8 = wasm_i32x4_add(wasm_i32x4_add(quad_data[8], other.quad_data[8]), qcarry);
773 uint64_t st0 = sr0 + TNM_WASM[0];
774 v128_t qt0 = wasm_i32x4_add(qr0, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[0])));
776 qcarry = wasm_u32x4_shr(qt0, 29);
778 qt0 = wasm_v128_and(qt0, mask_splat);
779 vector_field_detail::bb_vf_barrier_sqq(st0, qt0, qcarry);
780 asm volatile(
"" :
"+r"(scarry));
782 uint64_t st1 = sr1 + TNM_WASM[1] + scarry;
783 v128_t qt1 = wasm_i32x4_add(wasm_i32x4_add(qr1, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[1]))), qcarry);
785 qcarry = wasm_u32x4_shr(qt1, 29);
787 qt1 = wasm_v128_and(qt1, mask_splat);
788 vector_field_detail::bb_vf_barrier_sqq(st1, qt1, qcarry);
789 asm volatile(
"" :
"+r"(scarry));
791 uint64_t st2 = sr2 + TNM_WASM[2] + scarry;
792 v128_t qt2 = wasm_i32x4_add(wasm_i32x4_add(qr2, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[2]))), qcarry);
794 qcarry = wasm_u32x4_shr(qt2, 29);
796 qt2 = wasm_v128_and(qt2, mask_splat);
797 vector_field_detail::bb_vf_barrier_sqq(st2, qt2, qcarry);
798 asm volatile(
"" :
"+r"(scarry));
800 uint64_t st3 = sr3 + TNM_WASM[3] + scarry;
801 v128_t qt3 = wasm_i32x4_add(wasm_i32x4_add(qr3, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[3]))), qcarry);
803 qcarry = wasm_u32x4_shr(qt3, 29);
805 qt3 = wasm_v128_and(qt3, mask_splat);
806 vector_field_detail::bb_vf_barrier_sqq(st3, qt3, qcarry);
807 asm volatile(
"" :
"+r"(scarry));
809 uint64_t st4 = sr4 + TNM_WASM[4] + scarry;
810 v128_t qt4 = wasm_i32x4_add(wasm_i32x4_add(qr4, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[4]))), qcarry);
812 qcarry = wasm_u32x4_shr(qt4, 29);
814 qt4 = wasm_v128_and(qt4, mask_splat);
815 vector_field_detail::bb_vf_barrier_sqq(st4, qt4, qcarry);
816 asm volatile(
"" :
"+r"(scarry));
818 uint64_t st5 = sr5 + TNM_WASM[5] + scarry;
819 v128_t qt5 = wasm_i32x4_add(wasm_i32x4_add(qr5, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[5]))), qcarry);
821 qcarry = wasm_u32x4_shr(qt5, 29);
823 qt5 = wasm_v128_and(qt5, mask_splat);
824 vector_field_detail::bb_vf_barrier_sqq(st5, qt5, qcarry);
825 asm volatile(
"" :
"+r"(scarry));
827 uint64_t st6 = sr6 + TNM_WASM[6] + scarry;
828 v128_t qt6 = wasm_i32x4_add(wasm_i32x4_add(qr6, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[6]))), qcarry);
830 qcarry = wasm_u32x4_shr(qt6, 29);
832 qt6 = wasm_v128_and(qt6, mask_splat);
833 vector_field_detail::bb_vf_barrier_sqq(st6, qt6, qcarry);
834 asm volatile(
"" :
"+r"(scarry));
836 uint64_t st7 = sr7 + TNM_WASM[7] + scarry;
837 v128_t qt7 = wasm_i32x4_add(wasm_i32x4_add(qr7, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[7]))), qcarry);
839 qcarry = wasm_u32x4_shr(qt7, 29);
841 qt7 = wasm_v128_and(qt7, mask_splat);
842 vector_field_detail::bb_vf_barrier_sqq(st7, qt7, qcarry);
843 asm volatile(
"" :
"+r"(scarry));
845 uint64_t st8 = sr8 + TNM_WASM[8] + scarry;
846 v128_t qt8 = wasm_i32x4_add(wasm_i32x4_add(qr8, wasm_i32x4_splat(
static_cast<int32_t
>(TNM_WASM[8]))), qcarry);
848 const uint64_t sc_final = st8 >> 29;
849 const v128_t qc_final = wasm_u32x4_shr(qt8, 29);
851 qt8 = wasm_v128_and(qt8, mask_splat);
854 const uint64_t smask = 0ULL - sc_final;
857 const v128_t qmask = wasm_i32x4_eq(qc_final, wasm_i32x4_splat(1));
858 const uint64_t simask = ~smask;
860 result.scalar_data[0] =
static_cast<uint32_t
>((sr0 & simask) | (st0 & smask));
861 result.quad_data[0] = wasm_v128_bitselect(qt0, qr0, qmask);
862 result.scalar_data[1] =
static_cast<uint32_t
>((sr1 & simask) | (st1 & smask));
863 result.quad_data[1] = wasm_v128_bitselect(qt1, qr1, qmask);
864 result.scalar_data[2] =
static_cast<uint32_t
>((sr2 & simask) | (st2 & smask));
865 result.quad_data[2] = wasm_v128_bitselect(qt2, qr2, qmask);
866 result.scalar_data[3] =
static_cast<uint32_t
>((sr3 & simask) | (st3 & smask));
867 result.quad_data[3] = wasm_v128_bitselect(qt3, qr3, qmask);
868 result.scalar_data[4] =
static_cast<uint32_t
>((sr4 & simask) | (st4 & smask));
869 result.quad_data[4] = wasm_v128_bitselect(qt4, qr4, qmask);
870 result.scalar_data[5] =
static_cast<uint32_t
>((sr5 & simask) | (st5 & smask));
871 result.quad_data[5] = wasm_v128_bitselect(qt5, qr5, qmask);
872 result.scalar_data[6] =
static_cast<uint32_t
>((sr6 & simask) | (st6 & smask));
873 result.quad_data[6] = wasm_v128_bitselect(qt6, qr6, qmask);
874 result.scalar_data[7] =
static_cast<uint32_t
>((sr7 & simask) | (st7 & smask));
875 result.quad_data[7] = wasm_v128_bitselect(qt7, qr7, qmask);
876 result.scalar_data[8] =
static_cast<uint32_t
>((sr8 & simask) | (st8 & smask));
877 result.quad_data[8] = wasm_v128_bitselect(qt8, qr8, qmask);
889template <
class Params>
891 const VectorField& other)
const noexcept
893 constexpr uint64_t MASK = 0x1fffffffULL;
894 const v128_t mask_splat = wasm_i32x4_splat(MASK);
907 int64_t sdiff0 =
static_cast<int64_t
>(scalar_data[0]) -
static_cast<int64_t
>(other.scalar_data[0]);
908 v128_t qdiff0 = wasm_i32x4_sub(quad_data[0], other.quad_data[0]);
909 uint64_t sr0 =
static_cast<uint64_t
>(sdiff0) & MASK;
910 v128_t qr0 = wasm_v128_and(qdiff0, mask_splat);
912 int64_t sborrow = (sdiff0 < 0) ? 1 : 0;
913 v128_t qborrow = wasm_u32x4_shr(qdiff0, 31);
916 int64_t sdiff1 =
static_cast<int64_t
>(scalar_data[1]) -
static_cast<int64_t
>(other.scalar_data[1]) - sborrow;
917 v128_t qdiff1 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[1], other.quad_data[1]), qborrow);
918 uint64_t sr1 =
static_cast<uint64_t
>(sdiff1) & MASK;
919 v128_t qr1 = wasm_v128_and(qdiff1, mask_splat);
920 sborrow = (sdiff1 < 0) ? 1 : 0;
921 qborrow = wasm_u32x4_shr(qdiff1, 31);
922 vector_field_detail::bb_vf_barrier_sq(sr1, qr1);
923 asm volatile(
"" :
"+r"(sborrow),
"+r"(qborrow));
925 int64_t sdiff2 =
static_cast<int64_t
>(scalar_data[2]) -
static_cast<int64_t
>(other.scalar_data[2]) - sborrow;
926 v128_t qdiff2 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[2], other.quad_data[2]), qborrow);
927 uint64_t sr2 =
static_cast<uint64_t
>(sdiff2) & MASK;
928 v128_t qr2 = wasm_v128_and(qdiff2, mask_splat);
929 sborrow = (sdiff2 < 0) ? 1 : 0;
930 qborrow = wasm_u32x4_shr(qdiff2, 31);
931 vector_field_detail::bb_vf_barrier_sq(sr2, qr2);
932 asm volatile(
"" :
"+r"(sborrow),
"+r"(qborrow));
934 int64_t sdiff3 =
static_cast<int64_t
>(scalar_data[3]) -
static_cast<int64_t
>(other.scalar_data[3]) - sborrow;
935 v128_t qdiff3 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[3], other.quad_data[3]), qborrow);
936 uint64_t sr3 =
static_cast<uint64_t
>(sdiff3) & MASK;
937 v128_t qr3 = wasm_v128_and(qdiff3, mask_splat);
938 sborrow = (sdiff3 < 0) ? 1 : 0;
939 qborrow = wasm_u32x4_shr(qdiff3, 31);
940 vector_field_detail::bb_vf_barrier_sq(sr3, qr3);
941 asm volatile(
"" :
"+r"(sborrow),
"+r"(qborrow));
943 int64_t sdiff4 =
static_cast<int64_t
>(scalar_data[4]) -
static_cast<int64_t
>(other.scalar_data[4]) - sborrow;
944 v128_t qdiff4 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[4], other.quad_data[4]), qborrow);
945 uint64_t sr4 =
static_cast<uint64_t
>(sdiff4) & MASK;
946 v128_t qr4 = wasm_v128_and(qdiff4, mask_splat);
947 sborrow = (sdiff4 < 0) ? 1 : 0;
948 qborrow = wasm_u32x4_shr(qdiff4, 31);
949 vector_field_detail::bb_vf_barrier_sq(sr4, qr4);
950 asm volatile(
"" :
"+r"(sborrow),
"+r"(qborrow));
952 int64_t sdiff5 =
static_cast<int64_t
>(scalar_data[5]) -
static_cast<int64_t
>(other.scalar_data[5]) - sborrow;
953 v128_t qdiff5 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[5], other.quad_data[5]), qborrow);
954 uint64_t sr5 =
static_cast<uint64_t
>(sdiff5) & MASK;
955 v128_t qr5 = wasm_v128_and(qdiff5, mask_splat);
956 sborrow = (sdiff5 < 0) ? 1 : 0;
957 qborrow = wasm_u32x4_shr(qdiff5, 31);
958 vector_field_detail::bb_vf_barrier_sq(sr5, qr5);
959 asm volatile(
"" :
"+r"(sborrow),
"+r"(qborrow));
961 int64_t sdiff6 =
static_cast<int64_t
>(scalar_data[6]) -
static_cast<int64_t
>(other.scalar_data[6]) - sborrow;
962 v128_t qdiff6 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[6], other.quad_data[6]), qborrow);
963 uint64_t sr6 =
static_cast<uint64_t
>(sdiff6) & MASK;
964 v128_t qr6 = wasm_v128_and(qdiff6, mask_splat);
965 sborrow = (sdiff6 < 0) ? 1 : 0;
966 qborrow = wasm_u32x4_shr(qdiff6, 31);
967 vector_field_detail::bb_vf_barrier_sq(sr6, qr6);
968 asm volatile(
"" :
"+r"(sborrow),
"+r"(qborrow));
970 int64_t sdiff7 =
static_cast<int64_t
>(scalar_data[7]) -
static_cast<int64_t
>(other.scalar_data[7]) - sborrow;
971 v128_t qdiff7 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[7], other.quad_data[7]), qborrow);
972 uint64_t sr7 =
static_cast<uint64_t
>(sdiff7) & MASK;
973 v128_t qr7 = wasm_v128_and(qdiff7, mask_splat);
974 sborrow = (sdiff7 < 0) ? 1 : 0;
975 qborrow = wasm_u32x4_shr(qdiff7, 31);
976 vector_field_detail::bb_vf_barrier_sq(sr7, qr7);
977 asm volatile(
"" :
"+r"(sborrow),
"+r"(qborrow));
979 int64_t sdiff8 =
static_cast<int64_t
>(scalar_data[8]) -
static_cast<int64_t
>(other.scalar_data[8]) - sborrow;
980 v128_t qdiff8 = wasm_i32x4_sub(wasm_i32x4_sub(quad_data[8], other.quad_data[8]), qborrow);
981 uint64_t sr8 =
static_cast<uint64_t
>(sdiff8) & MASK;
982 v128_t qr8 = wasm_v128_and(qdiff8, mask_splat);
984 const uint64_t s_final_borrow = (sdiff8 < 0) ? 1 : 0;
985 const v128_t q_final_borrow_i32 = wasm_u32x4_shr(qdiff8, 31);
987 const v128_t q_final_borrow_mask = wasm_i32x4_eq(q_final_borrow_i32, wasm_i32x4_splat(1));
990 uint64_t ss0 = sr0 + TWOP_WASM[0];
991 v128_t qs0 = wasm_i32x4_add(qr0, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[0])));
992 uint64_t scarry = ss0 >> 29;
993 v128_t qcarry = wasm_u32x4_shr(qs0, 29);
995 qs0 = wasm_v128_and(qs0, mask_splat);
996 vector_field_detail::bb_vf_barrier_sqq(ss0, qs0, qcarry);
997 asm volatile(
"" :
"+r"(scarry));
999 uint64_t ss1 = sr1 + TWOP_WASM[1] + scarry;
1000 v128_t qs1 = wasm_i32x4_add(wasm_i32x4_add(qr1, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[1]))), qcarry);
1002 qcarry = wasm_u32x4_shr(qs1, 29);
1004 qs1 = wasm_v128_and(qs1, mask_splat);
1005 vector_field_detail::bb_vf_barrier_sqq(ss1, qs1, qcarry);
1006 asm volatile(
"" :
"+r"(scarry));
1008 uint64_t ss2 = sr2 + TWOP_WASM[2] + scarry;
1009 v128_t qs2 = wasm_i32x4_add(wasm_i32x4_add(qr2, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[2]))), qcarry);
1011 qcarry = wasm_u32x4_shr(qs2, 29);
1013 qs2 = wasm_v128_and(qs2, mask_splat);
1014 vector_field_detail::bb_vf_barrier_sqq(ss2, qs2, qcarry);
1015 asm volatile(
"" :
"+r"(scarry));
1017 uint64_t ss3 = sr3 + TWOP_WASM[3] + scarry;
1018 v128_t qs3 = wasm_i32x4_add(wasm_i32x4_add(qr3, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[3]))), qcarry);
1020 qcarry = wasm_u32x4_shr(qs3, 29);
1022 qs3 = wasm_v128_and(qs3, mask_splat);
1023 vector_field_detail::bb_vf_barrier_sqq(ss3, qs3, qcarry);
1024 asm volatile(
"" :
"+r"(scarry));
1026 uint64_t ss4 = sr4 + TWOP_WASM[4] + scarry;
1027 v128_t qs4 = wasm_i32x4_add(wasm_i32x4_add(qr4, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[4]))), qcarry);
1029 qcarry = wasm_u32x4_shr(qs4, 29);
1031 qs4 = wasm_v128_and(qs4, mask_splat);
1032 vector_field_detail::bb_vf_barrier_sqq(ss4, qs4, qcarry);
1033 asm volatile(
"" :
"+r"(scarry));
1035 uint64_t ss5 = sr5 + TWOP_WASM[5] + scarry;
1036 v128_t qs5 = wasm_i32x4_add(wasm_i32x4_add(qr5, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[5]))), qcarry);
1038 qcarry = wasm_u32x4_shr(qs5, 29);
1040 qs5 = wasm_v128_and(qs5, mask_splat);
1041 vector_field_detail::bb_vf_barrier_sqq(ss5, qs5, qcarry);
1042 asm volatile(
"" :
"+r"(scarry));
1044 uint64_t ss6 = sr6 + TWOP_WASM[6] + scarry;
1045 v128_t qs6 = wasm_i32x4_add(wasm_i32x4_add(qr6, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[6]))), qcarry);
1047 qcarry = wasm_u32x4_shr(qs6, 29);
1049 qs6 = wasm_v128_and(qs6, mask_splat);
1050 vector_field_detail::bb_vf_barrier_sqq(ss6, qs6, qcarry);
1051 asm volatile(
"" :
"+r"(scarry));
1053 uint64_t ss7 = sr7 + TWOP_WASM[7] + scarry;
1054 v128_t qs7 = wasm_i32x4_add(wasm_i32x4_add(qr7, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[7]))), qcarry);
1056 qcarry = wasm_u32x4_shr(qs7, 29);
1058 qs7 = wasm_v128_and(qs7, mask_splat);
1059 vector_field_detail::bb_vf_barrier_sqq(ss7, qs7, qcarry);
1060 asm volatile(
"" :
"+r"(scarry));
1062 uint64_t ss8 = sr8 + TWOP_WASM[8] + scarry;
1063 v128_t qs8 = wasm_i32x4_add(wasm_i32x4_add(qr8, wasm_i32x4_splat(
static_cast<int32_t
>(TWOP_WASM[8]))), qcarry);
1065 qs8 = wasm_v128_and(qs8, mask_splat);
1068 const uint64_t smask = 0ULL - s_final_borrow;
1069 const uint64_t simask = ~smask;
1070 const v128_t qmask = q_final_borrow_mask;
1072 result.scalar_data[0] =
static_cast<uint32_t
>((sr0 & simask) | (ss0 & smask));
1073 result.quad_data[0] = wasm_v128_bitselect(qs0, qr0, qmask);
1074 result.scalar_data[1] =
static_cast<uint32_t
>((sr1 & simask) | (ss1 & smask));
1075 result.quad_data[1] = wasm_v128_bitselect(qs1, qr1, qmask);
1076 result.scalar_data[2] =
static_cast<uint32_t
>((sr2 & simask) | (ss2 & smask));
1077 result.quad_data[2] = wasm_v128_bitselect(qs2, qr2, qmask);
1078 result.scalar_data[3] =
static_cast<uint32_t
>((sr3 & simask) | (ss3 & smask));
1079 result.quad_data[3] = wasm_v128_bitselect(qs3, qr3, qmask);
1080 result.scalar_data[4] =
static_cast<uint32_t
>((sr4 & simask) | (ss4 & smask));
1081 result.quad_data[4] = wasm_v128_bitselect(qs4, qr4, qmask);
1082 result.scalar_data[5] =
static_cast<uint32_t
>((sr5 & simask) | (ss5 & smask));
1083 result.quad_data[5] = wasm_v128_bitselect(qs5, qr5, qmask);
1084 result.scalar_data[6] =
static_cast<uint32_t
>((sr6 & simask) | (ss6 & smask));
1085 result.quad_data[6] = wasm_v128_bitselect(qs6, qr6, qmask);
1086 result.scalar_data[7] =
static_cast<uint32_t
>((sr7 & simask) | (ss7 & smask));
1087 result.quad_data[7] = wasm_v128_bitselect(qs7, qr7, qmask);
1088 result.scalar_data[8] =
static_cast<uint32_t
>((sr8 & simask) | (ss8 & smask));
1089 result.quad_data[8] = wasm_v128_bitselect(qs8, qr8, qmask);
1103template <
class Params>
1106 const VectorField d = (*this) - other;
1110 uint64_t sacc_z = d.scalar_data[0];
1111 v128_t qacc_z = d.quad_data[0];
1112 uint64_t sacc_p = d.scalar_data[0] ^ P_WASM[0];
1113 v128_t qacc_p = wasm_v128_xor(d.quad_data[0], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[0])));
1114 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1115 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1117 sacc_z |= d.scalar_data[1];
1118 qacc_z = wasm_v128_or(qacc_z, d.quad_data[1]);
1119 sacc_p |= d.scalar_data[1] ^ P_WASM[1];
1120 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[1], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[1]))));
1121 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1122 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1124 sacc_z |= d.scalar_data[2];
1125 qacc_z = wasm_v128_or(qacc_z, d.quad_data[2]);
1126 sacc_p |= d.scalar_data[2] ^ P_WASM[2];
1127 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[2], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[2]))));
1128 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1129 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1131 sacc_z |= d.scalar_data[3];
1132 qacc_z = wasm_v128_or(qacc_z, d.quad_data[3]);
1133 sacc_p |= d.scalar_data[3] ^ P_WASM[3];
1134 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[3], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[3]))));
1135 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1136 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1138 sacc_z |= d.scalar_data[4];
1139 qacc_z = wasm_v128_or(qacc_z, d.quad_data[4]);
1140 sacc_p |= d.scalar_data[4] ^ P_WASM[4];
1141 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[4], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[4]))));
1142 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1143 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1145 sacc_z |= d.scalar_data[5];
1146 qacc_z = wasm_v128_or(qacc_z, d.quad_data[5]);
1147 sacc_p |= d.scalar_data[5] ^ P_WASM[5];
1148 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[5], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[5]))));
1149 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1150 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1152 sacc_z |= d.scalar_data[6];
1153 qacc_z = wasm_v128_or(qacc_z, d.quad_data[6]);
1154 sacc_p |= d.scalar_data[6] ^ P_WASM[6];
1155 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[6], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[6]))));
1156 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1157 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1159 sacc_z |= d.scalar_data[7];
1160 qacc_z = wasm_v128_or(qacc_z, d.quad_data[7]);
1161 sacc_p |= d.scalar_data[7] ^ P_WASM[7];
1162 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[7], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[7]))));
1163 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1164 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1166 sacc_z |= d.scalar_data[8];
1167 qacc_z = wasm_v128_or(qacc_z, d.quad_data[8]);
1168 sacc_p |= d.scalar_data[8] ^ P_WASM[8];
1169 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(d.quad_data[8], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[8]))));
1170 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1171 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1177 const v128_t qzero = wasm_i32x4_splat(0);
1178 const uint32_t lanes_z = wasm_i32x4_bitmask(wasm_i32x4_eq(qacc_z, qzero));
1179 const uint32_t lanes_p = wasm_i32x4_bitmask(wasm_i32x4_eq(qacc_p, qzero));
1180 const uint32_t lanes_eq = lanes_z | lanes_p;
1182 const uint32_t scalar_eq = ((sacc_z == 0) || (sacc_p == 0)) ? 1u : 0u;
1185 return scalar_eq | (lanes_eq << 1);
1191 uint64_t sacc_z = scalar_data[0];
1192 v128_t qacc_z = quad_data[0];
1193 uint64_t sacc_p = scalar_data[0] ^ P_WASM[0];
1194 v128_t qacc_p = wasm_v128_xor(quad_data[0], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[0])));
1195 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1196 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1198 sacc_z |= scalar_data[1];
1199 qacc_z = wasm_v128_or(qacc_z, quad_data[1]);
1200 sacc_p |= scalar_data[1] ^ P_WASM[1];
1201 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[1], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[1]))));
1202 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1203 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1205 sacc_z |= scalar_data[2];
1206 qacc_z = wasm_v128_or(qacc_z, quad_data[2]);
1207 sacc_p |= scalar_data[2] ^ P_WASM[2];
1208 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[2], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[2]))));
1209 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1210 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1212 sacc_z |= scalar_data[3];
1213 qacc_z = wasm_v128_or(qacc_z, quad_data[3]);
1214 sacc_p |= scalar_data[3] ^ P_WASM[3];
1215 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[3], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[3]))));
1216 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1217 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1219 sacc_z |= scalar_data[4];
1220 qacc_z = wasm_v128_or(qacc_z, quad_data[4]);
1221 sacc_p |= scalar_data[4] ^ P_WASM[4];
1222 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[4], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[4]))));
1223 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1224 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1226 sacc_z |= scalar_data[5];
1227 qacc_z = wasm_v128_or(qacc_z, quad_data[5]);
1228 sacc_p |= scalar_data[5] ^ P_WASM[5];
1229 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[5], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[5]))));
1230 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1231 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1233 sacc_z |= scalar_data[6];
1234 qacc_z = wasm_v128_or(qacc_z, quad_data[6]);
1235 sacc_p |= scalar_data[6] ^ P_WASM[6];
1236 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[6], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[6]))));
1237 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1238 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1240 sacc_z |= scalar_data[7];
1241 qacc_z = wasm_v128_or(qacc_z, quad_data[7]);
1242 sacc_p |= scalar_data[7] ^ P_WASM[7];
1243 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[7], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[7]))));
1244 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1245 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1247 sacc_z |= scalar_data[8];
1248 qacc_z = wasm_v128_or(qacc_z, quad_data[8]);
1249 sacc_p |= scalar_data[8] ^ P_WASM[8];
1250 qacc_p = wasm_v128_or(qacc_p, wasm_v128_xor(quad_data[8], wasm_i32x4_splat(
static_cast<int32_t
>(P_WASM[8]))));
1251 vector_field_detail::bb_vf_barrier_sq(sacc_z, qacc_z);
1252 vector_field_detail::bb_vf_barrier_sq(sacc_p, qacc_p);
1254 const v128_t qzero = wasm_i32x4_splat(0);
1255 const uint32_t lanes_z = wasm_i32x4_bitmask(wasm_i32x4_eq(qacc_z, qzero));
1256 const uint32_t lanes_p = wasm_i32x4_bitmask(wasm_i32x4_eq(qacc_p, qzero));
1257 const uint32_t lanes_iz = lanes_z | lanes_p;
1259 const uint32_t scalar_iz = ((sacc_z == 0) || (sacc_p == 0)) ? 1u : 0u;
1261 return scalar_iz | (lanes_iz << 1);
1310 for (
size_t i = 0; i < 5; ++i) {
1317 for (
size_t i = 0; i < 5; ++i) {