/*
* Copyright © 2024, VideoLAN and dav1d authors
* Copyright © 2024, Janne Grunau
* Copyright © 2024, Martin Storsjo
* Copyright © 2024, Arm Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "src/arm/asm.S"
#include "util.S"
#if HAVE_DOTPROD
ENABLE_DOTPROD
// No spaces in these expressions, due to gas-preprocessor. It is translated by
// -1 to save the negative offset at getting the address of `mc_subpel_filters`.
#define REGULAR1 (((0 *15 -1 )<<7 )|(3 *15 -1 ))
#define SMOOTH1 (((1 *15 -1 )<<7 )|(4 *15 -1 ))
#define SHARP1 (((2 *15 -1 )<<7 )|(3 *15 -1 ))
#define FUNC_ALIGN 2
#define JUMP_ALIGN 2
#define LOOP_ALIGN 2
const h_tbl_neon_dotprod, align =4
// Shuffle indices to permute horizontal samples in preparation for
// input to SDOT instructions. The 8 -tap horizontal convolution uses
// sample indices in the interval of [-3 , 4 ] relative to the current
// sample position.
.byte 0 , 1 , 2 , 3 , 1 , 2 , 3 , 4 , 2 , 3 , 4 , 5 , 3 , 4 , 5 , 6
.byte 4 , 5 , 6 , 7 , 5 , 6 , 7 , 8 , 6 , 7 , 8 , 9 , 7 , 8 , 9 , 10
.byte 8 , 9 , 10 , 11 , 9 , 10 , 11 , 12 , 10 , 11 , 12 , 13 , 11 , 12 , 13 , 14
// Shuffle indices to permute horizontal samples in preparation for
// input to USMMLA instructions.
#define OFFSET_USMMLA 48
.byte 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
.byte 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13
// Lookup table used to help conversion of shifted 32 -bit values to 8 -bit.
#define OFFSET_CVT_32_8 80
.byte 1 , 2 , 5 , 6 , 9 , 10 , 13 , 14 , 17 , 18 , 21 , 22 , 25 , 26 , 29 , 30
endconst
const v_tbl_neon_dotprod, align =4
// Vertical convolutions are also using SDOT instructions, where a
// 128 -bit register contains a transposed 4 x4 matrix of values.
// Subsequent iterations of the vertical convolution can reuse the
// 3 x4 sub -matrix from the previous loop iteration. These shuffle
// indices shift and merge this 4 x4 matrix with the values of a new
// line.
.byte 1 , 2 , 3 , 16 , 5 , 6 , 7 , 20 , 9 , 10 , 11 , 24 , 13 , 14 , 15 , 28
.byte 1 , 2 , 3 , 16 , 5 , 6 , 7 , 17 , 9 , 10 , 11 , 18 , 13 , 14 , 15 , 19
.byte 1 , 2 , 3 , 20 , 5 , 6 , 7 , 21 , 9 , 10 , 11 , 22 , 13 , 14 , 15 , 23
.byte 1 , 2 , 3 , 24 , 5 , 6 , 7 , 25 , 9 , 10 , 11 , 26 , 13 , 14 , 15 , 27
.byte 1 , 2 , 3 , 28 , 5 , 6 , 7 , 29 , 9 , 10 , 11 , 30 , 13 , 14 , 15 , 31
endconst
.macro make_8tap_fn op, type, type_h, type_v, isa, jump=1
function \op\()_8 tap_\type\()_8 bpc_\isa, export=1 , align =FUNC_ALIGN
mov x9, \type_h
mov x10, \type_v
.if \jump
b \op\()_8 tap_\isa
.endif
endfunc
.endm
.macro filter_8tap_fn type, dot, isa, dst, d_strd, src, s_strd, w, h, mx, my, xmx, xmy, ldst, lsrc, wd_strd
make_8tap_fn \type, sharp, SHARP1, SHARP1, \isa
make_8tap_fn \type, sharp_smooth, SHARP1, SMOOTH1, \isa
make_8tap_fn \type, sharp_regular, SHARP1, REGULAR1, \isa
make_8tap_fn \type, smooth_sharp, SMOOTH1, SHARP1, \isa
make_8tap_fn \type, smooth, SMOOTH1, SMOOTH1, \isa
make_8tap_fn \type, smooth_regular, SMOOTH1, REGULAR1, \isa
make_8tap_fn \type, regular_sharp, REGULAR1, SHARP1, \isa
make_8tap_fn \type, regular_smooth, REGULAR1, SMOOTH1, \isa
make_8tap_fn \type, regular, REGULAR1, REGULAR1, \isa, jump=0
function \type\()_8 tap_\isa, align =FUNC_ALIGN
clz w8, \w
mov w11, #0 x4081 // (1 << 14 ) | (1 << 7 ) | (1 << 0 )
sub w8, w8, #24 // for jump tables
movrel x12, X(mc_subpel_filters)
cbnz \mx, L(\type\()_8 tap_h_hv_\isa)
cbnz \my, L(\type\()_8 tap_v_\isa)
.ifc \type, prep
add \wd_strd, \w, \w // prep_neon needs w * 2 as stride
.endif
b X(\type\()_neon)
.align JUMP_ALIGN
L(\type\()_8 tap_v_\isa):
madd \my, \my, w11, w10
movrel x13, v_tbl_neon_dotprod
sub \src, \src, \s_strd
.ifc \isa, neon_dotprod
.ifc \type, prep
mov w8, #0 x2002 // FILTER_WEIGHT * 128 + rounding
dup v4.4 s, w8
.else
movi v4.4 s, #32 , lsl #8 // FILTER_WEIGHT * 128 , bias for SDOT
.endif
.endif
ubfx w11, \my, #7 , #7
and \my, \my, #0 x7F
ldp q6, q28, [x13]
cmp \h, #4
csel \my, \my, w11, le
sub \src, \src, \s_strd, lsl #1 // src - s_strd * 3
add \xmy, x12, \xmy, lsl #3 // subpel V filter address
ldr q29, [x13, #32 ]
.ifc \isa, neon_dotprod
movi v5.16 b, #128
.endif
ldr d7, [\xmy]
cmp \w, #8
b.eq 80 f
b.lt 40 f
// .align JUMP_ALIGN // fallthrough
160 : // V - 16 xN+
ldp q30, q31, [x13, #48 ]
.ifc \type, prep
add \wd_strd, \w, \w
.endif
.align LOOP_ALIGN
161 :
mov \lsrc, \src
mov \ldst, \dst
sub w8, \h, #1
ldr q16, [\lsrc]
ldr q17, [\lsrc, \s_strd]
add \lsrc, \lsrc, \s_strd, lsl #1
ldr q18, [\lsrc]
ldr q19, [\lsrc, \s_strd]
add \lsrc, \lsrc, \s_strd, lsl #1
zip1 v0.16 b, v16.16 b, v17.16 b
zip2 v1.16 b, v16.16 b, v17.16 b
zip1 v2.16 b, v18.16 b, v19.16 b
zip2 v3.16 b, v18.16 b, v19.16 b
ldr q20, [\lsrc]
ldr q21, [\lsrc, \s_strd]
add \lsrc, \lsrc, \s_strd, lsl #1
ldr q22, [\lsrc]
ldr q23, [\lsrc, \s_strd]
add \lsrc, \lsrc, \s_strd, lsl #1
zip1 v18.16 b, v20.16 b, v21.16 b
zip2 v21.16 b, v20.16 b, v21.16 b
zip1 v24.16 b, v22.16 b, v23.16 b
zip2 v27.16 b, v22.16 b, v23.16 b
zip1 v16.8 h, v0.8 h, v2.8 h
zip2 v19.8 h, v0.8 h, v2.8 h
zip1 v22.8 h, v1.8 h, v3.8 h
zip2 v25.8 h, v1.8 h, v3.8 h
zip1 v17.8 h, v18.8 h, v24.8 h
zip2 v20.8 h, v18.8 h, v24.8 h
zip1 v23.8 h, v21.8 h, v27.8 h
zip2 v26.8 h, v21.8 h, v27.8 h
.ifc \isa, neon_dotprod
sub v16.16 b, v16.16 b, v5.16 b
sub v19.16 b, v19.16 b, v5.16 b
sub v22.16 b, v22.16 b, v5.16 b
sub v25.16 b, v25.16 b, v5.16 b
sub v17.16 b, v17.16 b, v5.16 b
sub v20.16 b, v20.16 b, v5.16 b
sub v23.16 b, v23.16 b, v5.16 b
sub v26.16 b, v26.16 b, v5.16 b
.endif
.align LOOP_ALIGN
16 :
.ifc \isa, neon_i8mm
ld1 {v18.16 b}, [\lsrc], \s_strd
movi v0.4 s, #0
movi v1.4 s, #0
movi v2.4 s, #0
movi v3.4 s, #0
mov v21.16 b, v18.16 b
mov v24.16 b, v18.16 b
mov v27.16 b, v18.16 b
.else // neon_dotprod
ld1 {v27.16 b}, [\lsrc], \s_strd
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
mov v2.16 b, v4.16 b
mov v3.16 b, v4.16 b
sub v18.16 b, v27.16 b, v5.16 b
sub v21.16 b, v27.16 b, v5.16 b
sub v24.16 b, v27.16 b, v5.16 b
sub v27.16 b, v27.16 b, v5.16 b
.endif
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v2.4 s, v22.16 b, v7.4 b[0 ]
\dot v3.4 s, v25.16 b, v7.4 b[0 ]
tbl v16.16 b, {v16.16 b, v17.16 b}, v6.16 b
tbl v19.16 b, {v19.16 b, v20.16 b}, v6.16 b
tbl v22.16 b, {v22.16 b, v23.16 b}, v6.16 b
tbl v25.16 b, {v25.16 b, v26.16 b}, v6.16 b
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
\dot v2.4 s, v23.16 b, v7.4 b[1 ]
\dot v3.4 s, v26.16 b, v7.4 b[1 ]
tbl v17.16 b, {v17.16 b, v18.16 b}, v28.16 b
tbl v20.16 b, {v20.16 b, v21.16 b}, v29.16 b
tbl v23.16 b, {v23.16 b, v24.16 b}, v30.16 b
tbl v26.16 b, {v26.16 b, v27.16 b}, v31.16 b
subs w8, w8, #1
uzp1 v0.8 h, v0.8 h, v1.8 h
uzp1 v2.8 h, v2.8 h, v3.8 h
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v0.8 h, v0.8 h, #2
srshr v1.8 h, v2.8 h, #2
.else
sshr v0.8 h, v0.8 h, #2
sshr v1.8 h, v2.8 h, #2
.endif
st1 {v0.8 h, v1.8 h}, [\ldst], \d_strd
.else // put
sqrshrun v0.8 b, v0.8 h, #6
sqrshrun2 v0.16 b, v2.8 h, #6
st1 {v0.16 b}, [\ldst], \d_strd
.endif
b.gt 16 b
.ifc \isa, neon_i8mm
movi v0.4 s, #0
movi v1.4 s, #0
movi v2.4 s, #0
movi v3.4 s, #0
.else // neon_dotprod
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
mov v2.16 b, v4.16 b
mov v3.16 b, v4.16 b
.endif
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v2.4 s, v22.16 b, v7.4 b[0 ]
\dot v3.4 s, v25.16 b, v7.4 b[0 ]
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
\dot v2.4 s, v23.16 b, v7.4 b[1 ]
\dot v3.4 s, v26.16 b, v7.4 b[1 ]
subs \w, \w, #16
uzp1 v0.8 h, v0.8 h, v1.8 h
uzp1 v2.8 h, v2.8 h, v3.8 h
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v0.8 h, v0.8 h, #2
srshr v1.8 h, v2.8 h, #2
.else
sshr v0.8 h, v0.8 h, #2
sshr v1.8 h, v2.8 h, #2
.endif
stp q0, q1, [\ldst]
add \dst, \dst, #32
.else // put
sqrshrun v0.8 b, v0.8 h, #6
sqrshrun2 v0.16 b, v2.8 h, #6
str q0, [\ldst]
add \dst, \dst, #16
.endif
add \src, \src, #16
b.gt 161 b
ret
.align JUMP_ALIGN
80 : // V - 8 xN
ldr d16, [\src]
ldr d17, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr d18, [\src]
ldr d19, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr d20, [\src]
ldr d21, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr d22, [\src]
ldr d23, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
subs \h, \h, #2 // for prep: sub is enough
zip1 v0.16 b, v16.16 b, v17.16 b
zip1 v2.16 b, v18.16 b, v19.16 b
zip1 v18.16 b, v20.16 b, v21.16 b
zip1 v24.16 b, v22.16 b, v23.16 b
zip1 v16.8 h, v0.8 h, v2.8 h
zip2 v19.8 h, v0.8 h, v2.8 h
zip1 v17.8 h, v18.8 h, v24.8 h
zip2 v20.8 h, v18.8 h, v24.8 h
.ifc \isa, neon_dotprod
sub v16.16 b, v16.16 b, v5.16 b
sub v19.16 b, v19.16 b, v5.16 b
sub v17.16 b, v17.16 b, v5.16 b
sub v20.16 b, v20.16 b, v5.16 b
.endif
.ifc \type, put
b.eq 82 f
.endif
.align LOOP_ALIGN
8 :
.ifc \isa, neon_i8mm
ldr d18, [\src]
movi v0.4 s, #0
movi v1.4 s, #0
ldr d24, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
movi v2.4 s, #0
movi v3.4 s, #0
mov v21.8 b, v18.8 b
mov v27.8 b, v24.8 b
.else // neon_dotprod
ldr d21, [\src]
ldr d27, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
mov v2.16 b, v4.16 b
mov v3.16 b, v4.16 b
sub v18.16 b, v21.16 b, v5.16 b
sub v21.16 b, v21.16 b, v5.16 b
sub v24.16 b, v27.16 b, v5.16 b
sub v27.16 b, v27.16 b, v5.16 b
.endif
tbl v22.16 b, {v16.16 b, v17.16 b}, v6.16 b
tbl v25.16 b, {v19.16 b, v20.16 b}, v6.16 b
tbl v23.16 b, {v17.16 b, v18.16 b}, v28.16 b
tbl v26.16 b, {v20.16 b, v21.16 b}, v29.16 b
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
tbl v16.16 b, {v22.16 b, v23.16 b}, v6.16 b
tbl v19.16 b, {v25.16 b, v26.16 b}, v6.16 b
tbl v17.16 b, {v23.16 b, v24.16 b}, v28.16 b
tbl v20.16 b, {v26.16 b, v27.16 b}, v29.16 b
\dot v2.4 s, v22.16 b, v7.4 b[0 ]
\dot v2.4 s, v23.16 b, v7.4 b[1 ]
\dot v3.4 s, v25.16 b, v7.4 b[0 ]
\dot v3.4 s, v26.16 b, v7.4 b[1 ]
subs \h, \h, #2
uzp1 v0.8 h, v0.8 h, v1.8 h
uzp1 v2.8 h, v2.8 h, v3.8 h
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v0.8 h, v0.8 h, #2
srshr v1.8 h, v2.8 h, #2
.else
sshr v0.8 h, v0.8 h, #2
sshr v1.8 h, v2.8 h, #2
.endif
stp q0, q1, [\dst], #32
.else // put
sqrshrun v0.8 b, v0.8 h, #6
sqrshrun v1.8 b, v2.8 h, #6
str d0, [\dst]
str d1, [\dst, \d_strd]
add \dst, \dst, \d_strd, lsl #1
.endif
b.gt 8 b
.ifc \type, put
.align JUMP_ALIGN
82 :
.endif
.ifc \isa, neon_i8mm
ldr d18, [\src]
movi v0.4 s, #0
movi v1.4 s, #0
movi v2.4 s, #0
movi v3.4 s, #0
mov v21.8 b, v18.8 b
.else // neon_dotprod
ldr d21, [\src]
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
mov v2.16 b, v4.16 b
mov v3.16 b, v4.16 b
sub v18.16 b, v21.16 b, v5.16 b
sub v21.16 b, v21.16 b, v5.16 b
.endif
tbl v22.16 b, {v16.16 b, v17.16 b}, v6.16 b
tbl v25.16 b, {v19.16 b, v20.16 b}, v6.16 b
tbl v23.16 b, {v17.16 b, v18.16 b}, v28.16 b
tbl v26.16 b, {v20.16 b, v21.16 b}, v29.16 b
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
\dot v2.4 s, v22.16 b, v7.4 b[0 ]
\dot v2.4 s, v23.16 b, v7.4 b[1 ]
\dot v3.4 s, v25.16 b, v7.4 b[0 ]
\dot v3.4 s, v26.16 b, v7.4 b[1 ]
uzp1 v0.8 h, v0.8 h, v1.8 h
uzp1 v2.8 h, v2.8 h, v3.8 h
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v0.8 h, v0.8 h, #2
srshr v1.8 h, v2.8 h, #2
.else
sshr v0.8 h, v0.8 h, #2
sshr v1.8 h, v2.8 h, #2
.endif
stp q0, q1, [\dst]
.else // put
sqrshrun v0.8 b, v0.8 h, #6
sqrshrun v1.8 b, v2.8 h, #6
str d0, [\dst]
str d1, [\dst, \d_strd]
.endif
ret
.align JUMP_ALIGN
40 : // V - 4 xN or 2 xN (put only)
.ifc \type, put
cmp \w, #2
b.eq 20 f
.endif
ldr s16, [\src]
ldr s17, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr s18, [\src]
ldr s19, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr s20, [\src]
ldr s21, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr s22, [\src]
ldr s23, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
subs \h, \h, #2 // for prep: sub is enough
zip1 v0.8 b, v16.8 b, v17.8 b
zip1 v2.8 b, v18.8 b, v19.8 b
zip1 v18.8 b, v20.8 b, v21.8 b
zip1 v24.8 b, v22.8 b, v23.8 b
zip1 v16.8 h, v0.8 h, v2.8 h
zip1 v17.8 h, v18.8 h, v24.8 h
.ifc \isa, neon_dotprod
sub v16.16 b, v16.16 b, v5.16 b
sub v17.16 b, v17.16 b, v5.16 b
.endif
.ifc \type, put
b.eq 42 f
.endif
.align LOOP_ALIGN
4 :
ldr s18, [\src]
ldr s21, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
.ifc \isa, neon_i8mm
movi v0.4 s, #0
movi v1.4 s, #0
.else // neon_dotprod
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
sub v18.16 b, v18.16 b, v5.16 b
sub v21.16 b, v21.16 b, v5.16 b
.endif
tbl v19.16 b, {v16.16 b, v17.16 b}, v6.16 b
tbl v20.16 b, {v17.16 b, v18.16 b}, v28.16 b
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
tbl v16.16 b, {v19.16 b, v20.16 b}, v6.16 b
tbl v17.16 b, {v20.16 b, v21.16 b}, v28.16 b
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
.ifc \type, prep
subs \h, \h, #2
.ifc \isa, neon_i8mm
rshrn v0.4 h, v0.4 s, #2
rshrn2 v0.8 h, v1.4 s, #2
.else
shrn v0.4 h, v0.4 s, #2
shrn2 v0.8 h, v1.4 s, #2
.endif
str q0, [\dst], #16
.else
uzp1 v0.8 h, v0.8 h, v1.8 h
sqrshrun v0.8 b, v0.8 h, #6
subs \h, \h, #2
fmov x8, d0
lsr x9, x8, #32
str w8, [\dst]
str w9, [\dst, \d_strd]
add \dst, \dst, \d_strd, lsl #1
.endif
b.gt 4 b
.ifc \type, put
.align JUMP_ALIGN
42 :
.endif
ldr s18, [\src]
.ifc \isa, neon_i8mm
movi v0.4 s, #0
movi v1.4 s, #0
.else // neon_dotprod
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
sub v18.16 b, v18.16 b, v5.16 b
.endif
tbl v19.16 b, {v16.16 b, v17.16 b}, v6.16 b
tbl v20.16 b, {v17.16 b, v18.16 b}, v28.16 b
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
.ifc \type, prep
.ifc \isa, neon_i8mm
rshrn v0.4 h, v0.4 s, #2
rshrn2 v0.8 h, v1.4 s, #2
.else
shrn v0.4 h, v0.4 s, #2
shrn2 v0.8 h, v1.4 s, #2
.endif
str q0, [\dst]
.else
uzp1 v0.8 h, v0.8 h, v1.8 h
sqrshrun v0.8 b, v0.8 h, #6
fmov x8, d0
lsr x9, x8, #32
str w8, [\dst]
str w9, [\dst, \d_strd]
.endif
ret
.ifc \type, put
.align JUMP_ALIGN
20 : // V - 2 xN
ldr h16, [\src]
ldr h17, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr h18, [\src]
ldr h19, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr h20, [\src]
ldr h21, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
ldr h22, [\src]
ldr h23, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
subs \h, \h, #2
zip1 v0.8 b, v16.8 b, v17.8 b
zip1 v2.8 b, v18.8 b, v19.8 b
zip1 v18.8 b, v20.8 b, v21.8 b
zip1 v24.8 b, v22.8 b, v23.8 b
zip1 v16.4 h, v0.4 h, v2.4 h
zip1 v17.4 h, v18.4 h, v24.4 h
.ifc \isa, neon_dotprod
sub v16.8 b, v16.8 b, v5.8 b
sub v17.8 b, v17.8 b, v5.8 b
.endif
b.eq 22 f
.align LOOP_ALIGN
2 :
ldr h18, [\src]
ldr h21, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
.ifc \isa, neon_i8mm
movi v0.4 s, #0
movi v1.4 s, #0
.else // put
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
sub v18.8 b, v18.8 b, v5.8 b
sub v21.8 b, v21.8 b, v5.8 b
.endif
tbl v19.16 b, {v16.16 b, v17.16 b}, v6.16 b
tbl v20.16 b, {v17.16 b, v18.16 b}, v28.16 b
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
tbl v16.16 b, {v19.16 b, v20.16 b}, v6.16 b
tbl v17.16 b, {v20.16 b, v21.16 b}, v28.16 b
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
uzp1 v0.8 h, v0.8 h, v1.8 h
sqrshrun v0.8 b, v0.8 h, #6
subs \h, \h, #2
fmov x8, d0
lsr x9, x8, #32
strh w8, [\dst]
strh w9, [\dst, \d_strd]
add \dst, \dst, \d_strd, lsl #1
b.gt 2 b
.align JUMP_ALIGN
22 :
ldr h18, [\src]
.ifc \isa, neon_i8mm
movi v0.4 s, #0
movi v1.4 s, #0
.else // put
mov v0.16 b, v4.16 b
mov v1.16 b, v4.16 b
sub v18.8 b, v18.8 b, v5.8 b
.endif
tbl v19.16 b, {v16.16 b, v17.16 b}, v6.16 b
tbl v20.16 b, {v17.16 b, v18.16 b}, v28.16 b
\dot v0.4 s, v16.16 b, v7.4 b[0 ]
\dot v0.4 s, v17.16 b, v7.4 b[1 ]
\dot v1.4 s, v19.16 b, v7.4 b[0 ]
\dot v1.4 s, v20.16 b, v7.4 b[1 ]
uzp1 v0.8 h, v0.8 h, v1.8 h
sqrshrun v0.8 b, v0.8 h, #6
fmov x8, d0
lsr x9, x8, #32
strh w8, [\dst]
strh w9, [\dst, \d_strd]
ret
.endif
.align JUMP_ALIGN
L(\type\()_8 tap_h_hv_\isa):
madd \mx, \mx, w11, w9
madd w14, \my, w11, w10 // for HV
.ifc \isa, neon_dotprod
mov w13, #0 x2002 // FILTER_WEIGHT * 128 + rounding
dup v27.4 s, w13 // put H overrides this
.endif
movrel x13, h_tbl_neon_dotprod
sub \src, \src, #3 // src - 3
ldr q28, [x13] // for 4 -tap & 8 -tap H filters
ubfx w15, \mx, #7 , #7
and \mx, \mx, #0 x7F
ubfx w11, w14, #7 , #7 // for HV
and w14, w14, #0 x7F // for HV
cmp \w, #4
csel \mx, \mx, w15, le
add \xmx, x12, \xmx, lsl #3 // subpel H filter address
.ifc \isa, neon_dotprod
movi v24.16 b, #128
.endif
cbz \my, L(\type\()_8 tap_h_\isa)
// HV cases
cmp \h, #4
csel w14, w14, w11, le
sub \src, \src, \s_strd, lsl #1 // src - s_strd * 2 - 3
add \xmy, x12, x14, lsl #3 // subpel V filter address
mov x15, x30
ldr d7, [\xmy]
.ifc \type, put
ldr q25, [x13, #(OFFSET_CVT_32_8)] // LUT to help conversion
.endif // of 32 b values to 8 b
sxtl v7.8 h, v7.8 b
cmp w10, #SHARP1
b.ne L(\type\()_6 tap_hv_\isa) // vertical != SHARP1
// HV 8 -tap cases
sub \src, \src, \s_strd // src - s_strd * 3 - 3
cmp \w, #4
b.eq 40 f
.ifc \type, put
b.lt 20 f
.endif
// .align JUMP_ALIGN // fallthrough
80 : // HV8 - 8 xN+
ldp q29, q30, [x13, #16 ]
ldr d26, [\xmx]
.ifc \type, prep
add \wd_strd, \w, \w
.endif
.align LOOP_ALIGN
81 :
mov \lsrc, \src
mov \ldst, \dst
mov w8, \h
.ifc \isa, neon_i8mm
bl L(\type\()_hv_filter8_\isa)
srshr v16.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v17.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v18.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v19.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v20.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v21.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v22.8 h, v22.8 h, #2
.else
bl L(\type\()_hv_filter8_\isa)
sshr v16.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v17.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v18.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v19.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v20.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v21.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v22.8 h, v22.8 h, #2
.endif
.align LOOP_ALIGN
8 :
ldr q23, [\lsrc]
add \lsrc, \lsrc, \s_strd
smull v0.4 s, v16.4 h, v7.h[0 ]
smull2 v1.4 s, v16.8 h, v7.h[0 ]
mov v16.16 b, v17.16 b
.ifc \isa, neon_i8mm
movi v5.4 s, #0
movi v6.4 s, #0
tbl v2.16 b, {v23.16 b}, v28.16 b
tbl v3.16 b, {v23.16 b}, v29.16 b
.else // neon_dotprod
sub v23.16 b, v23.16 b, v24.16 b
mov v5.16 b, v27.16 b
mov v6.16 b, v27.16 b
.endif
smlal v0.4 s, v17.4 h, v7.h[1 ]
smlal2 v1.4 s, v17.8 h, v7.h[1 ]
.ifc \isa, neon_i8mm
tbl v4.16 b, {v23.16 b}, v30.16 b
mov v17.16 b, v18.16 b
.else // neon_dotprod
mov v17.16 b, v18.16 b
tbl v2.16 b, {v23.16 b}, v28.16 b
tbl v3.16 b, {v23.16 b}, v29.16 b
tbl v4.16 b, {v23.16 b}, v30.16 b
.endif
smlal v0.4 s, v18.4 h, v7.h[2 ]
smlal2 v1.4 s, v18.8 h, v7.h[2 ]
mov v18.16 b, v19.16 b
\dot v5.4 s, v2.16 b, v26.4 b[0 ]
\dot v6.4 s, v3.16 b, v26.4 b[0 ]
smlal v0.4 s, v19.4 h, v7.h[3 ]
smlal2 v1.4 s, v19.8 h, v7.h[3 ]
mov v19.16 b, v20.16 b
\dot v5.4 s, v3.16 b, v26.4 b[1 ]
\dot v6.4 s, v4.16 b, v26.4 b[1 ]
smlal v0.4 s, v20.4 h, v7.h[4 ]
smlal2 v1.4 s, v20.8 h, v7.h[4 ]
mov v20.16 b, v21.16 b
smlal v0.4 s, v21.4 h, v7.h[5 ]
smlal2 v1.4 s, v21.8 h, v7.h[5 ]
.ifc \type, prep
uzp1 v23.8 h, v5.8 h, v6.8 h
.endif
mov v21.16 b, v22.16 b
smlal v0.4 s, v22.4 h, v7.h[6 ]
smlal2 v1.4 s, v22.8 h, v7.h[6 ]
.ifc \isa, neon_i8mm
subs w8, w8, #1
.endif
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v22.8 h, v23.8 h, #2
.else
sshr v22.8 h, v23.8 h, #2
.endif
smlal v0.4 s, v22.4 h, v7.h[7 ]
smlal2 v1.4 s, v22.8 h, v7.h[7 ]
rshrn v0.4 h, v0.4 s, #6
rshrn2 v0.8 h, v1.4 s, #6
.else // put
.ifc \isa, neon_i8mm
rshrn v22.4 h, v5.4 s, #2
rshrn2 v22.8 h, v6.4 s, #2
.else
shrn v22.4 h, v5.4 s, #2
shrn2 v22.8 h, v6.4 s, #2
.endif
smlal v0.4 s, v22.4 h, v7.h[7 ]
smlal2 v1.4 s, v22.8 h, v7.h[7 ]
tbl v0.16 b, {v0.16 b, v1.16 b}, v25.16 b
sqrshrun v0.8 b, v0.8 h, #2
.endif
.ifc \isa, neon_dotprod
subs w8, w8, #1
.endif
.ifc \type, prep
st1 {v0.8 h}, [\ldst], \d_strd
b.gt 8 b
add \dst, \dst, #16
.else
st1 {v0.8 b}, [\ldst], \d_strd
b.gt 8 b
add \dst, \dst, #8
.endif
add \src, \src, #8
subs \w, \w, #8
b.gt 81 b
ret x15
.align JUMP_ALIGN
40 : // HV8 - 4 xN
ldur s26, [\xmx, #2 ]
add \src, \src, #2
bl L(\type\()_hv_filter4_\isa)
shrn v16.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v17.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v18.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v19.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v20.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v21.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v22.4 h, v22.4 s, #2
.align LOOP_ALIGN
4 :
ld1 {v4.8 b}, [\src], \s_strd
smull v0.4 s, v16.4 h, v7.h[0 ]
smlal v0.4 s, v17.4 h, v7.h[1 ]
mov v16.16 b, v17.16 b
mov v17.16 b, v18.16 b
.ifc \isa, neon_dotprod
sub v4.16 b, v4.16 b, v24.16 b
.endif
smlal v0.4 s, v18.4 h, v7.h[2 ]
smlal v0.4 s, v19.4 h, v7.h[3 ]
tbl v2.16 b, {v4.16 b}, v28.16 b
.ifc \isa, neon_i8mm
movi v5.4 s, #0
.else
mov v5.16 b, v27.16 b
.endif
mov v18.16 b, v19.16 b
mov v19.16 b, v20.16 b
smlal v0.4 s, v20.4 h, v7.h[4 ]
smlal v0.4 s, v21.4 h, v7.h[5 ]
\dot v5.4 s, v2.16 b, v26.4 b[0 ]
mov v20.16 b, v21.16 b
mov v21.16 b, v22.16 b
smlal v0.4 s, v22.4 h, v7.h[6 ]
.ifc \isa, neon_i8mm
rshrn v22.4 h, v5.4 s, #2
.else
shrn v22.4 h, v5.4 s, #2
.endif
smlal v0.4 s, v22.4 h, v7.h[7 ]
.ifc \type, prep
rshrn v0.4 h, v0.4 s, #6
str d0, [\dst], #8
subs \h, \h, #1
.else
subs \h, \h, #1
tbl v0.8 b, {v0.16 b}, v25.8 b
sqrshrun v0.8 b, v0.8 h, #2
str s0, [\dst]
add \dst, \dst, \d_strd
.endif
b.gt 4 b
ret x15
.ifc \type, put
.align JUMP_ALIGN
20 : // HV8 - 2 xN
ldur s26, [\xmx, #2 ]
add \src, \src, #2
bl L(\type\()_hv_filter4_\isa)
shrn v16.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v17.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v18.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v19.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v20.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v21.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v22.4 h, v22.4 s, #2
.align LOOP_ALIGN
2 :
ld1 {v4.8 b}, [\src], \s_strd
smull v0.4 s, v16.4 h, v7.h[0 ]
smlal v0.4 s, v17.4 h, v7.h[1 ]
mov v16.16 b, v17.16 b
mov v17.16 b, v18.16 b
.ifc \isa, neon_dotprod
sub v4.16 b, v4.16 b, v24.16 b
.endif
smlal v0.4 s, v18.4 h, v7.h[2 ]
smlal v0.4 s, v19.4 h, v7.h[3 ]
tbl v2.16 b, {v4.16 b}, v28.16 b
.ifc \isa, neon_i8mm
movi v5.4 s, #0
.else
mov v5.16 b, v27.16 b
.endif
mov v18.16 b, v19.16 b
mov v19.16 b, v20.16 b
smlal v0.4 s, v20.4 h, v7.h[4 ]
smlal v0.4 s, v21.4 h, v7.h[5 ]
\dot v5.4 s, v2.16 b, v26.4 b[0 ]
mov v20.16 b, v21.16 b
mov v21.16 b, v22.16 b
smlal v0.4 s, v22.4 h, v7.h[6 ]
.ifc \isa, neon_i8mm
rshrn v22.4 h, v5.4 s, #2
.else
shrn v22.4 h, v5.4 s, #2
.endif
smlal v0.4 s, v22.4 h, v7.h[7 ]
subs \h, \h, #1
tbl v0.8 b, {v0.16 b}, v25.8 b
sqrshrun v0.8 b, v0.8 h, #2
str h0, [\dst]
add \dst, \dst, \d_strd
b.gt 2 b
ret x15
.endif
.align JUMP_ALIGN
L(\type\()_6 tap_hv_\isa):
cmp \w, #4
b.eq 40 f
.ifc \type, put
b.lt 20 f
.endif
// .align JUMP_ALIGN // fallthrough
80 : // HV6 - 8 xN+
ldr d26, [\xmx]
.ifc \type, prep
add \wd_strd, \w, \w
.endif
.ifc \isa, neon_i8mm
cmp w9, #SHARP1
b.eq 88 f // horizontal == SHARP1
ldp q29, q30, [x13, #(OFFSET_USMMLA)]
ext v0.8 b, v26.8 b, v26.8 b, #7
ins v26.d[1 ], v0.d[0 ]
.align LOOP_ALIGN
81 :
mov \lsrc, \src
mov \ldst, \dst
mov w8, \h
bl L(\type\()_hv_filter6_neon_i8mm)
srshr v16.8 h, v22.8 h, #2
bl L(\type\()_hv_filter6_neon_i8mm)
srshr v17.8 h, v22.8 h, #2
bl L(\type\()_hv_filter6_neon_i8mm)
srshr v18.8 h, v22.8 h, #2
bl L(\type\()_hv_filter6_neon_i8mm)
srshr v19.8 h, v22.8 h, #2
bl L(\type\()_hv_filter6_neon_i8mm)
srshr v20.8 h, v22.8 h, #2
.align LOOP_ALIGN
8 :
ld1 {v23.16 b}, [\lsrc], \s_strd
smull v0.4 s, v16.4 h, v7.h[1 ]
smull2 v1.4 s, v16.8 h, v7.h[1 ]
mov v16.16 b, v17.16 b
movi v5.4 s, #0
movi v6.4 s, #0
tbl v2.16 b, {v23.16 b}, v29.16 b
tbl v3.16 b, {v23.16 b}, v30.16 b
smlal v0.4 s, v17.4 h, v7.h[2 ]
smlal2 v1.4 s, v17.8 h, v7.h[2 ]
mov v17.16 b, v18.16 b
usmmla v5.4 s, v2.16 b, v26.16 b
usmmla v6.4 s, v3.16 b, v26.16 b
smlal v0.4 s, v18.4 h, v7.h[3 ]
smlal2 v1.4 s, v18.8 h, v7.h[3 ]
mov v18.16 b, v19.16 b
subs w8, w8, #1
smlal v0.4 s, v19.4 h, v7.h[4 ]
smlal2 v1.4 s, v19.8 h, v7.h[4 ]
uzp1 v23.8 h, v5.8 h, v6.8 h
mov v19.16 b, v20.16 b
smlal v0.4 s, v20.4 h, v7.h[5 ]
smlal2 v1.4 s, v20.8 h, v7.h[5 ]
srshr v20.8 h, v23.8 h, #2
smlal v0.4 s, v20.4 h, v7.h[6 ]
smlal2 v1.4 s, v20.8 h, v7.h[6 ]
.ifc \type, prep
rshrn v0.4 h, v0.4 s, #6
rshrn2 v0.8 h, v1.4 s, #6
st1 {v0.8 h}, [\ldst], \d_strd
b.gt 8 b
add \dst, \dst, #16
.else
tbl v0.16 b, {v0.16 b, v1.16 b}, v25.16 b
sqrshrun v0.8 b, v0.8 h, #2
st1 {v0.8 b}, [\ldst], \d_strd
b.gt 8 b
add \dst, \dst, #8
.endif
add \src, \src, #8
subs \w, \w, #8
b.gt 81 b
ret x15
.align JUMP_ALIGN
88 :
.endif // neon_i8mm
ldp q29, q30, [x13, #16 ]
.align LOOP_ALIGN
81 :
mov \lsrc, \src
mov \ldst, \dst
mov w8, \h
.ifc \isa, neon_i8mm
bl L(\type\()_hv_filter8_\isa)
srshr v16.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v17.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v18.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v19.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
srshr v20.8 h, v22.8 h, #2
.else
bl L(\type\()_hv_filter8_\isa)
sshr v16.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v17.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v18.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v19.8 h, v22.8 h, #2
bl L(\type\()_hv_filter8_\isa)
sshr v20.8 h, v22.8 h, #2
.endif
.align LOOP_ALIGN
8 :
ldr q23, [\lsrc]
add \lsrc, \lsrc, \s_strd
smull v0.4 s, v16.4 h, v7.h[1 ]
smull2 v1.4 s, v16.8 h, v7.h[1 ]
.ifc \isa, neon_dotprod
sub v23.16 b, v23.16 b, v24.16 b
.endif
mov v16.16 b, v17.16 b
.ifc \isa, neon_i8mm
movi v5.4 s, #0
movi v6.4 s, #0
.else
mov v5.16 b, v27.16 b
mov v6.16 b, v27.16 b
.endif
tbl v2.16 b, {v23.16 b}, v28.16 b
tbl v3.16 b, {v23.16 b}, v29.16 b
smlal v0.4 s, v17.4 h, v7.h[2 ]
smlal2 v1.4 s, v17.8 h, v7.h[2 ]
tbl v4.16 b, {v23.16 b}, v30.16 b
mov v17.16 b, v18.16 b
\dot v5.4 s, v2.16 b, v26.4 b[0 ]
\dot v6.4 s, v3.16 b, v26.4 b[0 ]
smlal v0.4 s, v18.4 h, v7.h[3 ]
smlal2 v1.4 s, v18.8 h, v7.h[3 ]
mov v18.16 b, v19.16 b
\dot v5.4 s, v3.16 b, v26.4 b[1 ]
\dot v6.4 s, v4.16 b, v26.4 b[1 ]
smlal v0.4 s, v19.4 h, v7.h[4 ]
smlal2 v1.4 s, v19.8 h, v7.h[4 ]
mov v19.16 b, v20.16 b
uzp1 v23.8 h, v5.8 h, v6.8 h
smlal v0.4 s, v20.4 h, v7.h[5 ]
smlal2 v1.4 s, v20.8 h, v7.h[5 ]
.ifc \isa, neon_i8mm
srshr v20.8 h, v23.8 h, #2
.else
sshr v20.8 h, v23.8 h, #2
.endif
subs w8, w8, #1
smlal v0.4 s, v20.4 h, v7.h[6 ]
smlal2 v1.4 s, v20.8 h, v7.h[6 ]
.ifc \type, prep
rshrn v0.4 h, v0.4 s, #6
rshrn2 v0.8 h, v1.4 s, #6
st1 {v0.8 h}, [\ldst], \d_strd
b.gt 8 b
add \dst, \dst, #16
.else
tbl v0.16 b, {v0.16 b, v1.16 b}, v25.16 b
sqrshrun v0.8 b, v0.8 h, #2
st1 {v0.8 b}, [\ldst], \d_strd
b.gt 8 b
add \dst, \dst, #8
.endif
add \src, \src, #8
subs \w, \w, #8
b.gt 81 b
ret x15
.align FUNC_ALIGN
L(\type\()_hv_filter8_\isa):
ld1 {v4.16 b}, [\lsrc], \s_strd
.ifc \isa, neon_i8mm
movi v22.4 s, #0
movi v23.4 s, #0
.else // neon_dotprod
sub v4.16 b, v4.16 b, v24.16 b
mov v22.16 b, v27.16 b
mov v23.16 b, v27.16 b
.endif
tbl v2.16 b, {v4.16 b}, v28.16 b
tbl v3.16 b, {v4.16 b}, v29.16 b
tbl v4.16 b, {v4.16 b}, v30.16 b
\dot v22.4 s, v2.16 b, v26.4 b[0 ]
\dot v23.4 s, v3.16 b, v26.4 b[0 ]
\dot v22.4 s, v3.16 b, v26.4 b[1 ]
\dot v23.4 s, v4.16 b, v26.4 b[1 ]
uzp1 v22.8 h, v22.8 h, v23.8 h
ret
.ifc \isa, neon_i8mm
.align FUNC_ALIGN
L(\type\()_hv_filter6_neon_i8mm):
ld1 {v4.16 b}, [\lsrc], \s_strd
movi v22.4 s, #0
movi v23.4 s, #0
tbl v2.16 b, {v4.16 b}, v29.16 b
tbl v3.16 b, {v4.16 b}, v30.16 b
usmmla v22.4 s, v2.16 b, v26.16 b
usmmla v23.4 s, v3.16 b, v26.16 b
uzp1 v22.8 h, v22.8 h, v23.8 h
ret
.endif
.align FUNC_ALIGN
L(\type\()_hv_filter4_\isa):
ld1 {v4.8 b}, [\src], \s_strd
.ifc \isa, neon_i8mm
movi v22.4 s, #2
.else
mov v22.16 b, v27.16 b
sub v4.16 b, v4.16 b, v24.16 b
.endif
tbl v2.16 b, {v4.16 b}, v28.16 b
\dot v22.4 s, v2.16 b, v26.4 b[0 ]
ret
.align JUMP_ALIGN
40 : // HV6 - 4 xN
ldur s26, [\xmx, #2 ]
add \src, \src, #2
bl L(\type\()_hv_filter4_\isa)
shrn v16.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v17.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v18.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v19.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v20.4 h, v22.4 s, #2
.align LOOP_ALIGN
4 :
ld1 {v4.8 b}, [\src], \s_strd
smull v0.4 s, v16.4 h, v7.h[1 ]
smlal v0.4 s, v17.4 h, v7.h[2 ]
.ifc \isa, neon_dotprod
sub v4.16 b, v4.16 b, v24.16 b
.endif
mov v16.16 b, v17.16 b
mov v17.16 b, v18.16 b
smlal v0.4 s, v18.4 h, v7.h[3 ]
smlal v0.4 s, v19.4 h, v7.h[4 ]
tbl v2.16 b, {v4.16 b}, v28.16 b
.ifc \isa, neon_i8mm
movi v5.4 s, #0
.else
mov v5.16 b, v27.16 b
.endif
mov v18.16 b, v19.16 b
mov v19.16 b, v20.16 b
\dot v5.4 s, v2.16 b, v26.4 b[0 ]
smlal v0.4 s, v20.4 h, v7.h[5 ]
.ifc \isa, neon_i8mm
rshrn v20.4 h, v5.4 s, #2
.else
shrn v20.4 h, v5.4 s, #2
.endif
subs \h, \h, #1
smlal v0.4 s, v20.4 h, v7.h[6 ]
.ifc \type, prep
rshrn v0.4 h, v0.4 s, #6
str d0, [\dst], #8
.else
tbl v0.8 b, {v0.16 b}, v25.8 b
sqrshrun v0.8 b, v0.8 h, #2
str s0, [\dst]
add \dst, \dst, \d_strd
.endif
b.gt 4 b
ret x15
.ifc \type, put
.align JUMP_ALIGN
20 : // HV6 - 2 xN
ldur s26, [\xmx, #2 ]
add \src, \src, #2
bl L(\type\()_hv_filter4_\isa)
shrn v16.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v17.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v18.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v19.4 h, v22.4 s, #2
bl L(\type\()_hv_filter4_\isa)
shrn v20.4 h, v22.4 s, #2
.align LOOP_ALIGN
2 :
ld1 {v4.8 b}, [\src], \s_strd
smull v0.4 s, v16.4 h, v7.h[1 ]
smlal v0.4 s, v17.4 h, v7.h[2 ]
.ifc \isa, neon_dotprod
sub v4.16 b, v4.16 b, v24.16 b
.endif
mov v16.16 b, v17.16 b
mov v17.16 b, v18.16 b
smlal v0.4 s, v18.4 h, v7.h[3 ]
smlal v0.4 s, v19.4 h, v7.h[4 ]
tbl v2.16 b, {v4.16 b}, v28.16 b
.ifc \isa, neon_i8mm
movi v5.4 s, #0
.else
mov v5.16 b, v27.16 b
.endif
mov v18.16 b, v19.16 b
mov v19.16 b, v20.16 b
\dot v5.4 s, v2.16 b, v26.4 b[0 ]
smlal v0.4 s, v20.4 h, v7.h[5 ]
.ifc \isa, neon_i8mm
rshrn v20.4 h, v5.4 s, #2
.else
shrn v20.4 h, v5.4 s, #2
.endif
subs \h, \h, #1
smlal v0.4 s, v20.4 h, v7.h[6 ]
tbl v0.8 b, {v0.16 b}, v25.8 b
sqrshrun v0.8 b, v0.8 h, #2
str h0, [\dst]
add \dst, \dst, \d_strd
b.gt 2 b
ret x15
.endif
.align JUMP_ALIGN
L(\type\()_8 tap_h_\isa):
movrel x11, \type\()_8 tap_h_\isa\()_tbl
ldrsw x8, [x11, x8, lsl #2 ]
.ifc \type, put
.ifc \isa, neon_i8mm
movi v27.4 s, #34 // special rounding
.else
mov w10, #0 x2022 // 64 * 128 + 34 , bias and rounding for SDOT
dup v27.4 s, w10
.endif
.endif
add x11, x11, x8
br x11
.ifc \type, put
.align JUMP_ALIGN
20 : // H - 2 xN
AARCH64_VALID_JUMP_TARGET
add \src, \src, #2
ldur s26, [\xmx, #2 ]
.align LOOP_ALIGN
2 :
ldr d0, [\src]
ldr d1, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
.ifc \isa, neon_dotprod
sub v0.8 b, v0.8 b, v24.8 b
sub v1.8 b, v1.8 b, v24.8 b
.endif
mov v4.16 b, v27.16 b
mov v5.16 b, v27.16 b
tbl v2.16 b, {v0.16 b}, v28.16 b
tbl v3.16 b, {v1.16 b}, v28.16 b
\dot v4.4 s, v2.16 b, v26.4 b[0 ]
\dot v5.4 s, v3.16 b, v26.4 b[0 ]
uzp1 v4.8 h, v4.8 h, v5.8 h
sqshrun v4.8 b, v4.8 h, #6
subs \h, \h, #2
fmov x8, d4
lsr x9, x8, #32
strh w8, [\dst]
strh w9, [\dst, \d_strd]
add \dst, \dst, \d_strd, lsl #1
b.gt 2 b
ret
.endif
.align JUMP_ALIGN
40 : // H - 4 xN
AARCH64_VALID_JUMP_TARGET
add \src, \src, #2
ldur s26, [\xmx, #2 ]
.align LOOP_ALIGN
4 :
ldr d0, [\src]
ldr d1, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
.ifc \type\()_\isa, prep_neon_i8mm
movi v4.4 s, #0
movi v5.4 s, #0
.else
.ifc \isa, neon_dotprod
sub v0.8 b, v0.8 b, v24.8 b
sub v1.8 b, v1.8 b, v24.8 b
.endif
mov v4.16 b, v27.16 b
mov v5.16 b, v27.16 b
.endif
tbl v2.16 b, {v0.16 b}, v28.16 b
tbl v3.16 b, {v1.16 b}, v28.16 b
\dot v4.4 s, v2.16 b, v26.4 b[0 ]
\dot v5.4 s, v3.16 b, v26.4 b[0 ]
.ifc \type, prep
subs \h, \h, #2
.ifc \isa, neon_i8mm
uzp1 v4.8 h, v4.8 h, v5.8 h
srshr v4.8 h, v4.8 h, #2
.else
shrn v4.4 h, v4.4 s, #2
shrn2 v4.8 h, v5.4 s, #2
.endif
str q4, [\dst], #16
.else // put
uzp1 v4.8 h, v4.8 h, v5.8 h
sqshrun v4.8 b, v4.8 h, #6
subs \h, \h, #2
fmov x8, d4
lsr x9, x8, #32
str w8, [\dst]
str w9, [\dst, \d_strd]
add \dst, \dst, \d_strd, lsl #1
.endif
b.gt 4 b
ret
.align JUMP_ALIGN
80 : // H - 8 xN
AARCH64_VALID_JUMP_TARGET
ldr d26, [\xmx]
.ifc \isa, neon_i8mm
cmp w9, #SHARP1
b.eq 88 f // horizontal == SHARP1
ldp q29, q30, [x13, #(OFFSET_USMMLA)]
ext v0.8 b, v26.8 b, v26.8 b, #7
ins v26.d[1 ], v0.d[0 ]
.align LOOP_ALIGN
8 :
ldr q0, [\src]
ldr q16, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
.ifc \type, prep
movi v4.4 s, #0
movi v5.4 s, #0
movi v20.4 s, #0
movi v21.4 s, #0
.else
mov v4.16 b, v27.16 b
mov v5.16 b, v27.16 b
mov v20.16 b, v27.16 b
mov v21.16 b, v27.16 b
.endif
tbl v1.16 b, {v0.16 b}, v29.16 b
tbl v2.16 b, {v0.16 b}, v30.16 b
tbl v17.16 b, {v16.16 b}, v29.16 b
tbl v18.16 b, {v16.16 b}, v30.16 b
usmmla v4.4 s, v1.16 b, v26.16 b
usmmla v5.4 s, v2.16 b, v26.16 b
usmmla v20.4 s, v17.16 b, v26.16 b
usmmla v21.4 s, v18.16 b, v26.16 b
uzp1 v4.8 h, v4.8 h, v5.8 h
uzp1 v20.8 h, v20.8 h, v21.8 h
.ifc \type, prep
srshr v4.8 h, v4.8 h, #2
srshr v20.8 h, v20.8 h, #2
subs \h, \h, #2
stp q4, q20, [\dst], #32
.else // put
sqshrun v4.8 b, v4.8 h, #6
sqshrun v20.8 b, v20.8 h, #6
subs \h, \h, #2
str d4, [\dst]
str d20, [\dst, \d_strd]
add \dst, \dst, \d_strd, lsl #1
.endif
b.gt 8 b
ret
.align JUMP_ALIGN
88 :
.endif // neon_i8mm
ldp q29, q30, [x13, #16 ]
.align LOOP_ALIGN
8 :
ldr q0, [\src]
ldr q16, [\src, \s_strd]
add \src, \src, \s_strd, lsl #1
.ifc \type\()_\isa, prep_neon_i8mm
movi v4.4 s, #0
movi v5.4 s, #0
movi v20.4 s, #0
movi v21.4 s, #0
.else
.ifc \isa, neon_dotprod
sub v0.16 b, v0.16 b, v24.16 b
sub v16.16 b, v16.16 b, v24.16 b
.endif
mov v4.16 b, v27.16 b
mov v5.16 b, v27.16 b
mov v20.16 b, v27.16 b
mov v21.16 b, v27.16 b
.endif
tbl v1.16 b, {v0.16 b}, v28.16 b
tbl v2.16 b, {v0.16 b}, v29.16 b
tbl v3.16 b, {v0.16 b}, v30.16 b
tbl v17.16 b, {v16.16 b}, v28.16 b
tbl v18.16 b, {v16.16 b}, v29.16 b
tbl v19.16 b, {v16.16 b}, v30.16 b
\dot v4.4 s, v1.16 b, v26.4 b[0 ]
\dot v5.4 s, v2.16 b, v26.4 b[0 ]
\dot v20.4 s, v17.16 b, v26.4 b[0 ]
\dot v21.4 s, v18.16 b, v26.4 b[0 ]
\dot v4.4 s, v2.16 b, v26.4 b[1 ]
\dot v5.4 s, v3.16 b, v26.4 b[1 ]
\dot v20.4 s, v18.16 b, v26.4 b[1 ]
\dot v21.4 s, v19.16 b, v26.4 b[1 ]
uzp1 v4.8 h, v4.8 h, v5.8 h
uzp1 v20.8 h, v20.8 h, v21.8 h
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v4.8 h, v4.8 h, #2
srshr v20.8 h, v20.8 h, #2
.else
sshr v4.8 h, v4.8 h, #2
sshr v20.8 h, v20.8 h, #2
.endif
subs \h, \h, #2
stp q4, q20, [\dst], #32
.else // put
sqshrun v4.8 b, v4.8 h, #6
sqshrun v20.8 b, v20.8 h, #6
subs \h, \h, #2
str d4, [\dst]
str d20, [\dst, \d_strd]
add \dst, \dst, \d_strd, lsl #1
.endif
b.gt 8 b
ret
.align JUMP_ALIGN
160 : // H - 16 xN
AARCH64_VALID_JUMP_TARGET
ldr d26, [\xmx]
.ifc \isa, neon_i8mm
cmp w9, #SHARP1
b.eq 168 f // horizontal == SHARP1
ldp q29, q30, [x13, #(OFFSET_USMMLA)]
ext v0.8 b, v26.8 b, v26.8 b, #7
ins v26.d[1 ], v0.d[0 ]
.align LOOP_ALIGN
16 :
ldr q16, [\src]
ldur q17, [\src, #8 ] // avoid 2 register TBL for small cores
add \src, \src, \s_strd
.ifc \type, prep
movi v6.4 s, #0
movi v7.4 s, #0
movi v22.4 s, #0
movi v23.4 s, #0
.else
mov v6.16 b, v27.16 b
mov v7.16 b, v27.16 b
mov v22.16 b, v27.16 b
mov v23.16 b, v27.16 b
.endif
tbl v0.16 b, {v16.16 b}, v29.16 b
tbl v1.16 b, {v16.16 b}, v30.16 b
tbl v2.16 b, {v17.16 b}, v29.16 b
tbl v3.16 b, {v17.16 b}, v30.16 b
usmmla v6.4 s, v0.16 b, v26.16 b
usmmla v7.4 s, v1.16 b, v26.16 b
usmmla v22.4 s, v2.16 b, v26.16 b
usmmla v23.4 s, v3.16 b, v26.16 b
uzp1 v6.8 h, v6.8 h, v7.8 h
uzp1 v22.8 h, v22.8 h, v23.8 h
.ifc \type, prep
srshr v6.8 h, v6.8 h, #2
srshr v22.8 h, v22.8 h, #2
subs \h, \h, #1
stp q6, q22, [\dst], #32
.else // put
sqshrun v6.8 b, v6.8 h, #6
sqshrun2 v6.16 b, v22.8 h, #6
subs \h, \h, #1
st1 {v6.16 b}, [\dst], \d_strd
.endif
b.gt 16 b
ret
.align JUMP_ALIGN
168 :
.endif // neon_i8mm
ldp q29, q30, [x13, #16 ]
.align LOOP_ALIGN
16 :
ldr q16, [\src]
ldur q17, [\src, #12 ] // avoid 2 register TBL for small cores
add \src, \src, \s_strd
.ifc \type\()_\isa, prep_neon_i8mm
movi v6.4 s, #0
movi v7.4 s, #0
movi v22.4 s, #0
movi v23.4 s, #0
.else
.ifc \isa, neon_dotprod
sub v16.16 b, v16.16 b, v24.16 b
sub v17.16 b, v17.16 b, v24.16 b
.endif
mov v6.16 b, v27.16 b
mov v7.16 b, v27.16 b
mov v22.16 b, v27.16 b
mov v23.16 b, v27.16 b
.endif
tbl v0.16 b, {v16.16 b}, v28.16 b
tbl v1.16 b, {v16.16 b}, v29.16 b
tbl v2.16 b, {v16.16 b}, v30.16 b
tbl v3.16 b, {v17.16 b}, v28.16 b
tbl v4.16 b, {v17.16 b}, v29.16 b
\dot v6.4 s, v0.16 b, v26.4 b[0 ]
\dot v7.4 s, v1.16 b, v26.4 b[0 ]
\dot v22.4 s, v2.16 b, v26.4 b[0 ]
\dot v23.4 s, v3.16 b, v26.4 b[0 ]
\dot v6.4 s, v1.16 b, v26.4 b[1 ]
\dot v7.4 s, v2.16 b, v26.4 b[1 ]
\dot v22.4 s, v3.16 b, v26.4 b[1 ]
\dot v23.4 s, v4.16 b, v26.4 b[1 ]
uzp1 v6.8 h, v6.8 h, v7.8 h
uzp1 v22.8 h, v22.8 h, v23.8 h
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v6.8 h, v6.8 h, #2
srshr v22.8 h, v22.8 h, #2
.else
sshr v6.8 h, v6.8 h, #2
sshr v22.8 h, v22.8 h, #2
.endif
subs \h, \h, #1
stp q6, q22, [\dst], #32
.else // put
sqshrun v6.8 b, v6.8 h, #6
sqshrun2 v6.16 b, v22.8 h, #6
subs \h, \h, #1
st1 {v6.16 b}, [\dst], \d_strd
.endif
b.gt 16 b
ret
.align JUMP_ALIGN
320 : // H - 32 xN+
640 :
1280 :
AARCH64_VALID_JUMP_TARGET
ldr d26, [\xmx]
.ifc \type, put
sub \d_strd, \d_strd, \w, uxtw
.endif
sub \s_strd, \s_strd, \w, uxtw
mov w8, \w
.ifc \isa, neon_i8mm
cmp w9, #SHARP1
b.eq 328 f // horizontal == SHARP1
ldp q29, q30, [x13, #(OFFSET_USMMLA)]
ext v0.8 b, v26.8 b, v26.8 b, #7
ins v26.d[1 ], v0.d[0 ]
.align LOOP_ALIGN
32 :
ldr q16, [\src]
ldur q17, [\src, #8 ] // avoid 2 register TBL for small cores
add \src, \src, #16
.ifc \type, prep
movi v6.4 s, #0
movi v7.4 s, #0
movi v22.4 s, #0
movi v23.4 s, #0
.else
mov v6.16 b, v27.16 b
mov v7.16 b, v27.16 b
mov v22.16 b, v27.16 b
mov v23.16 b, v27.16 b
.endif
tbl v0.16 b, {v16.16 b}, v29.16 b
tbl v1.16 b, {v16.16 b}, v30.16 b
tbl v2.16 b, {v17.16 b}, v29.16 b
tbl v3.16 b, {v17.16 b}, v30.16 b
usmmla v6.4 s, v0.16 b, v26.16 b
usmmla v7.4 s, v1.16 b, v26.16 b
usmmla v22.4 s, v2.16 b, v26.16 b
usmmla v23.4 s, v3.16 b, v26.16 b
uzp1 v6.8 h, v6.8 h, v7.8 h
uzp1 v22.8 h, v22.8 h, v23.8 h
.ifc \type, prep
srshr v6.8 h, v6.8 h, #2
srshr v22.8 h, v22.8 h, #2
subs w8, w8, #16
stp q6, q22, [\dst], #32
.else // put
sqshrun v6.8 b, v6.8 h, #6
sqshrun2 v6.16 b, v22.8 h, #6
subs w8, w8, #16
str q6, [\dst], #16
.endif
b.gt 32 b
add \src, \src, \s_strd
.ifc \type, put
add \dst, \dst, \d_strd
.endif
mov w8, \w
subs \h, \h, #1
b.gt 32 b
ret
.align JUMP_ALIGN
328 :
.endif // neon_i8mm
ldp q29, q30, [x13, #16 ]
.align LOOP_ALIGN
32 :
ldr q16, [\src]
ldur q17, [\src, #12 ] // avoid 2 register TBL for small cores
add \src, \src, #16
.ifc \type\()_\isa, prep_neon_i8mm
movi v6.4 s, #0
movi v7.4 s, #0
movi v22.4 s, #0
movi v23.4 s, #0
.else
.ifc \isa, neon_dotprod
sub v16.16 b, v16.16 b, v24.16 b
sub v17.16 b, v17.16 b, v24.16 b
.endif
mov v6.16 b, v27.16 b
mov v7.16 b, v27.16 b
mov v22.16 b, v27.16 b
mov v23.16 b, v27.16 b
.endif
tbl v0.16 b, {v16.16 b}, v28.16 b
tbl v1.16 b, {v16.16 b}, v29.16 b
tbl v2.16 b, {v16.16 b}, v30.16 b
tbl v3.16 b, {v17.16 b}, v28.16 b
tbl v4.16 b, {v17.16 b}, v29.16 b
\dot v6.4 s, v0.16 b, v26.4 b[0 ]
\dot v7.4 s, v1.16 b, v26.4 b[0 ]
\dot v22.4 s, v2.16 b, v26.4 b[0 ]
\dot v23.4 s, v3.16 b, v26.4 b[0 ]
\dot v6.4 s, v1.16 b, v26.4 b[1 ]
\dot v7.4 s, v2.16 b, v26.4 b[1 ]
\dot v22.4 s, v3.16 b, v26.4 b[1 ]
\dot v23.4 s, v4.16 b, v26.4 b[1 ]
uzp1 v6.8 h, v6.8 h, v7.8 h
uzp1 v22.8 h, v22.8 h, v23.8 h
.ifc \type, prep
.ifc \isa, neon_i8mm
srshr v6.8 h, v6.8 h, #2
srshr v22.8 h, v22.8 h, #2
.else
sshr v6.8 h, v6.8 h, #2
sshr v22.8 h, v22.8 h, #2
.endif
subs w8, w8, #16
stp q6, q22, [\dst], #32
.else // put
sqshrun v6.8 b, v6.8 h, #6
sqshrun2 v6.16 b, v22.8 h, #6
subs w8, w8, #16
str q6, [\dst], #16
.endif
b.gt 32 b
add \src, \src, \s_strd
.ifc \type, put
add \dst, \dst, \d_strd
.endif
mov w8, \w
subs \h, \h, #1
b.gt 32 b
ret
endfunc
jumptable \type\()_8 tap_h_\isa\()_tbl
.word 1280 b - \type\()_8 tap_h_\isa\()_tbl
.word 640 b - \type\()_8 tap_h_\isa\()_tbl
.word 320 b - \type\()_8 tap_h_\isa\()_tbl
.word 160 b - \type\()_8 tap_h_\isa\()_tbl
.word 80 b - \type\()_8 tap_h_\isa\()_tbl
.word 40 b - \type\()_8 tap_h_\isa\()_tbl
.ifc \type, put
.word 20 b - \type\()_8 tap_h_\isa\()_tbl
.endif
endjumptable
.endm
// dst(x0), d_strd(x7), src(x1), s_strd(x2), w(w3), h(w4), mx(w5), my(w6)
// xmx(x5), xmy(x6), ldst(x5), lsrc(x6), wd_strd(w7)
filter_8tap_fn prep, sdot, neon_dotprod, x0, x7, x1, x2, w3, w4, w5, w6, x5, x6, x5, x6, w7
// dst(x0) d_strd(x1) src(x2) s_strd(x3) w(w4) h(w5) mx(w6) my(w7)
// xmx(x6), xmy(x7), ldst(x6), lsrc(x7), wd_strd(w1)
filter_8tap_fn put, sdot, neon_dotprod, x0, x1, x2, x3, w4, w5, w6, w7, x6, x7, x6, x7, w1
#if HAVE_I8MM
ENABLE_I8MM
// dst(x0), d_strd(x7), src(x1), s_strd(x2), w(w3), h(w4), mx(w5), my(w6)
// xmx(x5), xmy(x6), ldst(x5), lsrc(x6), wd_strd(w7)
filter_8tap_fn prep, usdot, neon_i8mm, x0, x7, x1, x2, w3, w4, w5, w6, x5, x6, x5, x6, w7
// dst(x0) d_strd(x1) src(x2) s_strd(x3) w(w4) h(w5) mx(w6) my(w7)
// xmx(x6), xmy(x7), ldst(x6), lsrc(x7), wd_strd(w1)
filter_8tap_fn put, usdot, neon_i8mm, x0, x1, x2, x3, w4, w5, w6, w7, x6, x7, x6, x7, w1
DISABLE_I8MM
#endif // HAVE_I8MM
DISABLE_DOTPROD
#endif // HAVE_DOTPROD
Messung V0.5 in Prozent C=95 H=96 G=95
¤ Dauer der Verarbeitung: 0.42 Sekunden
(vorverarbeitet am 2026-06-04)
¤
*© Formatika GbR, Deutschland