364407128e880db9592b9ddcba2b8aae4e0e1b9c
[theora.git] / lib / arm / armenquant.s
1 ;********************************************************************
2 ;*                                                                  *
3 ;* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
4 ;* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5 ;* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 ;* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7 ;*                                                                  *
8 ;* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
9 ;* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
10 ;*                                                                  *
11 ;********************************************************************
12 ;
13 ; function:
14 ;   last mod: $Id: mmxstate.c 17247 2010-05-28 05:35:32Z tterribe $
15 ;
16 ;********************************************************************
17
18         AREA    |.text|, CODE, READONLY
19
20         GET     armopts.s
21
22  [ OC_ARM_ASM_NEON
23         EXPORT  oc_enc_enquant_table_init_neon
24         EXPORT  oc_enc_enquant_table_fixup_neon
25         EXPORT  oc_enc_quantize_neon
26
27 oc_enc_enquant_table_init_neon PROC
28         ; r0 = void               *_enquant
29         ; r1 = const ogg_uint16_t  _dequant[64]
30         STMFD r13!,{r0,r14}
31         ; Initialize the table using the C routine
32         BLX     oc_enc_enquant_table_init_c
33         LDR     r0, [r13],#4
34         MOV     r1, #2
35         ; Now partially de-interleave it, so that the first row is all
36         ;  multipliers, the second row is all shift factors, etc.
37         ; Also, negate the shifts for use by VSHL.
38 oeeti_neon_lp
39         SUBS    r1, r1, #1
40         VLDMIA          r0, {D16-D31}
41         VUZP.16         Q8, Q9
42         VNEG.S16        Q9, Q9
43         VUZP.16         Q10,Q11
44         VNEG.S16        Q11,Q11
45         VUZP.16         Q12,Q13
46         VNEG.S16        Q13,Q13
47         VUZP.16         Q14,Q15
48         VNEG.S16        Q15,Q15
49         VSTMIA          r0!,{D16-D31}
50         BNE     oeeti_neon_lp
51         LDR     PC, [r13],#4
52         ENDP
53
54 oc_enc_enquant_table_fixup_neon PROC
55         ; r0 = void *_enquant[3][3][2]
56         ; r1 = int   _nqis
57         STR     r14, [r13,#-4]!
58 oeetf_neon_lp1
59         SUBS    r1, r1, #1
60         BEQ     oeetf_neon_end1
61         MOV     r14,#3
62 oeetf_neon_lp2
63         LDR     r2, [r0]
64         SUBS    r14,r14,#1
65         LDRH    r3, [r2]
66         LDRH    r12,[r2,#16]
67         LDR     r2, [r0,#8]
68         STRH    r3, [r2]
69         STRH    r12,[r2,#16]
70         LDR     r2, [r0,#4]
71         LDRH    r3, [r2]
72         LDRH    r12,[r2,#16]
73         LDR     r2, [r0,#12]
74         ADD     r0, r0, #24
75         STRH    r3, [r2]
76         STRH    r12,[r2,#16]
77         BNE     oeetf_neon_lp2
78         SUB     r0, r0, #64
79         B       oeetf_neon_lp1
80 oeetf_neon_end1
81         LDR     PC, [r13],#4
82         ENDP
83
84 oc_enc_quantize_neon PROC
85         ; r0 = ogg_int16_t        _qdct[64]
86         ; r1 = const ogg_int16_t  _dct[64]
87         ; r2 = const ogg_int16_t  _dequant[64]
88         ; r3 = const void        *_enquant
89         STMFD   r13!,{r4,r5,r14}
90         ; The loop counter goes in the high half of r14
91         MOV     r14,#0xFFFCFFFF
92 oeq_neon_lp
93         ; Load the next two rows of the data and the quant matrices.
94         VLD1.64         {D16,D17,D18,D19},[r1@128]!
95         VLD1.64         {D20,D21,D22,D23},[r2@128]!
96         ; Add in the signed rounding bias from the quantizers.
97         ; Note that the VHADD relies on the fact that the quantizers are all
98         ;  even (they're in fact multiples of four) in order to round correctly
99         ;  on the entries being negated.
100         VSHR.S16        Q0, Q8, #15
101         VSHR.S16        Q1, Q9, #15
102         VLD1.64         {D24,D25,D26,D27},[r3@128]!
103         VHADD.S16       Q10,Q0, Q10
104         VHADD.S16       Q11,Q1, Q11
105         VLD1.64         {D28,D29,D30,D31},[r3@128]!
106         ADDS    r14,r14,#1<<16
107         VEOR.S16        Q10,Q0, Q10
108         VEOR.S16        Q11,Q1, Q11
109         VADD.S16        Q8, Q8, Q10
110         VADD.S16        Q9, Q9, Q11
111         ; Perform the actual division and save the result.
112         VQDMULH.S16     Q12,Q8, Q12
113         VQDMULH.S16     Q14,Q9, Q14
114         VADD.S16        Q8, Q8, Q8
115         VADD.S16        Q9, Q9, Q9
116         VADD.S16        Q8, Q8, Q12
117         VADD.S16        Q9, Q9, Q14
118         VSHL.S16        Q8, Q13
119         VSHL.S16        Q9, Q15
120         VSUB.S16        Q8, Q8, Q0
121         VSUB.S16        Q9, Q9, Q1
122         VST1.64         {D16,D17,D18,D19},[r0@128]!
123         ; Now pull out a bitfield marking the non-zero coefficients.
124         ; Sadly, NEON has no PMOVMSKB; emulating it requires 7 instructions.
125         VQMOVN.S16      D16,Q8
126         VQMOVN.S16      D17,Q9
127         VCEQ.S8         Q8, #0
128         VNEG.S8         Q8, Q8          ; D16=.......3.......2.......1.......0
129                                         ;     .......7.......6.......5.......4
130                                         ; D17=.......B.......A.......9.......8
131                                         ;     .......F.......E.......D.......C
132         VZIP.8          D16,D17         ; D16=.......9.......1.......8.......0
133                                         ;     .......B.......3.......A.......2
134                                         ; D17=.......D.......5.......C.......4
135                                         ;     .......F.......7.......E.......6
136         VSHL.U8         D17,D17,#4      ; D17=...D.......5.......C.......4....
137                                         ;     ...F.......7.......E.......6....
138         VORR            D16,D16,D17     ; D16=...D...9...5...1...C...8...4...0
139                                         ;     ...F...B...7...3...E...A...6...2
140         ; Shift over the bitfields from previous iterations and
141         ;  finish compacting the bitfield from the last iteration.
142         ORR     r4, r5, LSL #2          ; r4 =.F.D.B.9.7.5.3.1.E.C.A.8.6.4.2.0
143         ORR     r4, r4, LSR #15         ; r4 =.F.D.B.9.7.5.3.1FEDCBA9876543210
144         PKHTB   r14,r14,r12,ASR #16     ; r14=i|A
145         PKHBT   r12,r4, r12,LSL #16     ; r12=B|C
146         VMOV            r4, r5, D16
147         BLT     oeq_neon_lp
148         ; Start with the low half while the NEON register transfers.
149         PKHBT   r0, r14,r12             ; r0 =B|A
150         MVNS    r0, r0
151         CLZNE   r0, r0
152         RSBNE   r0, r0, #31
153         ; Stall 8-10 more cycles waiting for the last transfer.
154         ORR     r4, r5, LSL #2          ; r4 =.F.D.B.9.7.5.3.1.E.C.A.8.6.4.2.0
155         ORR     r4, r4, LSR #15         ; r4 =.F.D.B.9.7.5.3.1FEDCBA9876543210
156         PKHBT   r1, r12,r4, LSL #16     ; r1 = D|C
157         MVNS    r1, r1
158         CLZNE   r1, r1
159         RSBNE   r0, r1, #63
160         LDMFD   r13!,{r4,r5,PC}
161         ENDP
162  ]
163
164         END