[x265] [PATCH] asm_arm: NEON version of dct[16x16]
Min Chen
chenm003 at 163.com
Sat Jun 18 01:44:40 CEST 2016
# HG changeset patch
# User Min Chen <min.chen at multicorewareinc.com>
# Date 1466207075 18000
# Node ID 9475503fb46c1b4118441c62797799c454534e62
# Parent 78ffb67a844e3e76facf18c52790f1bd544754d6
asm_arm: NEON version of dct[16x16]
---
source/common/arm/asm-primitives.cpp | 1 +
source/common/arm/dct-a.S | 522 +++++++++++++++++++++++++++++++++-
source/common/arm/dct8.h | 1 +
3 files changed, 513 insertions(+), 11 deletions(-)
diff -r 78ffb67a844e -r 9475503fb46c source/common/arm/asm-primitives.cpp
--- a/source/common/arm/asm-primitives.cpp Fri Jun 10 15:53:28 2016 +0530
+++ b/source/common/arm/asm-primitives.cpp Fri Jun 17 18:44:35 2016 -0500
@@ -1007,6 +1007,7 @@
p.cu[BLOCK_4x4].dct = PFX(dct_4x4_neon);
p.cu[BLOCK_8x8].dct = PFX(dct_8x8_neon);
+ p.cu[BLOCK_16x16].dct = PFX(dct_16x16_neon);
#if !HIGH_BIT_DEPTH
p.cu[BLOCK_4x4].psy_cost_pp = PFX(psyCost_4x4_neon);
#endif // !HIGH_BIT_DEPTH
diff -r 78ffb67a844e -r 9475503fb46c source/common/arm/dct-a.S
--- a/source/common/arm/dct-a.S Fri Jun 10 15:53:28 2016 +0530
+++ b/source/common/arm/dct-a.S Fri Jun 17 18:44:35 2016 -0500
@@ -120,17 +120,6 @@
bx lr
endfunc
-.align 4
-ctr4:
-.word 83 // d0[0] = 83
-.word 36 // d0[1] = 36
-ctr8:
-.word 75 // d1[0] = 75
-.word 89 // d1[1] = 89
-.word 18 // d2[0] = 18
-.word 50 // d2[1] = 50
-
-
/* uses registers q4 - q7 for temp values */
.macro tr4 r0, r1, r2, r3
vsub.s32 q8, \r0, \r3 // EO0
@@ -398,3 +387,514 @@
bx lr
endfunc
+
+.align 8
+pw_tr16: .hword 90, 87, 80, 70, 57, 43, 25, 9 // q0 = [ 9 25 43 57 70 80 87 90]
+ .hword 83, 36, 75, 89, 18, 50, 00, 00 // q1 = [ x x 50 18 89 75 36 83]
+
+.align 8
+ctr4:
+ .word 83 // d0[0] = 83
+ .word 36 // d0[1] = 36
+ctr8:
+ .word 75 // d1[0] = 75
+ .word 89 // d1[1] = 89
+ .word 18 // d2[0] = 18
+ .word 50 // d2[1] = 50
+ctr16:
+ .word 90, 87 // d0
+ .word 80, 70 // d1
+ .word 57, 43 // d2
+ .word 25, 9 // d3
+
+/* void dct16_c(const int16_t* src, int16_t* dst, intptr_t srcStride) */
+function x265_dct_16x16_neon
+ push {lr}
+
+ // fill 3 of pipeline stall cycles (dependency link on SP)
+ add r2, r2
+ adr r3, pw_tr16
+ mov r12, #16/4
+
+ vpush {q4-q7}
+
+ // TODO: 16x16 transpose buffer (may share with input buffer in future)
+ sub sp, #16*16*2
+
+ vld1.16 {d0-d3}, [r3]
+ mov r3, sp
+ mov lr, #4*16*2
+
+ // DCT-1D
+.loop1:
+ // Row[0-3]
+ vld1.16 {q8-q9}, [r0, :64], r2 // q8 = [07 06 05 04 03 02 01 00], q9 = [0F 0E 0D 0C 0B 0A 09 08]
+ vld1.16 {q10-q11}, [r0, :64], r2 // q10 = [17 16 15 14 13 12 11 10], q11 = [1F 1E 1D 1C 1B 1A 19 18]
+ vld1.16 {q12-q13}, [r0, :64], r2 // q12 = [27 26 25 24 23 22 21 20], q13 = [2F 2E 2D 2C 2B 2A 29 28]
+ vld1.16 {q14-q15}, [r0, :64], r2 // q14 = [37 36 35 34 33 32 31 30], q15 = [3F 3E 3D 3C 3B 3A 39 38]
+
+ // Register map
+ // | 16 17 18 19 |
+ // | 20 21 22 23 |
+ // | 24 25 26 27 |
+ // | 28 29 30 31 |
+
+ // Transpose 16x4
+ vtrn.32 q8, q12 // q8 = [25 24 05 04 21 20 01 00], q12 = [27 26 07 06 23 22 03 02]
+ vtrn.32 q10, q14 // q10 = [35 34 15 14 31 30 11 10], q14 = [37 36 17 16 33 32 13 12]
+ vtrn.32 q9, q13 // q9 = [2D 2C 0D 0C 29 28 09 08], q13 = [2F 2E 0F 0E 2B 2A 0B 0A]
+ vtrn.32 q11, q15 // q11 = [3D 3C 1D 1C 39 38 19 18], q15 = [3F 3E 1F 1E 3B 3A 1B 1A]
+
+ vtrn.16 q8, q10 // q8 = [34 24 14 04 30 20 10 00], q10 = [35 25 15 05 31 21 11 01]
+ vtrn.16 q12, q14 // q12 = [36 26 16 06 32 22 12 02], q14 = [37 27 17 07 33 23 13 03]
+ vtrn.16 q13, q15 // q13 = [3E 2E 1E 0E 3A 2A 1A 0A], q15 = [3F 2F 1F 0F 3B 2B 1B 0B]
+ vtrn.16 q9, q11 // q9 = [3C 2C 1C 0C 38 28 18 08], q11 = [3D 2D 1D 0D 39 29 19 09]
+
+ vswp d26, d27 // q13 = [3A 2A 1A 0A 3E 2E 1E 0E]
+ vswp d30, d31 // q15 = [3B 2B 1B 0B 3F 2F 1F 0F]
+ vswp d18, d19 // q9 = [38 28 18 08 3C 2C 1C 0C]
+ vswp d22, d23 // q11 = [39 29 19 09 3D 2D 1D 0D]
+
+ // E[0-7] - 10 bits
+ vadd.s16 q4, q8, q15 // q4 = [E4 E0]
+ vadd.s16 q5, q10, q13 // q5 = [E5 E1]
+ vadd.s16 q6, q12, q11 // q6 = [E6 E2]
+ vadd.s16 q7, q14, q9 // q7 = [E7 E3]
+
+ // O[0-7] - 10 bits
+ vsub.s16 q8, q8, q15 // q8 = [O4 O0]
+ vsub.s16 q9, q14, q9 // q9 = [O7 O3]
+ vsub.s16 q10, q10, q13 // q10 = [O5 O1]
+ vsub.s16 q11, q12, q11 // q11 = [O6 O2]
+
+ // reorder Ex for EE/EO
+ vswp d9, d14 // q4 = [E3 E0], q7 = [E7 E4]
+ vswp d11, d12 // q5 = [E2 E1], q6 = [E6 E5]
+ vswp d14, d15 // q7 = [E4 E7]
+ vswp d12, d13 // q6 = [E5 E6]
+
+ // EE[0-3] - 11 bits
+ vadd.s16 q2, q4, q7 // q2 = [EE3 EE0]
+ vadd.s16 q3, q5, q6 // q3 = [EE2 EE1]
+
+ // EO[0-3] - 11 bits
+ vsub.s16 q4, q4, q7 // q4 = [EO3 EO0]
+ vsub.s16 q5, q5, q6 // q5 = [EO2 EO1]
+
+ // EEx[0-1] - 12 bits
+ vadd.s16 d12, d4, d5 // q6 = [EEE1 EEE0]
+ vadd.s16 d13, d6, d7
+ vsub.s16 d14, d4, d5 // q7 = [EEO1 EEO0]
+ vsub.s16 d15, d6, d7
+
+ // NEON Register map
+ // Ex -> [q4, q5, q6, q7], Ox -> [q8, q9, q10, q11], Const -> [q0, q1], Free -> [q2, q3, q12, q13, q14, q15]
+
+ // ODD[4,12]
+ vmull.s16 q14, d14, d2[0] // q14 = EEO0 * 83
+ vmull.s16 q15, d14, d2[1] // q15 = EEO0 * 36
+ vmlal.s16 q14, d15, d2[1] // q14+= EEO1 * 36
+ vmlsl.s16 q15, d15, d2[0] // q15+= EEO1 *-83
+
+ vadd.s16 d4, d12, d13 // d4 = (EEE0 + EEE1)
+ vsub.s16 d12, d13 // d12 = (EEE0 - EEE1)
+
+ // Row
+ vmull.s16 q12, d16, d0[0] // q12 = O0 * 90
+ vmull.s16 q13, d8, d2[3] // q13 = EO0 * 89
+ vqrshrn.s32 d14, q14, 3
+ vqrshrn.s32 d15, q15, 3 // q7 = [12 4] -> [12 4]
+ vmull.s16 q14, d16, d0[1] // q14 = O0 * 87
+ vmull.s16 q15, d16, d0[2] // q15 = O0 * 80
+ vshll.s16 q2, d4, #6 // q2 = (EEE0 + EEE1) * 64 -> [ 0]
+ vshll.s16 q6, d12, #6 // q6 = (EEE0 - EEE1) * 64 -> [ 8]
+
+ vmlal.s16 q12, d20, d0[1] // q12+= O1 * 87
+ vmlal.s16 q13, d10, d2[2] // q13+= EO1 * 75
+ vmlal.s16 q14, d20, d1[0] // q14+= O1 * 57
+ vmlal.s16 q15, d20, d1[3] // q15+= O1 * 9
+ vqrshrn.s32 d4, q2, 3 // q2 = [- 0]
+ vqrshrn.s32 d12, q6, 3 // q6 = [- 8]
+
+ vmlal.s16 q12, d22, d0[2] // q12+= O2 * 80
+ vmlal.s16 q13, d11, d3[1] // q13+= EO2 * 50
+ vmlal.s16 q14, d22, d1[3] // q14+= O2 * 9
+ vmlsl.s16 q15, d22, d0[3] // q15+= O2 *-70
+
+ vmlal.s16 q12, d18, d0[3] // q12+= O3 * 70
+ vmlal.s16 q13, d9, d3[0] // q13+= EO3 * 18 -> [ 2]
+ vmlsl.s16 q14, d18, d1[1] // q14+= O3 *-43
+ vmlsl.s16 q15, d18, d0[1] // q15+= O3 *-87
+
+ vmlal.s16 q12, d17, d1[0] // q12+= O4 * 57
+ vmlsl.s16 q14, d17, d0[2] // q14+= O4 *-80
+ vmlsl.s16 q15, d17, d1[2] // q15+= O4 *-25
+ vqrshrn.s32 d6, q13, 3 // q3 = [- 2]
+ vmull.s16 q13, d8, d2[2] // q13 = EO0 * 75
+
+ vmlal.s16 q12, d21, d1[1] // q12+= O5 * 43
+ vmlsl.s16 q13, d10, d3[0] // q13+= EO1 *-18
+ vmlsl.s16 q14, d21, d0[0] // q14+= O5 *-90
+ vmlal.s16 q15, d21, d1[0] // q15+= O5 * 57
+
+ vmlal.s16 q12, d23, d1[2] // q12+= O6 * 25
+ vmlsl.s16 q13, d11, d2[3] // q13+= EO2 *-89
+ vmlsl.s16 q14, d23, d0[3] // q14+= O6 *-70
+ vmlal.s16 q15, d23, d0[0] // q15+= O6 * 90
+
+ vmlal.s16 q12, d19, d1[3] // q12+= O7 * 9 -> [ 1]
+ vmlsl.s16 q13, d9, d3[1] // q13+= EO3 *-50 -> [ 6]
+ vmlsl.s16 q14, d19, d1[2] // q14+= O7 *-25 -> [ 3]
+ vmlal.s16 q15, d19, d1[1] // q15+= O7 * 43 -> [ 5]
+ vqrshrn.s32 d5, q12, 3 // q2 = [1 0]
+
+ vmull.s16 q12, d16, d0[3] // q12 = O0 * 70
+ vqrshrn.s32 d7, q14, 3 // q3 = [3 2]
+ vmull.s16 q14, d16, d1[0] // q14 = O0 * 57
+
+ vmlsl.s16 q12, d20, d1[1] // q12+= O1 *-43
+ vmlsl.s16 q14, d20, d0[2] // q14+= O1 *-80
+
+ vmlsl.s16 q12, d22, d0[1] // q12+= O2 *-87
+ vmlsl.s16 q14, d22, d1[2] // q14+= O2 *-25
+
+ vmlal.s16 q12, d18, d1[3] // q12+= O3 * 9
+ vmlal.s16 q14, d18, d0[0] // q14+= O3 * 90
+
+ // Row[0-3]
+ vst4.16 {d4-d7}, [r3], lr
+
+ vqrshrn.s32 d5, q15, 3 // q2 = [5 -]
+ vqrshrn.s32 d6, q13, 3 // q3 = [- 6]
+ vmull.s16 q13, d8, d3[1] // q13 = EO0 * 50
+ vmlal.s16 q12, d17, d0[0] // q12+= O4 * 90
+ vmlsl.s16 q14, d17, d1[3] // q14+= O4 *-9
+ vmull.s16 q15, d16, d1[1] // q15 = O0 * 43
+
+ vmlsl.s16 q13, d10, d2[3] // q13+= EO1 *-89
+ vmlal.s16 q12, d21, d1[2] // q12+= O5 * 25
+ vmlsl.s16 q14, d21, d0[1] // q14+= O5 *-87
+ vmlsl.s16 q15, d20, d0[0] // q15+= O1 *-90
+
+ vmlal.s16 q13, d11, d3[0] // q13+= EO2 * 18
+ vmlsl.s16 q12, d23, d0[2] // q12+= O6 *-80
+ vmlal.s16 q14, d23, d1[1] // q14+= O6 * 43
+ vmlal.s16 q15, d22, d1[0] // q15+= O2 * 57
+
+ vmlal.s16 q13, d9, d2[2] // q13+= EO3 * 75 -> [10]
+ vmlsl.s16 q12, d19, d1[0] // q12+= O7 *-57 -> [ 7]
+ vmlal.s16 q14, d19, d0[3] // q14+= O7 * 70 -> [ 9]
+ vmlal.s16 q15, d18, d1[2] // q15+= O3 * 25
+ vmlsl.s16 q15, d17, d0[1] // q15+= O4 *-87
+ vmlal.s16 q15, d21, d0[3] // q15+= O5 * 70
+ vmlal.s16 q15, d23, d1[3] // q15+= O6 * 9
+ vmlsl.s16 q15, d19, d0[2] // q15+= O7 *-80 -> [11]
+ vmov d4, d14 // q2 = [5 4]
+ vqrshrn.s32 d14, q13, 3 // q7 = [12 10]
+ vmull.s16 q13, d8, d3[0] // q13 = EO0 * 18
+ vqrshrn.s32 d7, q12, 3 // q3 = [7 6]
+ vmull.s16 q12, d16, d1[2] // q12 = O0 * 25
+ vmlsl.s16 q13, d9, d2[3] // q13 = EO3 *-89
+ vmull.s16 q4, d16, d1[3] // q4 = O0 * 9
+ vmlsl.s16 q12, d20, d0[3] // q12+= O1 *-70
+ vmlsl.s16 q13, d10, d3[1] // q13 = EO1 *-50
+ vmlsl.s16 q4, d20, d1[2] // q4 += O1 *-25
+ vmlal.s16 q12, d22, d0[0] // q12+= O2 * 90
+ vmlal.s16 q13, d11, d2[2] // q13 = EO2 * 75 -> [14]
+ vmlal.s16 q4, d22, d1[1] // q4 += O2 * 43
+ vmlsl.s16 q12, d18, d0[2] // q12+= O3 *-80
+ vmlsl.s16 q4, d18, d1[0] // q4 += O3 *-57
+ vmlal.s16 q12, d17, d1[1] // q12+= O4 * 43
+ vqrshrn.s32 d13, q14, 3 // q6 = [9 8]
+ vmov d28, d15 // q14 = [- 12]
+ vqrshrn.s32 d15, q15, 3 // q7 = [11 10]
+ vqrshrn.s32 d30, q13, 3 // q15 = [- 14]
+ vmlal.s16 q4, d17, d0[3] // q4 += O4 * 70
+ vmlal.s16 q12, d21, d1[3] // q12+= O5 * 9
+ vmlsl.s16 q4, d21, d0[2] // q4 += O5 *-80
+ vmlsl.s16 q12, d23, d1[0] // q12+= O6 *-57
+ vmlal.s16 q4, d23, d0[1] // q4 += O6 * 87
+ vmlal.s16 q12, d19, d0[1] // q12+= O7 * 87 -> [13]
+ vmlsl.s16 q4, d19, d0[0] // q4 += O7 *-90 -> [15]
+
+ // Row[4-7]
+ vst4.16 {d4-d7}, [r3], lr
+ vqrshrn.s32 d29, q12, 3 // q14 = [13 12]
+ vqrshrn.s32 d31, q4, 3 // q15 = [15 14]
+
+ // Row[8-11]
+ vst4.16 {d12-d15}, [r3], lr
+
+ // Row[12-15]
+ vst4.16 {d28-d31}, [r3]!
+
+
+ // loop into next process group
+ sub r3, #3*4*16*2
+ subs r12, #1
+ bgt .loop1
+
+
+ // DCT-2D
+ // r[0,2,3,12,lr], q[2-15] are free here
+ mov r2, sp // r3 -> internal temporary buffer
+ mov r3, #16*2*2
+ mov r12, #16/4 // Process 4 rows every loop
+
+.loop2:
+ vldm r2, {q8-q15}
+
+ // d16 = [30 20 10 00]
+ // d17 = [31 21 11 01]
+ // q18 = [32 22 12 02]
+ // d19 = [33 23 13 03]
+ // d20 = [34 24 14 04]
+ // d21 = [35 25 15 05]
+ // q22 = [36 26 16 06]
+ // d23 = [37 27 17 07]
+ // d24 = [38 28 18 08]
+ // d25 = [39 29 19 09]
+ // q26 = [3A 2A 1A 0A]
+ // d27 = [3B 2B 1B 0B]
+ // d28 = [3C 2C 1C 0C]
+ // d29 = [3D 2D 1D 0D]
+ // q30 = [3E 2E 1E 0E]
+ // d31 = [3F 2F 1F 0F]
+
+ // NOTE: the ARM haven't enough SIMD registers, so I have to process Even & Odd part series.
+
+ // Process Even
+
+ // E
+ vaddl.s16 q2, d16, d31 // q2 = [E30 E20 E10 E00]
+ vaddl.s16 q3, d17, d30 // q3 = [E31 E21 E11 E01]
+ vaddl.s16 q4, d18, d29 // q4 = [E32 E22 E12 E02]
+ vaddl.s16 q5, d19, d28 // q5 = [E33 E23 E13 E03]
+ vaddl.s16 q9, d23, d24 // q9 = [E37 E27 E17 E07]
+ vaddl.s16 q8, d22, d25 // q8 = [E36 E26 E16 E06]
+ vaddl.s16 q7, d21, d26 // q7 = [E35 E25 E15 E05]
+ vaddl.s16 q6, d20, d27 // q6 = [E34 E24 E14 E04]
+
+ // EE & EO
+ vadd.s32 q13, q2, q9 // q13 = [EE30 EE20 EE10 EE00]
+ vsub.s32 q9, q2, q9 // q9 = [EO30 EO20 EO10 EO00]
+
+ vadd.s32 q2, q5, q6 // q2 = [EE33 EE23 EE13 EE03]
+ vsub.s32 q12, q5, q6 // q12 = [EO33 EO23 EO13 EO03]
+
+ vadd.s32 q14, q3, q8 // q14 = [EE31 EE21 EE11 EE01]
+ vsub.s32 q10, q3, q8 // q10 = [EO31 EO21 EO11 EO01]
+
+ vadd.s32 q15, q4, q7 // q15 = [EE32 EE22 EE12 EE02]
+ vsub.s32 q11, q4, q7 // q11 = [EO32 EO22 EO12 EO02]
+
+ // Free=[3,4,5,6,7,8]
+
+ // EEE & EEO
+ vadd.s32 q5, q13, q2 // q5 = [EEE30 EEE20 EEE10 EEE00]
+ vadd.s32 q6, q14, q15 // q6 = [EEE31 EEE21 EEE11 EEE01]
+ vsub.s32 q7, q13, q2 // q7 = [EEO30 EEO20 EEO10 EEO00]
+ vsub.s32 q8, q14, q15 // q8 = [EEO31 EEO21 EEO11 EEO01]
+
+ // Convert Const for Dct EE to 32-bits
+ adr r0, ctr4
+ vld1.32 {d0-d3}, [r0, :64]
+
+ // Register Map (Qx)
+ // Free=[2,3,4,13,14,15], Const=[0,1], EEEx=[5,6,7,8], EO=[9,10,11,12]
+
+ vadd.s32 q15, q5, q6 // q15 = EEE0 + EEE1 -> 0
+ vmul.s32 q2, q9, d1[1] // q2 = EO0 * 89 -> 2
+ vmul.s32 q3, q7, d0[0] // q3 = EEO0 * 83 -> 4
+ vmul.s32 q4, q9, d1[0] // q4 = EO0 * 75 -> 6
+ vmul.s32 q14, q9, d2[1] // q14 = EO0 * 50 -> 10
+
+ vshl.s32 q15, #6 // q15 -> [ 0]'
+ vmla.s32 q2, q10, d1[0] // q2 += EO1 * 75
+ vmla.s32 q3, q8, d0[1] // q3 += EEO1 * 36 -> [ 4]'
+ vmls.s32 q4, q10, d2[0] // q4 += EO1 *-18
+ vmls.s32 q14, q10, d1[1] // q14+= EO1 *-89
+ vmul.s32 q13, q7, d0[1] // q13 = EEO0 * 36 -> 12
+
+ vqrshrn.s32 d30, q15, 10 // d30 -> [ 0]
+ vqrshrn.s32 d31, q3, 10 // d31 -> [ 4]
+ vmls.s32 q4, q11, d1[1] // q4 += EO2 *-89
+ vsub.s32 q3, q5, q6 // q3 = EEE0 - EEE1 -> 8
+ vmla.s32 q2, q11, d2[1] // q2 += EO2 * 50
+ vmla.s32 q14, q11, d2[0] // q14+= EO2 * 18
+ vmls.s32 q13, q8, d0[0] // q13+= EEO1 *-83 -> [12]'
+ vst1.16 {d30}, [r1], r3 // Stroe [ 0]
+
+ vshl.s32 q3, #6 // q3 -> [ 8]'
+ vmls.s32 q4, q12, d2[1] // q4 += EO3 *-50 -> [ 6]'
+ vmla.s32 q2, q12, d2[0] // q2 += EO3 * 18 -> [ 2]'
+ vqrshrn.s32 d26, q13, 10 // d26 -> [12]
+ vmla.s32 q14, q12, d1[0] // q14+= EO3 * 75 -> [10]'
+
+ vqrshrn.s32 d30, q3, 10 // d30 -> [ 8]
+ vmul.s32 q3, q9, d2[0] // q3 = EO0 * 18 -> 14
+ vqrshrn.s32 d4, q2, 10 // d4 -> [ 2]
+ vmls.s32 q3, q10, d2[1] // q3 += EO1 *-50
+ vqrshrn.s32 d5, q4, 10 // d30 -> [ 6]
+ vmla.s32 q3, q11, d1[0] // q3 += EO2 * 75
+ vqrshrn.s32 d27, q14, 10 // d27 -> [10]
+ vmls.s32 q3, q12, d1[1] // q3 += EO3 *-89 -> [14]'
+
+ vst1.16 {d4 }, [r1], r3 // Stroe [ 2]
+ vst1.16 {d31}, [r1], r3 // Stroe [ 4]
+ vst1.16 {d5 }, [r1], r3 // Stroe [ 6]
+ vst1.16 {d30}, [r1], r3 // Stroe [ 8]
+ vqrshrn.s32 d30, q3, 10 // d30 -> [14]
+ vst1.16 {d27}, [r1], r3 // Stroe [10]
+ vst1.16 {d26}, [r1], r3 // Stroe [12]
+ vst1.16 {d30}, [r1], r3 // Stroe [14]
+
+ // Process Odd
+ sub r1, #(15*16)*2
+ vldm r2!, {q8-q15}
+
+ // d8 = [30 20 10 00]
+ // d9 = [31 21 11 01]
+ // q10 = [32 22 12 02]
+ // d11 = [33 23 13 03]
+ // d12 = [34 24 14 04]
+ // d13 = [35 25 15 05]
+ // q14 = [36 26 16 06]
+ // d15 = [37 27 17 07]
+ // d16 = [38 28 18 08]
+ // d17 = [39 29 19 09]
+ // q18 = [3A 2A 1A 0A]
+ // d19 = [3B 2B 1B 0B]
+ // d20 = [3C 2C 1C 0C]
+ // d21 = [3D 2D 1D 0D]
+ // q22 = [3E 2E 1E 0E]
+ // d23 = [3F 2F 1F 0F]
+
+ // O
+ vsubl.s16 q2, d16, d31 // q2 = [O30 O20 O10 O00]
+ vsubl.s16 q3, d17, d30 // q3 = [O31 O21 O11 O01]
+ vsubl.s16 q4, d18, d29 // q4 = [O32 O22 O12 O02]
+ vsubl.s16 q5, d19, d28 // q5 = [O33 O23 O13 O03]
+ vsubl.s16 q9, d23, d24 // q9 = [O37 O27 O17 O07]
+ vsubl.s16 q8, d22, d25 // q8 = [O36 O26 O16 O06]
+ vsubl.s16 q7, d21, d26 // q7 = [O35 O25 O15 O05]
+ vsubl.s16 q6, d20, d27 // q6 = [O34 O24 O14 O04]
+
+ // Load DCT Ox Constant
+ adr r0, ctr16
+ vld1.32 {d0-d3}, [r0]
+
+ // Register Map (Qx)
+ // Free=[10,11,12,13,14,15], Const=[0,1], O=[2,3,4,5,6,7,8,9]
+
+ vmul.s32 q10, q2, d0[0] // q10 = O0 * 90 -> 1
+ vmul.s32 q11, q2, d0[1] // q11 = O0 * 87 -> 3
+ vmul.s32 q12, q2, d1[0] // q12 = O0 * 80 -> 5
+ vmul.s32 q13, q2, d1[1] // q13 = O0 * 70 -> 7
+ vmul.s32 q14, q2, d2[0] // q14 = O0 * 57 -> 9
+ vmul.s32 q15, q2, d2[1] // q15 = O0 * 43 -> 11
+
+ vmla.s32 q10, q3, d0[1] // q10+= O1 * 87
+ vmla.s32 q11, q3, d2[0] // q11+= O1 * 57
+ vmla.s32 q12, q3, d3[1] // q12+= O1 * 9
+ vmls.s32 q13, q3, d2[1] // q13+= O1 *-43
+ vmls.s32 q14, q3, d1[0] // q14+= O1 *-80
+ vmls.s32 q15, q3, d0[0] // q15+= O1 *-90
+
+ vmla.s32 q10, q4, d1[0] // q10+= O2 * 80
+ vmla.s32 q11, q4, d3[1] // q11+= O2 * 9
+ vmls.s32 q12, q4, d1[1] // q12+= O2 *-70
+ vmls.s32 q13, q4, d0[1] // q13+= O2 *-87
+ vmls.s32 q14, q4, d3[0] // q14+= O2 *-25
+ vmla.s32 q15, q4, d2[0] // q15+= O2 * 57
+
+ vmla.s32 q10, q5, d1[1] // q10+= O3 * 70
+ vmls.s32 q11, q5, d2[1] // q11+= O3 *-43
+ vmls.s32 q12, q5, d0[1] // q12+= O3 *-87
+ vmla.s32 q13, q5, d3[1] // q13+= O3 * 9
+ vmla.s32 q14, q5, d0[0] // q14+= O3 * 90
+ vmla.s32 q15, q5, d3[0] // q15+= O3 * 25
+
+ vmla.s32 q10, q6, d2[0] // q10+= O4 * 57
+ vmls.s32 q11, q6, d1[0] // q11+= O4 *-80
+ vmls.s32 q12, q6, d3[0] // q12+= O4 *-25
+ vmla.s32 q13, q6, d0[0] // q13+= O4 * 90
+ vmls.s32 q14, q6, d3[1] // q14+= O4 *-9
+ vmls.s32 q15, q6, d0[1] // q15+= O4 *-87
+
+ vmla.s32 q10, q7, d2[1] // q10+= O5 * 43
+ vmls.s32 q11, q7, d0[0] // q11+= O5 *-90
+ vmla.s32 q12, q7, d2[0] // q12+= O5 * 57
+ vmla.s32 q13, q7, d3[0] // q13+= O5 * 25
+ vmls.s32 q14, q7, d0[1] // q14+= O5 *-87
+ vmla.s32 q15, q7, d1[1] // q15+= O5 * 70
+
+ vmla.s32 q10, q8, d3[0] // q10+= O6 * 25
+ vmls.s32 q11, q8, d1[1] // q11+= O6 *-70
+ vmla.s32 q12, q8, d0[0] // q12+= O6 * 90
+ vmls.s32 q13, q8, d1[0] // q13+= O6 *-80
+ vmla.s32 q14, q8, d2[1] // q14+= O6 * 43
+ vmla.s32 q15, q8, d3[1] // q15+= O6 * 9
+
+ vmla.s32 q10, q9, d3[1] // q10+= O7 * 9 -> [ 1]'
+ vmls.s32 q11, q9, d3[0] // q11+= O7 *-25 -> [ 3]'
+ vmla.s32 q12, q9, d2[1] // q12+= O7 * 43 -> [ 5]'
+ vqrshrn.s32 d20, q10, 10 // d20 -> [ 1]
+ vmls.s32 q13, q9, d2[0] // q13+= O7 *-57 -> [ 7]'
+ vqrshrn.s32 d21, q11, 10 // d21 -> [ 3]
+
+ vmul.s32 q11, q2, d3[0] // q11 = O0 * 25 -> 13
+ vmul.s32 q2, q2, d3[1] // q2 = O0 * 9 -> 15
+
+ vst1.16 {d20}, [r1], r3 // Stroe [ 1]
+ vst1.16 {d21}, [r1], r3 // Stroe [ 3]
+
+ vmls.s32 q11, q3, d1[1] // q11+= O1 *-70
+ vmls.s32 q2, q3, d3[0] // q2 += O1 *-25
+
+ vmla.s32 q14, q9, d1[1] // q14+= O7 * 70 -> [ 9]'
+ vmls.s32 q15, q9, d1[0] // q15+= O7 *-80 -> [11]'
+
+ vqrshrn.s32 d24, q12, 10 // d24 -> [ 5]
+
+ vqrshrn.s32 d25, q13, 10 // d25 -> [ 7]
+ vqrshrn.s32 d28, q14, 10 // d28 -> [ 9]
+ vqrshrn.s32 d29, q15, 10 // d29 -> [11]
+
+ vst1.16 {d24}, [r1], r3 // Stroe [ 5]
+ vst1.16 {d25}, [r1], r3 // Stroe [ 7]
+ vst1.16 {d28}, [r1], r3 // Stroe [ 9]
+ vst1.16 {d29}, [r1], r3 // Stroe [11]
+
+ vmla.s32 q11, q4, d0[0] // q11+= O2 * 90
+ vmla.s32 q2, q4, d2[1] // q2 += O2 * 43
+
+ vmls.s32 q11, q5, d1[0] // q11+= O3 *-80
+ vmls.s32 q2, q5, d2[0] // q2 += O3 *-57
+
+ vmla.s32 q11, q6, d2[1] // q11+= O4 * 43
+ vmla.s32 q2, q6, d1[1] // q2 += O4 * 70
+
+ vmla.s32 q11, q7, d3[1] // q11+= O5 * 9
+ vmls.s32 q2, q7, d1[0] // q2 += O5 *-80
+
+ vmls.s32 q11, q8, d2[0] // q11+= O6 *-57
+ vmla.s32 q2, q8, d0[1] // q2 += O6 * 87
+
+ vmla.s32 q11, q9, d0[1] // q11+= O7 * 87 -> [13]'
+ vmls.s32 q2, q9, d0[0] // q2 += O7 *-90 -> [15]'
+
+ vqrshrn.s32 d6, q11, 10 // d6 -> [13]
+ vqrshrn.s32 d7, q2, 10 // d7 -> [15]
+ vst1.16 {d6}, [r1], r3 // Stroe [13]
+ vst1.16 {d7}, [r1], r3 // Stroe [15]
+
+ sub r1, #(17*16-4)*2
+ subs r12, #1
+ bgt .loop2
+
+ add sp, #16*16*2
+ vpop {q4-q7}
+ pop {pc}
+endfunc
+
diff -r 78ffb67a844e -r 9475503fb46c source/common/arm/dct8.h
--- a/source/common/arm/dct8.h Fri Jun 10 15:53:28 2016 +0530
+++ b/source/common/arm/dct8.h Fri Jun 17 18:44:35 2016 -0500
@@ -27,5 +27,6 @@
void PFX(dct_4x4_neon)(const int16_t* src, int16_t* dst, intptr_t srcStride);
void PFX(dct_8x8_neon)(const int16_t* src, int16_t* dst, intptr_t srcStride);
+void PFX(dct_16x16_neon)(const int16_t* src, int16_t* dst, intptr_t srcStride);
#endif // ifndef X265_DCT8_ARM_H
More information about the x265-devel
mailing list