[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