991624f431d28659d41381a061f9264dc8d47605
[theora.git] / lib / arm / armidct.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-2010                *
9 ;* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
10 ;*                                                                  *
11 ;********************************************************************
12 ; Original implementation:
13 ;  Copyright (C) 2009 Robin Watts for Pinknoise Productions Ltd
14 ; last mod: $Id$
15 ;********************************************************************
16
17         AREA    |.text|, CODE, READONLY
18
19         GET     armopts.s
20
21         EXPORT  oc_idct8x8_1_arm
22         EXPORT  oc_idct8x8_arm
23
24 oc_idct8x8_1_arm
25         ; r0 = ogg_int16_t  *_y
26         ; r1 = ogg_uint16_t  _dc
27         ORR     r1, r1, r1, LSL #16
28         MOV     r2, r1
29         MOV     r3, r1
30         MOV     r12,r1
31         STMIA   r0!,{r1,r2,r3,r12}
32         STMIA   r0!,{r1,r2,r3,r12}
33         STMIA   r0!,{r1,r2,r3,r12}
34         STMIA   r0!,{r1,r2,r3,r12}
35         STMIA   r0!,{r1,r2,r3,r12}
36         STMIA   r0!,{r1,r2,r3,r12}
37         STMIA   r0!,{r1,r2,r3,r12}
38         STMIA   r0!,{r1,r2,r3,r12}
39         MOV     PC, r14
40
41 oc_idct8x8_arm
42         ; r0 = ogg_int16_t *_y
43         ; r1 = ogg_int16_t *_x
44         ; r2 = int          _last_zzi
45         CMP     r2, #3
46         BLE     oc_idct8x8_3_arm
47         CMP     r2, #6
48         BLE     oc_idct8x8_6_arm
49         CMP     r2, #10
50         BLE     oc_idct8x8_10_arm
51 oc_idct8x8_slow_arm
52         STMFD   r13!,{r4-r11,r14}
53         SUB     r13,r13,#64*2
54 ; Row transforms
55         STR     r0, [r13,#-4]!
56         ADD     r0, r13, #4     ; Write to temp storage.
57         BL      idct8core_arm
58         BL      idct8core_arm
59         BL      idct8core_arm
60         BL      idct8core_arm
61         BL      idct8core_arm
62         BL      idct8core_arm
63         BL      idct8core_arm
64         BL      idct8core_arm
65         LDR     r0, [r13], #4   ; Write to the final destination.
66         ; Clear input data for next block (decoder only).
67         SUB     r2, r1, #8*16
68         CMP     r0, r2
69         MOV     r1, r13         ; And read from temp storage.
70         BEQ     oc_idct8x8_slow_arm_cols
71         MOV     r4, #0
72         MOV     r5, #0
73         MOV     r6, #0
74         MOV     r7, #0
75         STMIA   r2!,{r4,r5,r6,r7}
76         STMIA   r2!,{r4,r5,r6,r7}
77         STMIA   r2!,{r4,r5,r6,r7}
78         STMIA   r2!,{r4,r5,r6,r7}
79         STMIA   r2!,{r4,r5,r6,r7}
80         STMIA   r2!,{r4,r5,r6,r7}
81         STMIA   r2!,{r4,r5,r6,r7}
82         STMIA   r2!,{r4,r5,r6,r7}
83 oc_idct8x8_slow_arm_cols
84 ; Column transforms
85         BL      idct8core_down_arm
86         BL      idct8core_down_arm
87         BL      idct8core_down_arm
88         BL      idct8core_down_arm
89         BL      idct8core_down_arm
90         BL      idct8core_down_arm
91         BL      idct8core_down_arm
92         BL      idct8core_down_arm
93         ADD     r13,r13,#64*2
94         LDMFD   r13!,{r4-r11,PC}
95
96 oc_idct8x8_10_arm
97         STMFD   r13!,{r4-r11,r14}
98         SUB     r13,r13,#64*2
99 ; Row transforms
100         MOV     r2, r0
101         MOV     r0, r13         ; Write to temp storage.
102         BL      idct4core_arm
103         BL      idct3core_arm
104         BL      idct2core_arm
105         BL      idct1core_arm
106         ; Clear input data for next block (decoder only).
107         SUB     r0, r1, #4*16
108         CMP     r0, r2
109         MOV     r1, r13         ; Read from temp storage.
110         BEQ     oc_idct8x8_10_arm_cols
111         MOV     r4, #0
112         STR     r4, [r0]
113         STR     r4, [r0,#4]
114         STR     r4, [r0,#16]
115         STR     r4, [r0,#20]
116         STR     r4, [r0,#32]
117         STR     r4, [r0,#48]
118         MOV     r0, r2          ; Write to the final destination
119 oc_idct8x8_10_arm_cols
120 ; Column transforms
121         BL      idct4core_down_arm
122         BL      idct4core_down_arm
123         BL      idct4core_down_arm
124         BL      idct4core_down_arm
125         BL      idct4core_down_arm
126         BL      idct4core_down_arm
127         BL      idct4core_down_arm
128         BL      idct4core_down_arm
129         ADD     r13,r13,#64*2
130         LDMFD   r13!,{r4-r11,PC}
131
132 oc_idct8x8_6_arm
133         STMFD   r13!,{r4-r7,r9-r11,r14}
134         SUB     r13,r13,#64*2
135 ; Row transforms
136         MOV     r2, r0
137         MOV     r0, r13         ; Write to temp storage.
138         BL      idct3core_arm
139         BL      idct2core_arm
140         BL      idct1core_arm
141         ; Clear input data for next block (decoder only).
142         SUB     r0, r1, #3*16
143         CMP     r0, r2
144         MOV     r1, r13         ; Read from temp storage.
145         BEQ     oc_idct8x8_6_arm_cols
146         MOV     r4, #0
147         STR     r4, [r0]
148         STR     r4, [r0,#4]
149         STR     r4, [r0,#16]
150         STR     r4, [r0,#32]
151         MOV     r0, r2          ; Write to the final destination
152 oc_idct8x8_6_arm_cols
153 ; Column transforms
154         BL      idct3core_down_arm
155         BL      idct3core_down_arm
156         BL      idct3core_down_arm
157         BL      idct3core_down_arm
158         BL      idct3core_down_arm
159         BL      idct3core_down_arm
160         BL      idct3core_down_arm
161         BL      idct3core_down_arm
162         ADD     r13,r13,#64*2
163         LDMFD   r13!,{r4-r7,r9-r11,PC}
164
165 oc_idct8x8_3_arm
166         STMFD   r13!,{r4-r7,r9-r11,r14}
167         SUB     r13,r13,#64*2
168 ; Row transforms
169         MOV     r2, r0
170         MOV     r0, r13         ; Write to temp storage.
171         BL      idct2core_arm
172         BL      idct1core_arm
173         ; Clear input data for next block (decoder only).
174         SUB     r0, r1, #2*16
175         CMP     r0, r2
176         MOV     r1, r13         ; Read from temp storage.
177         MOVNE   r4, #0
178         STRNE   r4, [r0]
179         STRNE   r4, [r0,#16]
180         MOVNE   r0, r2          ; Write to the final destination
181 ; Column transforms
182         BL      idct2core_down_arm
183         BL      idct2core_down_arm
184         BL      idct2core_down_arm
185         BL      idct2core_down_arm
186         BL      idct2core_down_arm
187         BL      idct2core_down_arm
188         BL      idct2core_down_arm
189         BL      idct2core_down_arm
190         ADD     r13,r13,#64*2
191         LDMFD   r13!,{r4-r7,r9-r11,PC}
192
193 idct1core_arm
194         ; r0 =       ogg_int16_t *_y (destination)
195         ; r1 = const ogg_int16_t *_x (source)
196         LDRSH   r3, [r1], #16
197         MOV     r12,#0x05
198         ORR     r12,r12,#0xB500
199         MUL     r3, r12, r3
200         ; Stall ?
201         MOV     r3, r3, ASR #16
202         STRH    r3, [r0], #2
203         STRH    r3, [r0, #14]
204         STRH    r3, [r0, #30]
205         STRH    r3, [r0, #46]
206         STRH    r3, [r0, #62]
207         STRH    r3, [r0, #78]
208         STRH    r3, [r0, #94]
209         STRH    r3, [r0, #110]
210         MOV     PC,R14
211
212 idct2core_arm
213         ; r0 =       ogg_int16_t *_y (destination)
214         ; r1 = const ogg_int16_t *_x (source)
215         LDRSH   r9, [r1], #16           ; r9 = x[0]
216         LDR     r12,OC_C4S4
217         LDRSH   r11,[r1, #-14]          ; r11= x[1]
218         LDR     r3, OC_C7S1
219         MUL     r9, r12,r9              ; r9 = t[0]<<16 = OC_C4S4*x[0]
220         LDR     r10,OC_C1S7
221         MUL     r3, r11,r3              ; r3 = t[4]<<16 = OC_C7S1*x[1]
222         MOV     r9, r9, ASR #16         ; r9 = t[0]
223         MUL     r11,r10,r11             ; r11= t[7]<<16 = OC_C1S7*x[1]
224         MOV     r3, r3, ASR #16         ; r3 = t[4]
225         MUL     r10,r12,r3              ; r10= t[5]<<16 = OC_C4S4*t[4]
226         MOV     r11,r11,ASR #16         ; r11= t[7]
227         MUL     r12,r11,r12             ; r12= t[6]<<16 = OC_C4S4*t[7]
228         MOV     r10,r10,ASR #16         ; r10= t[5]
229         ADD     r12,r9,r12,ASR #16      ; r12= t[0]+t[6]
230         ADD     r12,r12,r10             ; r12= t[0]+t2[6] = t[0]+t[6]+t[5]
231         SUB     r10,r12,r10,LSL #1      ; r10= t[0]+t2[5] = t[0]+t[6]-t[5]
232         ADD     r3, r3, r9              ; r3 = t[0]+t[4]
233         ADD     r11,r11,r9              ; r11= t[0]+t[7]
234         STRH    r11,[r0], #2            ; y[0] = t[0]+t[7]
235         STRH    r12,[r0, #14]           ; y[1] = t[0]+t[6]
236         STRH    r10,[r0, #30]           ; y[2] = t[0]+t[5]
237         STRH    r3, [r0, #46]           ; y[3] = t[0]+t[4]
238         RSB     r3, r3, r9, LSL #1      ; r3 = t[0]*2-(t[0]+t[4])=t[0]-t[4]
239         RSB     r10,r10,r9, LSL #1      ; r10= t[0]*2-(t[0]+t[5])=t[0]-t[5]
240         RSB     r12,r12,r9, LSL #1      ; r12= t[0]*2-(t[0]+t[6])=t[0]-t[6]
241         RSB     r11,r11,r9, LSL #1      ; r1 = t[0]*2-(t[0]+t[7])=t[0]-t[7]
242         STRH    r3, [r0, #62]           ; y[4] = t[0]-t[4]
243         STRH    r10,[r0, #78]           ; y[5] = t[0]-t[5]
244         STRH    r12,[r0, #94]           ; y[6] = t[0]-t[6]
245         STRH    r11,[r0, #110]          ; y[7] = t[0]-t[7]
246         MOV     PC,r14
247
248 idct2core_down_arm
249         ; r0 =       ogg_int16_t *_y (destination)
250         ; r1 = const ogg_int16_t *_x (source)
251         LDRSH   r9, [r1], #16           ; r9 = x[0]
252         LDR     r12,OC_C4S4
253         LDRSH   r11,[r1, #-14]          ; r11= x[1]
254         LDR     r3, OC_C7S1
255         MUL     r9, r12,r9              ; r9 = t[0]<<16 = OC_C4S4*x[0]
256         LDR     r10,OC_C1S7
257         MUL     r3, r11,r3              ; r3 = t[4]<<16 = OC_C7S1*x[1]
258         MOV     r9, r9, ASR #16         ; r9 = t[0]
259         MUL     r11,r10,r11             ; r11= t[7]<<16 = OC_C1S7*x[1]
260         ADD     r9, r9, #8              ; r9 = t[0]+8
261         MOV     r3, r3, ASR #16         ; r3 = t[4]
262         MUL     r10,r12,r3              ; r10= t[5]<<16 = OC_C4S4*t[4]
263         MOV     r11,r11,ASR #16         ; r11= t[7]
264         MUL     r12,r11,r12             ; r12= t[6]<<16 = OC_C4S4*t[7]
265         MOV     r10,r10,ASR #16         ; r10= t[5]
266         ADD     r12,r9,r12,ASR #16      ; r12= t[0]+t[6]+8
267         ADD     r12,r12,r10             ; r12= t[0]+t2[6] = t[0]+t[6]+t[5]+8
268         SUB     r10,r12,r10,LSL #1      ; r10= t[0]+t2[5] = t[0]+t[6]-t[5]+8
269         ADD     r3, r3, r9              ; r3 = t[0]+t[4]+8
270         ADD     r11,r11,r9              ; r11= t[0]+t[7]+8
271         ; TODO: This is wrong.
272         ; The C code truncates to 16 bits by storing to RAM and doing the
273         ;  shifts later; we've got an extra 4 bits here.
274         MOV     r4, r11,ASR #4
275         MOV     r5, r12,ASR #4
276         MOV     r6, r10,ASR #4
277         MOV     r7, r3, ASR #4
278         RSB     r3, r3, r9, LSL #1      ;r3 =t[0]*2+8-(t[0]+t[4])=t[0]-t[4]+8
279         RSB     r10,r10,r9, LSL #1      ;r10=t[0]*2+8-(t[0]+t[5])=t[0]-t[5]+8
280         RSB     r12,r12,r9, LSL #1      ;r12=t[0]*2+8-(t[0]+t[6])=t[0]-t[6]+8
281         RSB     r11,r11,r9, LSL #1      ;r11=t[0]*2+8-(t[0]+t[7])=t[0]-t[7]+8
282         MOV     r3, r3, ASR #4
283         MOV     r10,r10,ASR #4
284         MOV     r12,r12,ASR #4
285         MOV     r11,r11,ASR #4
286         STRH    r4, [r0], #2            ; y[0] = t[0]+t[7]
287         STRH    r5, [r0, #14]           ; y[1] = t[0]+t[6]
288         STRH    r6, [r0, #30]           ; y[2] = t[0]+t[5]
289         STRH    r7, [r0, #46]           ; y[3] = t[0]+t[4]
290         STRH    r3, [r0, #62]           ; y[4] = t[0]-t[4]
291         STRH    r10,[r0, #78]           ; y[5] = t[0]-t[5]
292         STRH    r12,[r0, #94]           ; y[6] = t[0]-t[6]
293         STRH    r11,[r0, #110]          ; y[7] = t[0]-t[7]
294         MOV     PC,r14
295
296 idct3core_arm
297         LDRSH   r9, [r1], #16           ; r9 = x[0]
298         LDR     r12,OC_C4S4             ; r12= OC_C4S4
299         LDRSH   r3, [r1, #-12]          ; r3 = x[2]
300         LDR     r10,OC_C6S2             ; r10= OC_C6S2
301         MUL     r9, r12,r9              ; r9 = t[0]<<16 = OC_C4S4*x[0]
302         LDR     r4, OC_C2S6             ; r4 = OC_C2S6
303         MUL     r10,r3, r10             ; r10= t[2]<<16 = OC_C6S2*x[2]
304         LDRSH   r11,[r1, #-14]          ; r11= x[1]
305         MUL     r3, r4, r3              ; r3 = t[3]<<16 = OC_C2S6*x[2]
306         LDR     r4, OC_C7S1             ; r4 = OC_C7S1
307         LDR     r5, OC_C1S7             ; r5 = OC_C1S7
308         MOV     r9, r9, ASR #16         ; r9 = t[0]
309         MUL     r4, r11,r4              ; r4 = t[4]<<16 = OC_C7S1*x[1]
310         ADD     r3, r9, r3, ASR #16     ; r3 = t[0]+t[3]
311         MUL     r11,r5, r11             ; r11= t[7]<<16 = OC_C1S7*x[1]
312         MOV     r4, r4, ASR #16         ; r4 = t[4]
313         MUL     r5, r12,r4              ; r5 = t[5]<<16 = OC_C4S4*t[4]
314         MOV     r11,r11,ASR #16         ; r11= t[7]
315         MUL     r12,r11,r12             ; r12= t[6]<<16 = OC_C4S4*t[7]
316         ADD     r10,r9, r10,ASR #16     ; r10= t[1] = t[0]+t[2]
317         RSB     r6, r10,r9, LSL #1      ; r6 = t[2] = t[0]-t[2]
318                                         ; r3 = t2[0] = t[0]+t[3]
319         RSB     r9, r3, r9, LSL #1      ; r9 = t2[3] = t[0]-t[3]
320         MOV     r12,r12,ASR #16         ; r12= t[6]
321         ADD     r5, r12,r5, ASR #16     ; r5 = t2[6] = t[6]+t[5]
322         RSB     r12,r5, r12,LSL #1      ; r12= t2[5] = t[6]-t[5]
323         ADD     r11,r3, r11             ; r11= t2[0]+t[7]
324         ADD     r5, r10,r5              ; r5 = t[1]+t2[6]
325         ADD     r12,r6, r12             ; r12= t[2]+t2[5]
326         ADD     r4, r9, r4              ; r4 = t2[3]+t[4]
327         STRH    r11,[r0], #2            ; y[0] = t[0]+t[7]
328         STRH    r5, [r0, #14]           ; y[1] = t[1]+t2[6]
329         STRH    r12,[r0, #30]           ; y[2] = t[2]+t2[5]
330         STRH    r4, [r0, #46]           ; y[3] = t2[3]+t[4]
331         RSB     r11,r11,r3, LSL #1      ; r11= t2[0] - t[7]
332         RSB     r5, r5, r10,LSL #1      ; r5 = t[1]  - t2[6]
333         RSB     r12,r12,r6, LSL #1      ; r6 = t[2]  - t2[5]
334         RSB     r4, r4, r9, LSL #1      ; r4 = t2[3] - t[4]
335         STRH    r4, [r0, #62]           ; y[4] = t2[3]-t[4]
336         STRH    r12,[r0, #78]           ; y[5] = t[2]-t2[5]
337         STRH    r5, [r0, #94]           ; y[6] = t[1]-t2[6]
338         STRH    r11,[r0, #110]          ; y[7] = t2[0]-t[7]
339         MOV     PC,R14
340
341 idct3core_down_arm
342         LDRSH   r9, [r1], #16           ; r9 = x[0]
343         LDR     r12,OC_C4S4             ; r12= OC_C4S4
344         LDRSH   r3, [r1, #-12]          ; r3 = x[2]
345         LDR     r10,OC_C6S2             ; r10= OC_C6S2
346         MUL     r9, r12,r9              ; r9 = t[0]<<16 = OC_C4S4*x[0]
347         LDR     r4, OC_C2S6             ; r4 = OC_C2S6
348         MUL     r10,r3, r10             ; r10= t[2]<<16 = OC_C6S2*x[2]
349         LDRSH   r11,[r1, #-14]          ; r11= x[1]
350         MUL     r3, r4, r3              ; r3 = t[3]<<16 = OC_C2S6*x[2]
351         LDR     r4, OC_C7S1             ; r4 = OC_C7S1
352         LDR     r5, OC_C1S7             ; r5 = OC_C1S7
353         MOV     r9, r9, ASR #16         ; r9 = t[0]
354         MUL     r4, r11,r4              ; r4 = t[4]<<16 = OC_C7S1*x[1]
355         ADD     r9, r9, #8              ; r9 = t[0]+8
356         MUL     r11,r5, r11             ; r11= t[7]<<16 = OC_C1S7*x[1]
357         ADD     r3, r9, r3, ASR #16     ; r3 = t[0]+t[3]+8
358         MOV     r4, r4, ASR #16         ; r4 = t[4]
359         MUL     r5, r12,r4              ; r5 = t[5]<<16 = OC_C4S4*t[4]
360         MOV     r11,r11,ASR #16         ; r11= t[7]
361         MUL     r12,r11,r12             ; r12= t[6]<<16 = OC_C4S4*t[7]
362         ADD     r10,r9, r10,ASR #16     ; r10= t[1]+8 = t[0]+t[2]+8
363         RSB     r6, r10,r9, LSL #1      ; r6 = t[2]+8 = t[0]-t[2]+8
364                                         ; r3 = t2[0]+8 = t[0]+t[3]+8
365         RSB     r9, r3, r9, LSL #1      ; r9 = t2[3]+8 = t[0]-t[3]+8
366         MOV     r12,r12,ASR #16         ; r12= t[6]
367         ADD     r5, r12,r5, ASR #16     ; r5 = t2[6] = t[6]+t[5]
368         RSB     r12,r5, r12,LSL #1      ; r12= t2[5] = t[6]-t[5]
369         ADD     r11,r3, r11             ; r11= t2[0]+t[7] +8
370         ADD     r5, r10,r5              ; r5 = t[1] +t2[6]+8
371         ADD     r12,r6, r12             ; r12= t[2] +t2[5]+8
372         ADD     r4, r9, r4              ; r4 = t2[3]+t[4] +8
373         RSB     r3, r11,r3, LSL #1      ; r11= t2[0] - t[7]  + 8
374         RSB     r10,r5, r10,LSL #1      ; r5 = t[1]  - t2[6] + 8
375         RSB     r6, r12,r6, LSL #1      ; r6 = t[2]  - t2[5] + 8
376         RSB     r9, r4, r9, LSL #1      ; r4 = t2[3] - t[4]  + 8
377         ; TODO: This is wrong.
378         ; The C code truncates to 16 bits by storing to RAM and doing the
379         ;  shifts later; we've got an extra 4 bits here.
380         MOV     r11,r11,ASR #4
381         MOV     r5, r5, ASR #4
382         MOV     r12,r12,ASR #4
383         MOV     r4, r4, ASR #4
384         MOV     r9, r9, ASR #4
385         MOV     r6, r6, ASR #4
386         MOV     r10,r10,ASR #4
387         MOV     r3, r3, ASR #4
388         STRH    r11,[r0], #2            ; y[0] = t[0]+t[7]
389         STRH    r5, [r0, #14]           ; y[1] = t[1]+t2[6]
390         STRH    r12,[r0, #30]           ; y[2] = t[2]+t2[5]
391         STRH    r4, [r0, #46]           ; y[3] = t2[3]+t[4]
392         STRH    r9, [r0, #62]           ; y[4] = t2[3]-t[4]
393         STRH    r6, [r0, #78]           ; y[5] = t[2]-t2[5]
394         STRH    r10,[r0, #94]           ; y[6] = t[1]-t2[6]
395         STRH    r3, [r0, #110]          ; y[7] = t2[0]-t[7]
396         MOV     PC,R14
397
398 idct4core_arm
399         ; r0 =       ogg_int16_t *_y (destination)
400         ; r1 = const ogg_int16_t *_x (source)
401         LDRSH   r9, [r1], #16           ; r9 = x[0]
402         LDR     r10,OC_C4S4             ; r10= OC_C4S4
403         LDRSH   r12,[r1, #-12]          ; r12= x[2]
404         LDR     r4, OC_C6S2             ; r4 = OC_C6S2
405         MUL     r9, r10,r9              ; r9 = t[0]<<16 = OC_C4S4*x[0]
406         LDR     r5, OC_C2S6             ; r5 = OC_C2S6
407         MUL     r4, r12,r4              ; r4 = t[2]<<16 = OC_C6S2*x[2]
408         LDRSH   r3, [r1, #-14]          ; r3 = x[1]
409         MUL     r5, r12,r5              ; r5 = t[3]<<16 = OC_C2S6*x[2]
410         LDR     r6, OC_C7S1             ; r6 = OC_C7S1
411         LDR     r12,OC_C1S7             ; r12= OC_C1S7
412         LDRSH   r11,[r1, #-10]          ; r11= x[3]
413         MUL     r6, r3, r6              ; r6 = t[4]<<16 = OC_C7S1*x[1]
414         LDR     r7, OC_C5S3             ; r7 = OC_C5S3
415         MUL     r3, r12,r3              ; r3 = t[7]<<16 = OC_C1S7*x[1]
416         LDR     r8, OC_C3S5             ; r8 = OC_C3S5
417         MUL     r7, r11,r7              ; r7 = -t[5]<<16 = OC_C5S3*x[3]
418         MOV     r9, r9, ASR #16         ; r9 = t[0]
419         MUL     r11,r8, r11             ; r11= t[6]<<16 = OC_C3S5*x[3]
420         MOV     r6, r6, ASR #16         ; r6 = t[4]
421 ; TODO: This is wrong; t[4]-t[5] and t[7]-t[6] need to be truncated to 16-bit
422 ; before multiplying, not after (this is not equivalent)
423         SUB     r7, r6, r7, ASR #16     ; r7 = t2[4]=t[4]+t[5] (as r7=-t[5])
424         RSB     r6, r7, r6, LSL #1      ; r6 = t[4]-t[5]
425         MUL     r6, r10,r6              ; r6 = t2[5]<<16 =OC_C4S4*(t[4]-t[5])
426         MOV     r3, r3, ASR #16         ; r3 = t[7]
427         ADD     r11,r3, r11,ASR #16     ; r11= t2[7]=t[7]+t[6]
428         RSB     r3, r11,r3, LSL #1      ; r3 = t[7]-t[6]
429         MUL     r3, r10,r3              ; r3 = t2[6]<<16 =OC_C4S4*(t[7]-t[6])
430         ADD     r4, r9, r4, ASR #16     ; r4 = t[1] = t[0] + t[2]
431         RSB     r10,r4, r9, LSL #1      ; r10= t[2] = t[0] - t[2]
432         ADD     r5, r9, r5, ASR #16     ; r5 = t[0] = t[0] + t[3]
433         RSB     r9, r5, r9, LSL #1      ; r9 = t[3] = t[0] - t[3]
434         MOV     r3, r3, ASR #16         ; r3 = t2[6]
435         ADD     r6, r3, r6, ASR #16     ; r6 = t3[6] = t2[6]+t2[5]
436         RSB     r3, r6, r3, LSL #1      ; r3 = t3[5] = t2[6]-t2[5]
437         ADD     r11,r5, r11             ; r11= t[0]+t2[7]
438         ADD     r6, r4, r6              ; r6 = t[1]+t3[6]
439         ADD     r3, r10,r3              ; r3 = t[2]+t3[5]
440         ADD     r7, r9, r7              ; r7 = t[3]+t2[4]
441         STRH    r11,[r0], #2            ; y[0] = t[0]+t[7]
442         STRH    r6, [r0, #14]           ; y[1] = t[1]+t2[6]
443         STRH    r3, [r0, #30]           ; y[2] = t[2]+t2[5]
444         STRH    r7, [r0, #46]           ; y[3] = t2[3]+t[4]
445         RSB     r11,r11,r5, LSL #1      ; r11= t[0]-t2[7]
446         RSB     r6, r6, r4, LSL #1      ; r6 = t[1]-t3[6]
447         RSB     r3, r3, r10,LSL #1      ; r3 = t[2]-t3[5]
448         RSB     r7, r7, r9, LSL #1      ; r7 = t[3]-t2[4]
449         STRH    r7, [r0, #62]           ; y[4] = t2[3]-t[4]
450         STRH    r3, [r0, #78]           ; y[5] = t[2]-t2[5]
451         STRH    r6, [r0, #94]           ; y[6] = t[1]-t2[6]
452         STRH    r11, [r0, #110]         ; y[7] = t2[0]-t[7]
453         MOV     PC,r14
454
455 idct4core_down_arm
456         ; r0 =       ogg_int16_t *_y (destination)
457         ; r1 = const ogg_int16_t *_x (source)
458         LDRSH   r9, [r1], #16           ; r9 = x[0]
459         LDR     r10,OC_C4S4             ; r10= OC_C4S4
460         LDRSH   r12,[r1, #-12]          ; r12= x[2]
461         LDR     r4, OC_C6S2             ; r4 = OC_C6S2
462         MUL     r9, r10,r9              ; r9 = t[0]<<16 = OC_C4S4*x[0]
463         LDR     r5, OC_C2S6             ; r5 = OC_C2S6
464         MUL     r4, r12,r4              ; r4 = t[2]<<16 = OC_C6S2*x[2]
465         LDRSH   r3, [r1, #-14]          ; r3 = x[1]
466         MUL     r5, r12,r5              ; r5 = t[3]<<16 = OC_C2S6*x[2]
467         LDR     r6, OC_C7S1             ; r6 = OC_C7S1
468         LDR     r12,OC_C1S7             ; r12= OC_C1S7
469         LDRSH   r11,[r1, #-10]          ; r11= x[3]
470         MUL     r6, r3, r6              ; r6 = t[4]<<16 = OC_C7S1*x[1]
471         LDR     r7, OC_C5S3             ; r7 = OC_C5S3
472         MUL     r3, r12,r3              ; r3 = t[7]<<16 = OC_C1S7*x[1]
473         LDR     r8, OC_C3S5             ; r8 = OC_C3S5
474         MUL     r7, r11,r7              ; r7 = -t[5]<<16 = OC_C5S3*x[3]
475         MOV     r9, r9, ASR #16         ; r9 = t[0]
476         MUL     r11,r8, r11             ; r11= t[6]<<16 = OC_C3S5*x[3]
477         MOV     r6, r6, ASR #16         ; r6 = t[4]
478 ; TODO: This is wrong; t[4]-t[5] and t[7]-t[6] need to be truncated to 16-bit
479 ; before multiplying, not after (this is not equivalent)
480         SUB     r7, r6, r7, ASR #16     ; r7 = t2[4]=t[4]+t[5] (as r7=-t[5])
481         RSB     r6, r7, r6, LSL #1      ; r6 = t[4]-t[5]
482         MUL     r6, r10,r6              ; r6 = t2[5]<<16 =OC_C4S4*(t[4]-t[5])
483         MOV     r3, r3, ASR #16         ; r3 = t[7]
484         ADD     r11,r3, r11,ASR #16     ; r11= t2[7]=t[7]+t[6]
485         RSB     r3, r11,r3, LSL #1      ; r3 = t[7]-t[6]
486         ADD     r9, r9, #8              ; r9 = t[0]+8
487         MUL     r3, r10,r3              ; r3 = t2[6]<<16 =OC_C4S4*(t[7]-t[6])
488         ADD     r4, r9, r4, ASR #16     ; r4 = t[1] = t[0] + t[2] + 8
489         RSB     r10,r4, r9, LSL #1      ; r10= t[2] = t[0] - t[2] + 8
490         ADD     r5, r9, r5, ASR #16     ; r5 = t[0] = t[0] + t[3] + 8
491         RSB     r9, r5, r9, LSL #1      ; r9 = t[3] = t[0] - t[3] + 8
492         MOV     r3, r3, ASR #16         ; r3 = t2[6]
493         ADD     r6, r3, r6, ASR #16     ; r6 = t3[6] = t2[6]+t2[5]
494         RSB     r3, r6, r3, LSL #1      ; r3 = t3[5] = t2[6]-t2[5]
495         ADD     r5, r5, r11             ; r5 = t[0]+t2[7]+8
496         ADD     r4, r4, r6              ; r4 = t[1]+t3[6]+8
497         ADD     r10,r10,r3              ; r10= t[2]+t3[5]+8
498         ADD     r9, r9, r7              ; r9 = t[3]+t2[4]+8
499         SUB     r11,r5, r11,LSL #1      ; r11= t[0]-t2[7]+8
500         SUB     r6, r4, r6, LSL #1      ; r6 = t[1]-t3[6]+8
501         SUB     r3, r10,r3, LSL #1      ; r3 = t[2]-t3[5]+8
502         SUB     r7, r9, r7, LSL #1      ; r7 = t[3]-t2[4]+8
503         ; TODO: This is wrong.
504         ; The C code truncates to 16 bits by storing to RAM and doing the
505         ;  shifts later; we've got an extra 4 bits here.
506         MOV     r11,r11,ASR #4
507         MOV     r6, r6, ASR #4
508         MOV     r3, r3, ASR #4
509         MOV     r7, r7, ASR #4
510         MOV     r9, r9, ASR #4
511         MOV     r10,r10,ASR #4
512         MOV     r4, r4, ASR #4
513         MOV     r5, r5, ASR #4
514         STRH    r5,[r0], #2             ; y[0] = t[0]+t[7]
515         STRH    r4, [r0, #14]           ; y[1] = t[1]+t2[6]
516         STRH    r10,[r0, #30]           ; y[2] = t[2]+t2[5]
517         STRH    r9, [r0, #46]           ; y[3] = t2[3]+t[4]
518         STRH    r7, [r0, #62]           ; y[4] = t2[3]-t[4]
519         STRH    r3, [r0, #78]           ; y[5] = t[2]-t2[5]
520         STRH    r6, [r0, #94]           ; y[6] = t[1]-t2[6]
521         STRH    r11,[r0, #110]          ; y[7] = t2[0]-t[7]
522         MOV     PC,r14
523
524 idct8core_arm
525         ; r0 =       ogg_int16_t *_y (destination)
526         ; r1 = const ogg_int16_t *_x (source)
527         LDRSH   r2, [r1],#16            ; r2 = x[0]
528         STMFD   r13!,{r1,r14}
529         LDRSH   r6, [r1, #-8]           ; r6 = x[4]
530         LDR     r12,OC_C4S4             ; r12= C4S4
531         LDRSH   r4, [r1, #-12]          ; r4 = x[2]
532         ADD     r2, r2, r6              ; r2 = x[0] + x[4]
533         SUB     r6, r2, r6, LSL #1      ; r6 = x[0] - x[4]
534         ; For spec compliance, these sums must be truncated to 16-bit precision
535         ; _before_ the multiply (not after).
536         ; Sadly, ARMv4 provides no simple way to do that.
537         MOV     r2, r2, LSL #16
538         MOV     r6, r6, LSL #16
539         MOV     r2, r2, ASR #16
540         MOV     r6, r6, ASR #16
541         MUL     r2, r12,r2              ; r2 = t[0]<<16 = C4S4*(x[0]+x[4])
542         LDRSH   r8, [r1, #-4]           ; r8 = x[6]
543         LDR     r7, OC_C6S2             ; r7 = OC_C6S2
544         MUL     r6, r12,r6              ; r6 = t[1]<<16 = C4S4*(x[0]-x[4])
545         LDR     r14,OC_C2S6             ; r14= OC_C2S6
546         MUL     r3, r4, r7              ; r3 = OC_C6S2*x[2]
547         LDR     r5, OC_C7S1             ; r5 = OC_C7S1
548         MUL     r4, r14,r4              ; r4 = OC_C2S6*x[2]
549         MOV     r3, r3, ASR #16         ; r3 = OC_C6S2*x[2]>>16
550         MUL     r14,r8, r14             ; r14= OC_C2S6*x[6]
551         MOV     r4, r4, ASR #16         ; r4 = OC_C2S6*x[2]>>16
552         MUL     r8, r7, r8              ; r8 = OC_C6S2*x[6]
553         LDR     r7, OC_C1S7             ; r7 = OC_C1S7
554         SUB     r3, r3, r14,ASR #16     ; r3=t[2]=C6S2*x[2]>>16-C2S6*x[6]>>16
555         LDRSH   r14,[r1, #-14]          ; r14= x[1]
556         ADD     r4, r4, r8, ASR #16     ; r4=t[3]=C2S6*x[2]>>16+C6S2*x[6]>>16
557         LDRSH   r8, [r1, #-2]           ; r8 = x[7]
558         MUL     r9, r5, r14             ; r9 = OC_C7S1*x[1]
559         LDRSH   r10,[r1, #-6]           ; r10= x[5]
560         MUL     r14,r7, r14             ; r14= OC_C1S7*x[1]
561         MOV     r9, r9, ASR #16         ; r9 = OC_C7S1*x[1]>>16
562         MUL     r7, r8, r7              ; r7 = OC_C1S7*x[7]
563         MOV     r14,r14,ASR #16         ; r14= OC_C1S7*x[1]>>16
564         MUL     r8, r5, r8              ; r8 = OC_C7S1*x[7]
565         LDRSH   r1, [r1, #-10]          ; r1 = x[3]
566         LDR     r5, OC_C3S5             ; r5 = OC_C3S5
567         LDR     r11,OC_C5S3             ; r11= OC_C5S3
568         ADD     r8, r14,r8, ASR #16     ; r8=t[7]=C1S7*x[1]>>16+C7S1*x[7]>>16
569         MUL     r14,r5, r10             ; r14= OC_C3S5*x[5]
570         SUB     r9, r9, r7, ASR #16     ; r9=t[4]=C7S1*x[1]>>16-C1S7*x[7]>>16
571         MUL     r10,r11,r10             ; r10= OC_C5S3*x[5]
572         MOV     r14,r14,ASR #16         ; r14= OC_C3S5*x[5]>>16
573         MUL     r11,r1, r11             ; r11= OC_C5S3*x[3]
574         MOV     r10,r10,ASR #16         ; r10= OC_C5S3*x[5]>>16
575         MUL     r1, r5, r1              ; r1 = OC_C3S5*x[3]
576         SUB     r14,r14,r11,ASR #16     ;r14=t[5]=C3S5*x[5]>>16-C5S3*x[3]>>16
577         ADD     r10,r10,r1, ASR #16     ;r10=t[6]=C5S3*x[5]>>16+C3S5*x[3]>>16
578         ; r2=t[0]<<16 r3=t[2] r4=t[3] r6=t[1]<<16 r8=t[7] r9=t[4]
579         ; r10=t[6] r12=C4S4 r14=t[5]
580 ; TODO: This is wrong; t[4]-t[5] and t[7]-t[6] need to be truncated to 16-bit
581 ; before multiplying, not after (this is not equivalent)
582         ; Stage 2
583         ; 4-5 butterfly
584         ADD     r9, r9, r14             ; r9 = t2[4]     =       t[4]+t[5]
585         SUB     r14,r9, r14, LSL #1     ; r14=                   t[4]-t[5]
586         MUL     r14,r12,r14             ; r14= t2[5]<<16 = C4S4*(t[4]-t[5])
587         ; 7-6 butterfly
588         ADD     r8, r8, r10             ; r8 = t2[7]     =       t[7]+t[6]
589         SUB     r10,r8, r10, LSL #1     ; r10=                   t[7]-t[6]
590         MUL     r10,r12,r10             ; r10= t2[6]<<16 = C4S4*(t[7]+t[6])
591         ; r2=t[0]<<16 r3=t[2] r4=t[3] r6=t[1]<<16 r8=t2[7] r9=t2[4]
592         ; r10=t2[6]<<16 r12=C4S4 r14=t2[5]<<16
593         ; Stage 3
594         ; 0-3 butterfly
595         ADD     r2, r4, r2, ASR #16     ; r2 = t2[0] = t[0] + t[3]
596         SUB     r4, r2, r4, LSL #1      ; r4 = t2[3] = t[0] - t[3]
597         ; 1-2 butterfly
598         ADD     r6, r3, r6, ASR #16     ; r6 = t2[1] = t[1] + t[2]
599         SUB     r3, r6, r3, LSL #1      ; r3 = t2[2] = t[1] - t[2]
600         ; 6-5 butterfly
601         MOV     r14,r14,ASR #16         ; r14= t2[5]
602         ADD     r10,r14,r10,ASR #16     ; r10= t3[6] = t[6] + t[5]
603         SUB     r14,r10,r14,LSL #1      ; r14= t3[5] = t[6] - t[5]
604         ; r2=t2[0] r3=t2[2] r4=t2[3] r6=t2[1] r8=t2[7] r9=t2[4]
605         ; r10=t3[6] r14=t3[5]
606         ; Stage 4
607         ADD     r2, r2, r8              ; r2 = t[0] + t[7]
608         ADD     r6, r6, r10             ; r6 = t[1] + t[6]
609         ADD     r3, r3, r14             ; r3 = t[2] + t[5]
610         ADD     r4, r4, r9              ; r4 = t[3] + t[4]
611         SUB     r8, r2, r8, LSL #1      ; r8 = t[0] - t[7]
612         SUB     r10,r6, r10,LSL #1      ; r10= t[1] - t[6]
613         SUB     r14,r3, r14,LSL #1      ; r14= t[2] - t[5]
614         SUB     r9, r4, r9, LSL #1      ; r9 = t[3] - t[4]
615         STRH    r2, [r0], #2            ; y[0] = t[0]+t[7]
616         STRH    r6, [r0, #14]           ; y[1] = t[1]+t[6]
617         STRH    r3, [r0, #30]           ; y[2] = t[2]+t[5]
618         STRH    r4, [r0, #46]           ; y[3] = t[3]+t[4]
619         STRH    r9, [r0, #62]           ; y[4] = t[3]-t[4]
620         STRH    r14,[r0, #78]           ; y[5] = t[2]-t[5]
621         STRH    r10,[r0, #94]           ; y[6] = t[1]-t[6]
622         STRH    r8, [r0, #110]          ; y[7] = t[0]-t[7]
623         LDMFD   r13!,{r1,PC}
624
625 idct8core_down_arm
626         ; r0 =       ogg_int16_t *_y (destination)
627         ; r1 = const ogg_int16_t *_x (source)
628         LDRSH   r2, [r1],#16            ; r2 = x[0]
629         STMFD   r13!,{r1,r14}
630         LDRSH   r6, [r1, #-8]           ; r6 = x[4]
631         LDR     r12,OC_C4S4             ; r12= C4S4
632         LDRSH   r4, [r1, #-12]          ; r4 = x[2]
633         ADD     r2, r2, r6              ; r2 = x[0] + x[4]
634         SUB     r6, r2, r6, LSL #1      ; r6 = x[0] - x[4]
635         ; For spec compliance, these sums must be truncated to 16-bit precision
636         ; _before_ the multiply (not after).
637         ; Sadly, ARMv4 provides no simple way to do that.
638         MOV     r2, r2, LSL #16
639         MOV     r6, r6, LSL #16
640         MOV     r2, r2, ASR #16
641         MOV     r6, r6, ASR #16
642         MUL     r2, r12,r2              ; r2 = t[0]<<16 = C4S4*(x[0]+x[4])
643         LDRSH   r8, [r1, #-4]           ; r8 = x[6]
644         LDR     r7, OC_C6S2             ; r7 = OC_C6S2
645         MUL     r6, r12,r6              ; r6 = t[1]<<16 = C4S4*(x[0]-x[4])
646         LDR     r14,OC_C2S6             ; r14= OC_C2S6
647         MUL     r3, r4, r7              ; r3 = OC_C6S2*x[2]
648         LDR     r5, OC_C7S1             ; r5 = OC_C7S1
649         MUL     r4, r14,r4              ; r4 = OC_C2S6*x[2]
650         MOV     r3, r3, ASR #16         ; r3 = OC_C6S2*x[2]>>16
651         MUL     r14,r8, r14             ; r14= OC_C2S6*x[6]
652         MOV     r4, r4, ASR #16         ; r4 = OC_C2S6*x[2]>>16
653         MUL     r8, r7, r8              ; r8 = OC_C6S2*x[6]
654         LDR     r7, OC_C1S7             ; r7 = OC_C1S7
655         SUB     r3, r3, r14,ASR #16     ; r3=t[2]=C6S2*x[2]>>16-C2S6*x[6]>>16
656         LDRSH   r14,[r1, #-14]          ; r14= x[1]
657         ADD     r4, r4, r8, ASR #16     ; r4=t[3]=C2S6*x[2]>>16+C6S2*x[6]>>16
658         LDRSH   r8, [r1, #-2]           ; r8 = x[7]
659         MUL     r9, r5, r14             ; r9 = OC_C7S1*x[1]
660         LDRSH   r10,[r1, #-6]           ; r10= x[5]
661         MUL     r14,r7, r14             ; r14= OC_C1S7*x[1]
662         MOV     r9, r9, ASR #16         ; r9 = OC_C7S1*x[1]>>16
663         MUL     r7, r8, r7              ; r7 = OC_C1S7*x[7]
664         MOV     r14,r14,ASR #16         ; r14= OC_C1S7*x[1]>>16
665         MUL     r8, r5, r8              ; r8 = OC_C7S1*x[7]
666         LDRSH   r1, [r1, #-10]          ; r1 = x[3]
667         LDR     r5, OC_C3S5             ; r5 = OC_C3S5
668         LDR     r11,OC_C5S3             ; r11= OC_C5S3
669         ADD     r8, r14,r8, ASR #16     ; r8=t[7]=C1S7*x[1]>>16+C7S1*x[7]>>16
670         MUL     r14,r5, r10             ; r14= OC_C3S5*x[5]
671         SUB     r9, r9, r7, ASR #16     ; r9=t[4]=C7S1*x[1]>>16-C1S7*x[7]>>16
672         MUL     r10,r11,r10             ; r10= OC_C5S3*x[5]
673         MOV     r14,r14,ASR #16         ; r14= OC_C3S5*x[5]>>16
674         MUL     r11,r1, r11             ; r11= OC_C5S3*x[3]
675         MOV     r10,r10,ASR #16         ; r10= OC_C5S3*x[5]>>16
676         MUL     r1, r5, r1              ; r1 = OC_C3S5*x[3]
677         SUB     r14,r14,r11,ASR #16     ;r14=t[5]=C3S5*x[5]>>16-C5S3*x[3]>>16
678         ADD     r10,r10,r1, ASR #16     ;r10=t[6]=C5S3*x[5]>>16+C3S5*x[3]>>16
679         ; r2=t[0]<<16 r3=t[2] r4=t[3] r6=t[1]<<16 r8=t[7] r9=t[4]
680         ; r10=t[6] r12=C4S4 r14=t[5]
681         ; Stage 2
682 ; TODO: This is wrong; t[4]-t[5] and t[7]-t[6] need to be truncated to 16-bit
683 ; before multiplying, not after (this is not equivalent)
684         ; 4-5 butterfly
685         ADD     r9, r9, r14             ; r9 = t2[4]     =       t[4]+t[5]
686         SUB     r14,r9, r14, LSL #1     ; r14=                   t[4]-t[5]
687         MUL     r14,r12,r14             ; r14= t2[5]<<16 = C4S4*(t[4]-t[5])
688         ; 7-6 butterfly
689         ADD     r8, r8, r10             ; r8 = t2[7]     =       t[7]+t[6]
690         SUB     r10,r8, r10, LSL #1     ; r10=                   t[7]-t[6]
691         MUL     r10,r12,r10             ; r10= t2[6]<<16 = C4S4*(t[7]+t[6])
692         ; r2=t[0]<<16 r3=t[2] r4=t[3] r6=t[1]<<16 r8=t2[7] r9=t2[4]
693         ; r10=t2[6]<<16 r12=C4S4 r14=t2[5]<<16
694         ; Stage 3
695         ADD     r2, r2, #8<<16          ; r2 = t[0]+8<<16
696         ADD     r6, r6, #8<<16          ; r6 = t[1]+8<<16
697         ; 0-3 butterfly
698         ADD     r2, r4, r2, ASR #16     ; r2 = t2[0] = t[0] + t[3] + 8
699         SUB     r4, r2, r4, LSL #1      ; r4 = t2[3] = t[0] - t[3] + 8
700         ; 1-2 butterfly
701         ADD     r6, r3, r6, ASR #16     ; r6 = t2[1] = t[1] + t[2] + 8
702         SUB     r3, r6, r3, LSL #1      ; r3 = t2[2] = t[1] - t[2] + 8
703         ; 6-5 butterfly
704         MOV     r14,r14,ASR #16         ; r14= t2[5]
705         ADD     r10,r14,r10,ASR #16     ; r10= t3[6] = t[6] + t[5]
706         SUB     r14,r10,r14,LSL #1      ; r14= t3[5] = t[6] - t[5]
707         ; r2=t2[0] r3=t2[2] r4=t2[3] r6=t2[1] r8=t2[7] r9=t2[4]
708         ; r10=t3[6] r14=t3[5]
709         ; Stage 4
710         ADD     r2, r2, r8              ; r2 = t[0] + t[7] + 8
711         ADD     r6, r6, r10             ; r6 = t[1] + t[6] + 8
712         ADD     r3, r3, r14             ; r3 = t[2] + t[5] + 8
713         ADD     r4, r4, r9              ; r4 = t[3] + t[4] + 8
714         SUB     r8, r2, r8, LSL #1      ; r8 = t[0] - t[7] + 8
715         SUB     r10,r6, r10,LSL #1      ; r10= t[1] - t[6] + 8
716         SUB     r14,r3, r14,LSL #1      ; r14= t[2] - t[5] + 8
717         SUB     r9, r4, r9, LSL #1      ; r9 = t[3] - t[4] + 8
718         ; TODO: This is wrong.
719         ; The C code truncates to 16 bits by storing to RAM and doing the
720         ;  shifts later; we've got an extra 4 bits here.
721         MOV     r2, r2, ASR #4
722         MOV     r6, r6, ASR #4
723         MOV     r3, r3, ASR #4
724         MOV     r4, r4, ASR #4
725         MOV     r8, r8, ASR #4
726         MOV     r10,r10,ASR #4
727         MOV     r14,r14,ASR #4
728         MOV     r9, r9, ASR #4
729         STRH    r2, [r0], #2            ; y[0] = t[0]+t[7]
730         STRH    r6, [r0, #14]           ; y[1] = t[1]+t[6]
731         STRH    r3, [r0, #30]           ; y[2] = t[2]+t[5]
732         STRH    r4, [r0, #46]           ; y[3] = t[3]+t[4]
733         STRH    r9, [r0, #62]           ; y[4] = t[3]-t[4]
734         STRH    r14,[r0, #78]           ; y[5] = t[2]-t[5]
735         STRH    r10,[r0, #94]           ; y[6] = t[1]-t[6]
736         STRH    r8, [r0, #110]          ; y[7] = t[0]-t[7]
737         LDMFD   r13!,{r1,PC}
738
739  [ OC_ARM_ASM_MEDIA
740         EXPORT  oc_idct8x8_1_v6
741         EXPORT  oc_idct8x8_v6
742
743 oc_idct8x8_1_v6
744         ; r0 = ogg_int16_t  *_y
745         ; r1 = ogg_uint16_t  _dc
746         ORR     r2, r1, r1, LSL #16
747         ORR     r3, r1, r1, LSL #16
748         STRD    r2, [r0], #8
749         STRD    r2, [r0], #8
750         STRD    r2, [r0], #8
751         STRD    r2, [r0], #8
752         STRD    r2, [r0], #8
753         STRD    r2, [r0], #8
754         STRD    r2, [r0], #8
755         STRD    r2, [r0], #8
756         STRD    r2, [r0], #8
757         STRD    r2, [r0], #8
758         STRD    r2, [r0], #8
759         STRD    r2, [r0], #8
760         STRD    r2, [r0], #8
761         STRD    r2, [r0], #8
762         STRD    r2, [r0], #8
763         STRD    r2, [r0], #8
764         MOV     PC, r14
765
766 oc_idct8x8_v6
767         ; r0 = ogg_int16_t *_y
768         ; r1 = ogg_int16_t *_x
769         ; r2 = int          _last_zzi
770         CMP     r2, #3
771         BLE     oc_idct8x8_3_v6
772         ;CMP    r2, #6
773         ;BLE    oc_idct8x8_6_v6
774         CMP     r2, #10
775         BLE     oc_idct8x8_10_v6
776 oc_idct8x8_slow_v6
777         STMFD   r13!,{r4-r11,r14}
778         SUB     r13,r13,#64*2
779 ; Row transforms
780         STR     r0, [r13,#-4]!
781         ADD     r0, r13, #4     ; Write to temp storage.
782         BL      idct8_8core_v6
783         BL      idct8_8core_v6
784         BL      idct8_8core_v6
785         BL      idct8_8core_v6
786         LDR     r0, [r13], #4   ; Write to the final destination.
787         ; Clear input data for next block (decoder only).
788         SUB     r2, r1, #8*16
789         CMP     r0, r2
790         MOV     r1, r13         ; And read from temp storage.
791         BEQ     oc_idct8x8_slow_v6_cols
792         MOV     r4, #0
793         MOV     r5, #0
794         STRD    r4, [r2], #8
795         STRD    r4, [r2], #8
796         STRD    r4, [r2], #8
797         STRD    r4, [r2], #8
798         STRD    r4, [r2], #8
799         STRD    r4, [r2], #8
800         STRD    r4, [r2], #8
801         STRD    r4, [r2], #8
802         STRD    r4, [r2], #8
803         STRD    r4, [r2], #8
804         STRD    r4, [r2], #8
805         STRD    r4, [r2], #8
806         STRD    r4, [r2], #8
807         STRD    r4, [r2], #8
808         STRD    r4, [r2], #8
809         STRD    r4, [r2], #8
810 oc_idct8x8_slow_v6_cols
811 ; Column transforms
812         BL      idct8_8core_down_v6
813         BL      idct8_8core_down_v6
814         BL      idct8_8core_down_v6
815         BL      idct8_8core_down_v6
816         ADD     r13,r13,#64*2
817         LDMFD   r13!,{r4-r11,PC}
818
819 oc_idct8x8_10_v6
820         STMFD   r13!,{r4-r11,r14}
821         SUB     r13,r13,#64*2+4
822 ; Row transforms
823         MOV     r2, r13
824         STR     r0, [r13,#-4]!
825         AND     r0, r2, #4      ; Align the stack.
826         ADD     r0, r0, r2      ; Write to temp storage.
827         BL      idct4_3core_v6
828         BL      idct2_1core_v6
829         LDR     r0, [r13], #4   ; Write to the final destination.
830         ; Clear input data for next block (decoder only).
831         SUB     r2, r1, #4*16
832         CMP     r0, r2
833         AND     r1, r13,#4      ; Align the stack.
834         BEQ     oc_idct8x8_10_v6_cols
835         MOV     r4, #0
836         MOV     r5, #0
837         STRD    r4, [r2]
838         STRD    r4, [r2,#16]
839         STR     r4, [r2,#32]
840         STR     r4, [r2,#48]
841 oc_idct8x8_10_v6_cols
842 ; Column transforms
843         ADD     r1, r1, r13     ; And read from temp storage.
844         BL      idct4_4core_down_v6
845         BL      idct4_4core_down_v6
846         BL      idct4_4core_down_v6
847         BL      idct4_4core_down_v6
848         ADD     r13,r13,#64*2+4
849         LDMFD   r13!,{r4-r11,PC}
850
851 oc_idct8x8_3_v6
852         STMFD   r13!,{r4-r8,r14}
853         SUB     r13,r13,#64*2
854 ; Row transforms
855         MOV     r8, r0
856         MOV     r0, r13         ; Write to temp storage.
857         BL      idct2_1core_v6
858         ; Clear input data for next block (decoder only).
859         SUB     r0, r1, #2*16
860         CMP     r0, r8
861         MOV     r1, r13         ; Read from temp storage.
862         MOVNE   r4, #0
863         STRNE   r4, [r0]
864         STRNE   r4, [r0,#16]
865         MOVNE   r0, r8          ; Write to the final destination.
866 ; Column transforms
867         BL      idct2_2core_down_v6
868         BL      idct2_2core_down_v6
869         BL      idct2_2core_down_v6
870         BL      idct2_2core_down_v6
871         ADD     r13,r13,#64*2
872         LDMFD   r13!,{r4-r8,PC}
873
874 idct2_1core_v6
875         ; r0 =       ogg_int16_t *_y (destination)
876         ; r1 = const ogg_int16_t *_x (source)
877 ; Stage 1:
878         LDR     r2, [r1], #16           ; r2 = <x[0,1]|x[0,0]>
879         LDR     r3, OC_C4S4
880         LDRSH   r6, [r1], #16           ; r6 = x[1,0]
881         SMULWB  r12,r3, r2              ; r12= t[0,0]=OC_C4S4*x[0,0]>>16
882         LDRD    r4, OC_C7S1             ; r4 = OC_C7S1; r5 = OC_C1S7
883         SMULWB  r6, r3, r6              ; r6 = t[1,0]=OC_C4S4*x[1,0]>>16
884         SMULWT  r4, r4, r2              ; r4 = t[0,4]=OC_C7S1*x[0,1]>>16
885         SMULWT  r7, r5, r2              ; r7 = t[0,7]=OC_C1S7*x[0,1]>>16
886 ; Stage 2:
887         SMULWB  r5, r3, r4              ; r5 = t[0,5]=OC_C4S4*t[0,4]>>16
888         PKHBT   r12,r12,r6, LSL #16     ; r12= <t[1,0]|t[0,0]>
889         SMULWB  r6, r3, r7              ; r6 = t[0,6]=OC_C4S4*t[0,7]>>16
890         PKHBT   r7, r7, r3              ; r7 = <0|t[0,7]>
891 ; Stage 3:
892         PKHBT   r5, r6, r5, LSL #16     ; r5 = <t[0,5]|t[0,6]>
893         PKHBT   r4, r4, r3              ; r4 = <0|t[0,4]>
894         SASX    r5, r5, r5              ; r5 = <t[0,6]+t[0,5]|t[0,6]-t[0,5]>
895 ; Stage 4:
896         PKHTB   r6, r3, r5, ASR #16     ; r6 = <0|t[0,6]>
897         PKHBT   r5, r5, r3              ; r5 = <0|t[0,5]>
898         SADD16  r3, r12,r7              ; r3 = t[0]+t[7]
899         STR     r3, [r0], #4            ; y[0<<3] = t[0]+t[7]
900         SADD16  r3, r12,r6              ; r3 = t[0]+t[6]
901         STR     r3, [r0, #12]           ; y[1<<3] = t[0]+t[6]
902         SADD16  r3, r12,r5              ; r3 = t[0]+t[5]
903         STR     r3, [r0, #28]           ; y[2<<3] = t[0]+t[5]
904         SADD16  r3, r12,r4              ; r3 = t[0]+t[4]
905         STR     r3, [r0, #44]           ; y[3<<3] = t[0]+t[4]
906         SSUB16  r4, r12,r4              ; r4 = t[0]-t[4]
907         STR     r4, [r0, #60]           ; y[4<<3] = t[0]-t[4]
908         SSUB16  r5, r12,r5              ; r5 = t[0]-t[5]
909         STR     r5, [r0, #76]           ; y[5<<3] = t[0]-t[5]
910         SSUB16  r6, r12,r6              ; r6 = t[0]-t[6]
911         STR     r6, [r0, #92]           ; y[6<<3] = t[0]-t[6]
912         SSUB16  r7, r12,r7              ; r7 = t[0]-t[7]
913         STR     r7, [r0, #108]          ; y[7<<3] = t[0]-t[7]
914         MOV     PC,r14
915  ]
916
917         ALIGN 8
918 OC_C7S1
919         DCD     12785 ; 31F1
920 OC_C1S7
921         DCD     64277 ; FB15
922 OC_C6S2
923         DCD     25080 ; 61F8
924 OC_C2S6
925         DCD     60547 ; EC83
926 OC_C5S3
927         DCD     36410 ; 8E3A
928 OC_C3S5
929         DCD     54491 ; D4DB
930 OC_C4S4
931         DCD     46341 ; B505
932
933  [ OC_ARM_ASM_MEDIA
934 idct2_2core_down_v6
935         ; r0 =       ogg_int16_t *_y (destination)
936         ; r1 = const ogg_int16_t *_x (source)
937 ; Stage 1:
938         LDR     r2, [r1], #16           ; r2 = <x[0,1]|x[0,0]>
939         LDR     r3, OC_C4S4
940         MOV     r7 ,#8                  ; r7  = 8
941         LDR     r6, [r1], #16           ; r6 = <x[1,1]|x[1,0]>
942         SMLAWB  r12,r3, r2, r7          ; r12= (t[0,0]=OC_C4S4*x[0,0]>>16)+8
943         LDRD    r4, OC_C7S1             ; r4 = OC_C7S1; r5 = OC_C1S7
944         SMLAWB  r7, r3, r6, r7          ; r7 = (t[1,0]=OC_C4S4*x[1,0]>>16)+8
945         SMULWT  r5, r5, r2              ; r2 = t[0,7]=OC_C1S7*x[0,1]>>16
946         PKHBT   r12,r12,r7, LSL #16     ; r12= <t[1,0]+8|t[0,0]+8>
947         SMULWT  r4, r4, r2              ; r4 = t[0,4]=OC_C7S1*x[0,1]>>16
948 ; Here we cheat: row 1 had just a DC, so x[0,1]==x[1,1] by definition.
949         PKHBT   r7, r5, r5, LSL #16     ; r7 = <t[0,7]|t[0,7]>
950 ; Stage 2:
951         SMULWB  r6, r3, r7              ; r6 = t[0,6]=OC_C4S4*t[0,7]>>16
952         PKHBT   r4, r4, r4, LSL #16     ; r4 = <t[0,4]|t[0,4]>
953         SMULWT  r2, r3, r7              ; r2 = t[1,6]=OC_C4S4*t[1,7]>>16
954         SMULWB  r5, r3, r4              ; r5 = t[0,5]=OC_C4S4*t[0,4]>>16
955         PKHBT   r6, r6, r2, LSL #16     ; r6 = <t[1,6]|t[0,6]>
956         SMULWT  r2, r3, r4              ; r2 = t[1,5]=OC_C4S4*t[1,4]>>16
957         PKHBT   r2, r5, r2, LSL #16     ; r2 = <t[1,5]|t[0,5]>
958 ; Stage 3:
959         SSUB16  r5, r6, r2              ; r5 = <t[1,6]-t[1,5]|t[0,6]-t[0,5]>
960         SADD16  r6, r6, r2              ; r6 = <t[1,6]+t[1,5]|t[0,6]+t[0,5]>
961 ; Stage 4:
962         SADD16  r2, r12,r7              ; r2 = t[0]+t[7]+8
963         MOV     r3, r2, ASR #4
964         MOV     r2, r2, LSL #16
965         PKHTB   r3, r3, r2, ASR #20     ; r3 = t[0]+t[7]+8>>4
966         STR     r3, [r0], #4            ; y[0<<3] = t[0]+t[7]+8>>4
967         SADD16  r2, r12,r6              ; r2 = t[0]+t[6]+8
968         MOV     r3, r2, ASR #4
969         MOV     r2, r2, LSL #16
970         PKHTB   r3, r3, r2, ASR #20     ; r3 = t[0]+t[6]+8>>4
971         STR     r3, [r0, #12]           ; y[1<<3] = t[0]+t[6]+8>>4
972         SADD16  r2, r12,r5              ; r2 = t[0]+t[5]+8
973         MOV     r3, r2, ASR #4
974         MOV     r2, r2, LSL #16
975         PKHTB   r3, r3, r2, ASR #20     ; r3 = t[0]+t[5]+8>>4
976         STR     r3, [r0, #28]           ; y[2<<3] = t[0]+t[5]+8>>4
977         SADD16  r2, r12,r4              ; r2 = t[0]+t[4]+8
978         MOV     r3, r2, ASR #4
979         MOV     r2, r2, LSL #16
980         PKHTB   r3, r3, r2, ASR #20     ; r3 = t[0]+t[4]+8>>4
981         STR     r3, [r0, #44]           ; y[3<<3] = t[0]+t[4]+8>>4
982         SSUB16  r4, r12,r4              ; r4 = t[0]-t[4]+8
983         MOV     r3, r4, ASR #4
984         MOV     r4, r4, LSL #16
985         PKHTB   r3, r3, r4, ASR #20     ; r3 = t[0]-t[4]+8>>4
986         STR     r3, [r0, #60]           ; y[4<<3] = t[0]-t[4]+8>>4
987         SSUB16  r5, r12,r5              ; r5 = t[0]-t[5]+8
988         MOV     r3, r5, ASR #4
989         MOV     r5, r5, LSL #16
990         PKHTB   r3, r3, r5, ASR #20     ; r3 = t[0]-t[5]+8>>4
991         STR     r3, [r0, #76]           ; y[5<<3] = t[0]-t[5]+8>>4
992         SSUB16  r6, r12,r6              ; r6 = t[0]-t[6]+8
993         MOV     r3, r6, ASR #4
994         MOV     r6, r6, LSL #16
995         PKHTB   r3, r3, r6, ASR #20     ; r3 = t[0]-t[6]+8>>4
996         STR     r3, [r0, #92]           ; y[6<<3] = t[0]-t[6]+8>>4
997         SSUB16  r7, r12,r7              ; r7 = t[0]-t[7]+8
998         MOV     r3, r7, ASR #4
999         MOV     r7, r7, LSL #16
1000         PKHTB   r3, r3, r7, ASR #20     ; r3 = t[0]-t[7]+8>>4
1001         STR     r3, [r0, #108]          ; y[7<<3] = t[0]-t[7]+8>>4
1002         MOV     PC,r14
1003
1004 ; In theory this should save ~75 cycles over oc_idct8x8_10, more than enough to
1005 ;  pay for increased branch mis-prediction to get here, but in practice it
1006 ;  doesn't seem to slow anything down to take it out, and it's less code this
1007 ;  way.
1008  [ 0
1009 oc_idct8x8_6_v6
1010         STMFD   r13!,{r4-r8,r10,r11,r14}
1011         SUB     r13,r13,#64*2+4
1012 ; Row transforms
1013         MOV     r8, r0
1014         AND     r0, r13,#4      ; Align the stack.
1015         ADD     r0, r0, r13     ; Write to temp storage.
1016         BL      idct3_2core_v6
1017         BL      idct1core_v6
1018         ; Clear input data for next block (decoder only).
1019         SUB     r0, r1, #3*16
1020         CMP     r0, r8
1021         AND     r1, r13,#4      ; Align the stack.
1022         BEQ     oc_idct8x8_6_v6_cols
1023         MOV     r4, #0
1024         MOV     r5, #0
1025         STRD    r4, [r0]
1026         STR     r4, [r0,#16]
1027         STR     r4, [r0,#32]
1028         MOV     r0, r8          ; Write to the final destination.
1029 oc_idct8x8_6_v6_cols
1030 ; Column transforms
1031         ADD     r1, r1, r13     ; And read from temp storage.
1032         BL      idct3_3core_down_v6
1033         BL      idct3_3core_down_v6
1034         BL      idct3_3core_down_v6
1035         BL      idct3_3core_down_v6
1036         ADD     r13,r13,#64*2+4
1037         LDMFD   r13!,{r4-r8,r10,r11,PC}
1038
1039 idct1core_v6
1040         ; r0 =       ogg_int16_t *_y (destination)
1041         ; r1 = const ogg_int16_t *_x (source)
1042         LDRSH   r3, [r1], #16
1043         MOV     r12,#0x05
1044         ORR     r12,r12,#0xB500
1045         MUL     r3, r12, r3
1046         ; Stall ?
1047         MOV     r3, r3, ASR #16
1048         ; Don't need to actually store the odd lines; they won't be read.
1049         STRH    r3, [r0], #2
1050         STRH    r3, [r0, #30]
1051         STRH    r3, [r0, #62]
1052         STRH    r3, [r0, #94]
1053         MOV     PC,R14
1054
1055 idct3_2core_v6
1056         ; r0 =       ogg_int16_t *_y (destination)
1057         ; r1 = const ogg_int16_t *_x (source)
1058 ; Stage 1:
1059         LDRD    r4, [r1], #16           ; r4 = <x[0,1]|x[0,0]>; r5 = <*|x[0,2]>
1060         LDRD    r10,OC_C6S2_3_v6        ; r10= OC_C6S2; r11= OC_C2S6
1061         ; Stall
1062         SMULWB  r3, r11,r5              ; r3 = t[0,3]=OC_C2S6*x[0,2]>>16
1063         LDR     r11,OC_C4S4
1064         SMULWB  r2, r10,r5              ; r2 = t[0,2]=OC_C6S2*x[0,2]>>16
1065         LDR     r5, [r1], #16           ; r5 = <x[1,1]|x[1,0]>
1066         SMULWB  r12,r11,r4              ; r12= (t[0,0]=OC_C4S4*x[0,0]>>16)
1067         LDRD    r6, OC_C7S1_3_v6        ; r6 = OC_C7S1; r7 = OC_C1S7
1068         SMULWB  r10,r11,r5              ; r10= (t[1,0]=OC_C4S4*x[1,0]>>16)
1069         PKHBT   r12,r12,r10,LSL #16     ; r12= <t[1,0]|t[0,0]>
1070         SMULWT  r10,r7, r5              ; r10= t[1,7]=OC_C1S7*x[1,1]>>16
1071         PKHBT   r2, r2, r11             ; r2 = <0|t[0,2]>
1072         SMULWT  r7, r7, r4              ; r7 = t[0,7]=OC_C1S7*x[0,1]>>16
1073         PKHBT   r3, r3, r11             ; r3 = <0|t[0,3]>
1074         SMULWT  r5, r6, r5              ; r10= t[1,4]=OC_C7S1*x[1,1]>>16
1075         PKHBT   r7, r7, r10,LSL #16     ; r7 = <t[1,7]|t[0,7]>
1076         SMULWT  r4, r6, r4              ; r4 = t[0,4]=OC_C7S1*x[0,1]>>16
1077 ; Stage 2:
1078         SMULWB  r6, r11,r7              ; r6 = t[0,6]=OC_C4S4*t[0,7]>>16
1079         PKHBT   r4, r4, r5, LSL #16     ; r4 = <t[1,4]|t[0,4]>
1080         SMULWT  r10,r11,r7              ; r10= t[1,6]=OC_C4S4*t[1,7]>>16
1081         SMULWB  r5, r11,r4              ; r5 = t[0,5]=OC_C4S4*t[0,4]>>16
1082         PKHBT   r6, r6, r10,LSL #16     ; r6 = <t[1,6]|t[0,6]>
1083         SMULWT  r10,r11,r4              ; r10= t[1,5]=OC_C4S4*t[1,4]>>16
1084 ; Stage 3:
1085         B       idct4_3core_stage3_v6
1086
1087 ; Another copy so the LDRD offsets are less than +/- 255.
1088         ALIGN 8
1089 OC_C7S1_3_v6
1090         DCD     12785 ; 31F1
1091 OC_C1S7_3_v6
1092         DCD     64277 ; FB15
1093 OC_C6S2_3_v6
1094         DCD     25080 ; 61F8
1095 OC_C2S6_3_v6
1096         DCD     60547 ; EC83
1097
1098 idct3_3core_down_v6
1099         ; r0 =       ogg_int16_t *_y (destination)
1100         ; r1 = const ogg_int16_t *_x (source)
1101 ; Stage 1:
1102         LDRD    r10,[r1], #16           ; r10= <x[0,1]|x[0,0]>; r11= <??|x[0,2]>
1103         LDRD    r6, OC_C6S2_3_v6        ; r6 = OC_C6S2; r7 = OC_C2S6
1104         LDR     r4, [r1], #16           ; r4 = <x[1,1]|x[1,0]>
1105         SMULWB  r3, r7, r11             ; r3 = t[0,3]=OC_C2S6*x[0,2]>>16
1106         MOV     r7,#8
1107         SMULWB  r2, r6, r11             ; r2 = t[0,2]=OC_C6S2*x[0,2]>>16
1108         LDR     r11,OC_C4S4
1109         SMLAWB  r12,r11,r10,r7          ; r12= t[0,0]+8=(OC_C4S4*x[0,0]>>16)+8
1110 ; Here we cheat: row 2 had just a DC, so x[0,2]==x[1,2] by definition.
1111         PKHBT   r3, r3, r3, LSL #16     ; r3 = <t[0,3]|t[0,3]>
1112         SMLAWB  r5, r11,r4, r7          ; r5 = t[1,0]+8=(OC_C4S4*x[1,0]>>16)+8
1113         PKHBT   r2, r2, r2, LSL #16     ; r2 = <t[0,2]|t[0,2]>
1114         LDRD    r6, OC_C7S1_3_v6        ; r6 = OC_C7S1; r7 = OC_C1S7
1115         PKHBT   r12,r12,r5, LSL #16     ; r12= <t[1,0]+8|t[0,0]+8>
1116         SMULWT  r5, r7, r4              ; r5 = t[1,7]=OC_C1S7*x[1,1]>>16
1117         SMULWT  r7, r7, r10             ; r7 = t[0,7]=OC_C1S7*x[0,1]>>16
1118         SMULWT  r10,r6, r10             ; r10= t[0,4]=OC_C7S1*x[0,1]>>16
1119         PKHBT   r7, r7, r5, LSL #16     ; r7 = <t[1,7]|t[0,7]>
1120         SMULWT  r4, r6, r4              ; r4 = t[1,4]=OC_C7S1*x[1,1]>>16
1121 ; Stage 2:
1122         SMULWB  r6, r11,r7              ; r6 = t[0,6]=OC_C4S4*t[0,7]>>16
1123         PKHBT   r4, r10,r4, LSL #16     ; r4 = <t[1,4]|t[0,4]>
1124         SMULWT  r10,r11,r7              ; r10= t[1,6]=OC_C4S4*t[1,7]>>16
1125         SMULWB  r5, r11,r4              ; r5 = t[0,5]=OC_C4S4*t[0,4]>>16
1126         PKHBT   r6, r6, r10,LSL #16     ; r6 = <t[1,6]|t[0,6]>
1127         SMULWT  r10,r11,r4              ; r10= t[1,5]=OC_C4S4*t[1,4]>>16
1128 ; Stage 3:
1129         B       idct4_4core_down_stage3_v6
1130  ]
1131
1132 idct4_3core_v6
1133         ; r0 =       ogg_int16_t *_y (destination)
1134         ; r1 = const ogg_int16_t *_x (source)
1135 ; Stage 1:
1136         LDRD    r10,[r1], #16   ; r10= <x[0,1]|x[0,0]>; r11= <x[0,3]|x[0,2]>
1137         LDRD    r2, OC_C5S3_4_v6        ; r2 = OC_C5S3; r3 = OC_C3S5
1138         LDRD    r4, [r1], #16           ; r4 = <x[1,1]|x[1,0]>; r5 = <??|x[1,2]>
1139         SMULWT  r9, r3, r11             ; r9 = t[0,6]=OC_C3S5*x[0,3]>>16
1140         SMULWT  r8, r2, r11             ; r8 = -t[0,5]=OC_C5S3*x[0,3]>>16
1141         PKHBT   r9, r9, r2              ; r9 = <0|t[0,6]>
1142         LDRD    r6, OC_C6S2_4_v6        ; r6 = OC_C6S2; r7 = OC_C2S6
1143         PKHBT   r8, r8, r2              ; r9 = <0|-t[0,5]>
1144         SMULWB  r3, r7, r11             ; r3 = t[0,3]=OC_C2S6*x[0,2]>>16
1145         SMULWB  r2, r6, r11             ; r2 = t[0,2]=OC_C6S2*x[0,2]>>16
1146         LDR     r11,OC_C4S4
1147         SMULWB  r12,r7, r5              ; r12= t[1,3]=OC_C2S6*x[1,2]>>16
1148         SMULWB  r5, r6, r5              ; r5 = t[1,2]=OC_C6S2*x[1,2]>>16
1149         PKHBT   r3, r3, r12,LSL #16     ; r3 = <t[1,3]|t[0,3]>
1150         SMULWB  r12,r11,r10             ; r12= t[0,0]=OC_C4S4*x[0,0]>>16
1151         PKHBT   r2, r2, r5, LSL #16     ; r2 = <t[1,2]|t[0,2]>
1152         SMULWB  r5, r11,r4              ; r5 = t[1,0]=OC_C4S4*x[1,0]>>16
1153         LDRD    r6, OC_C7S1_4_v6        ; r6 = OC_C7S1; r7 = OC_C1S7
1154         PKHBT   r12,r12,r5, LSL #16     ; r12= <t[1,0]|t[0,0]>
1155         SMULWT  r5, r7, r4              ; r5 = t[1,7]=OC_C1S7*x[1,1]>>16
1156         SMULWT  r7, r7, r10             ; r7 = t[0,7]=OC_C1S7*x[0,1]>>16
1157         SMULWT  r10,r6, r10             ; r10= t[0,4]=OC_C7S1*x[0,1]>>16
1158         PKHBT   r7, r7, r5, LSL #16     ; r7 = <t[1,7]|t[0,7]>
1159         SMULWT  r4, r6, r4              ; r4 = t[1,4]=OC_C7S1*x[1,1]>>16
1160 ; Stage 2:
1161         SSUB16  r6, r7, r9              ; r6 = t[7]-t[6]
1162         PKHBT   r4, r10,r4, LSL #16     ; r4 = <t[1,4]|t[0,4]>
1163         SADD16  r7, r7, r9              ; r7 = t[7]=t[7]+t[6]
1164         SMULWT  r9, r11,r6              ; r9 = t[1,6]=OC_C4S4*r6T>>16
1165         SADD16  r5, r4, r8              ; r5 = t[4]-t[5]
1166         SMULWB  r6, r11,r6              ; r6 = t[0,6]=OC_C4S4*r6B>>16
1167         SSUB16  r4, r4, r8              ; r4 = t[4]=t[4]+t[5]
1168         SMULWT  r10,r11,r5              ; r10= t[1,5]=OC_C4S4*r5T>>16
1169         PKHBT   r6, r6, r9, LSL #16     ; r6 = <t[1,6]|t[0,6]>
1170         SMULWB  r5, r11,r5              ; r5 = t[0,5]=OC_C4S4*r5B>>16
1171 ; Stage 3:
1172 idct4_3core_stage3_v6
1173         SADD16  r11,r12,r2              ; r11= t[1]=t[0]+t[2]
1174         PKHBT   r10,r5, r10,LSL #16     ; r10= <t[1,5]|t[0,5]>
1175         SSUB16  r2, r12,r2              ; r2 = t[2]=t[0]-t[2]
1176 idct4_3core_stage3_5_v6
1177         SSUB16  r5, r6, r10             ; r5 = t[5]'=t[6]-t[5]
1178         SADD16  r6, r6, r10             ; r6 = t[6]=t[6]+t[5]
1179         SADD16  r10,r12,r3              ; r10= t[0]'=t[0]+t[3]
1180         SSUB16  r3, r12,r3              ; r3 = t[3]=t[0]-t[3]
1181 ; Stage 4:
1182         SADD16  r12,r10,r7              ; r12= t[0]+t[7]
1183         STR     r12,[r0], #4            ; y[0<<3] = t[0]+t[7]
1184         SADD16  r12,r11,r6              ; r12= t[1]+t[6]
1185         STR     r12,[r0, #12]           ; y[1<<3] = t[1]+t[6]
1186         SADD16  r12,r2, r5              ; r12= t[2]+t[5]
1187         STR     r12,[r0, #28]           ; y[2<<3] = t[2]+t[5]
1188         SADD16  r12,r3, r4              ; r12= t[3]+t[4]
1189         STR     r12,[r0, #44]           ; y[3<<3] = t[3]+t[4]
1190         SSUB16  r4, r3, r4              ; r4 = t[3]-t[4]
1191         STR     r4, [r0, #60]           ; y[4<<3] = t[3]-t[4]
1192         SSUB16  r5, r2, r5              ; r5 = t[2]-t[5]
1193         STR     r5, [r0, #76]           ; y[5<<3] = t[2]-t[5]
1194         SSUB16  r6, r11,r6              ; r6 = t[1]-t[6]
1195         STR     r6, [r0, #92]           ; y[6<<3] = t[1]-t[6]
1196         SSUB16  r7, r10,r7              ; r7 = t[0]-t[7]
1197         STR     r7, [r0, #108]          ; y[7<<3] = t[0]-t[7]
1198         MOV     PC,r14
1199
1200 ; Another copy so the LDRD offsets are less than +/- 255.
1201         ALIGN 8
1202 OC_C7S1_4_v6
1203         DCD     12785 ; 31F1
1204 OC_C1S7_4_v6
1205         DCD     64277 ; FB15
1206 OC_C6S2_4_v6
1207         DCD     25080 ; 61F8
1208 OC_C2S6_4_v6
1209         DCD     60547 ; EC83
1210 OC_C5S3_4_v6
1211         DCD     36410 ; 8E3A
1212 OC_C3S5_4_v6
1213         DCD     54491 ; D4DB
1214
1215 idct4_4core_down_v6
1216         ; r0 =       ogg_int16_t *_y (destination)
1217         ; r1 = const ogg_int16_t *_x (source)
1218 ; Stage 1:
1219         LDRD    r10,[r1], #16   ; r10= <x[0,1]|x[0,0]>; r11= <x[0,3]|x[0,2]>
1220         LDRD    r2, OC_C5S3_4_v6        ; r2 = OC_C5S3; r3 = OC_C3S5
1221         LDRD    r4, [r1], #16   ; r4 = <x[1,1]|x[1,0]>; r5 = <x[1,3]|x[1,2]>
1222         SMULWT  r9, r3, r11             ; r9 = t[0,6]=OC_C3S5*x[0,3]>>16
1223         LDRD    r6, OC_C6S2_4_v6        ; r6 = OC_C6S2; r7 = OC_C2S6
1224         SMULWT  r8, r2, r11             ; r8 = -t[0,5]=OC_C5S3*x[0,3]>>16
1225 ; Here we cheat: row 3 had just a DC, so x[0,3]==x[1,3] by definition.
1226         PKHBT   r9, r9, r9, LSL #16     ; r9 = <t[0,6]|t[0,6]>
1227         SMULWB  r3, r7, r11             ; r3 = t[0,3]=OC_C2S6*x[0,2]>>16
1228         PKHBT   r8, r8, r8, LSL #16     ; r8 = <-t[0,5]|-t[0,5]>
1229         SMULWB  r2, r6, r11             ; r2 = t[0,2]=OC_C6S2*x[0,2]>>16
1230         LDR     r11,OC_C4S4
1231         SMULWB  r12,r7, r5              ; r12= t[1,3]=OC_C2S6*x[1,2]>>16
1232         MOV     r7,#8
1233         SMULWB  r5, r6, r5              ; r5 = t[1,2]=OC_C6S2*x[1,2]>>16
1234         PKHBT   r3, r3, r12,LSL #16     ; r3 = <t[1,3]|t[0,3]>
1235         SMLAWB  r12,r11,r10,r7          ; r12= t[0,0]+8=(OC_C4S4*x[0,0]>>16)+8
1236         PKHBT   r2, r2, r5, LSL #16     ; r2 = <t[1,2]|t[0,2]>
1237         SMLAWB  r5, r11,r4 ,r7          ; r5 = t[1,0]+8=(OC_C4S4*x[1,0]>>16)+8
1238         LDRD    r6, OC_C7S1_4_v6        ; r6 = OC_C7S1; r7 = OC_C1S7
1239         PKHBT   r12,r12,r5, LSL #16     ; r12= <t[1,0]+8|t[0,0]+8>
1240         SMULWT  r5, r7, r4              ; r5 = t[1,7]=OC_C1S7*x[1,1]>>16
1241         SMULWT  r7, r7, r10             ; r7 = t[0,7]=OC_C1S7*x[0,1]>>16
1242         SMULWT  r10,r6, r10             ; r10= t[0,4]=OC_C7S1*x[0,1]>>16
1243         PKHBT   r7, r7, r5, LSL #16     ; r7 = <t[1,7]|t[0,7]>
1244         SMULWT  r4, r6, r4              ; r4 = t[1,4]=OC_C7S1*x[1,1]>>16
1245 ; Stage 2:
1246         SSUB16  r6, r7, r9              ; r6 = t[7]-t[6]
1247         PKHBT   r4, r10,r4, LSL #16     ; r4 = <t[1,4]|t[0,4]>
1248         SADD16  r7, r7, r9              ; r7 = t[7]=t[7]+t[6]
1249         SMULWT  r9, r11,r6              ; r9 = t[1,6]=OC_C4S4*r6T>>16
1250         SADD16  r5, r4, r8              ; r5 = t[4]-t[5]
1251         SMULWB  r6, r11,r6              ; r6 = t[0,6]=OC_C4S4*r6B>>16
1252         SSUB16  r4, r4, r8              ; r4 = t[4]=t[4]+t[5]
1253         SMULWT  r10,r11,r5              ; r10= t[1,5]=OC_C4S4*r5T>>16
1254         PKHBT   r6, r6, r9, LSL #16     ; r6 = <t[1,6]|t[0,6]>
1255         SMULWB  r5, r11,r5              ; r5 = t[0,5]=OC_C4S4*r5B>>16
1256 ; Stage 3:
1257 idct4_4core_down_stage3_v6
1258         SADD16  r11,r12,r2              ; r11= t[1]+8=t[0]+t[2]+8
1259         PKHBT   r10,r5, r10,LSL #16     ; r10= <t[1,5]|t[0,5]>
1260         SSUB16  r2, r12,r2              ; r2 = t[2]+8=t[0]-t[2]+8
1261         B       idct8_8core_down_stage3_5_v6
1262
1263 idct8_8core_v6
1264         STMFD   r13!,{r0,r14}
1265 ; Stage 1:
1266         ;5-6 rotation by 3pi/16
1267         LDRD    r10,OC_C5S3_4_v6        ; r10= OC_C5S3, r11= OC_C3S5
1268         LDR     r4, [r1,#8]             ; r4 = <x[0,5]|x[0,4]>
1269         LDR     r7, [r1,#24]            ; r7 = <x[1,5]|x[1,4]>
1270         SMULWT  r5, r11,r4              ; r5 = OC_C3S5*x[0,5]>>16
1271         LDR     r0, [r1,#4]             ; r0 = <x[0,3]|x[0,2]>
1272         SMULWT  r3, r11,r7              ; r3 = OC_C3S5*x[1,5]>>16
1273         LDR     r12,[r1,#20]            ; r12= <x[1,3]|x[1,2]>
1274         SMULWT  r6, r11,r0              ; r6 = OC_C3S5*x[0,3]>>16
1275         SMULWT  r11,r11,r12             ; r11= OC_C3S5*x[1,3]>>16
1276         SMLAWT  r6, r10,r4, r6          ; r6 = t[0,6]=r6+(OC_C5S3*x[0,5]>>16)
1277         PKHBT   r5, r5, r3, LSL #16     ; r5 = <r3|r5>
1278         SMLAWT  r11,r10,r7, r11         ; r11= t[1,6]=r11+(OC_C5S3*x[1,5]>>16)
1279         PKHBT   r4, r4, r7, LSL #16     ; r4 = <x[1,4]|x[0,4]>
1280         SMULWT  r3, r10,r0              ; r3 = OC_C5S3*x[0,3]>>16
1281         PKHBT   r6, r6, r11,LSL #16     ; r6 = <t[1,6]|t[0,6]>
1282         SMULWT  r8, r10,r12             ; r8 = OC_C5S3*x[1,3]>>16
1283         ;2-3 rotation by 6pi/16
1284         LDRD    r10,OC_C6S2_4_v6        ; r10= OC_C6S2, r11= OC_C2S6
1285         PKHBT   r3, r3, r8, LSL #16     ; r3 = <r8|r3>
1286         LDR     r8, [r1,#12]            ; r8 = <x[0,7]|x[0,6]>
1287         SMULWB  r2, r10,r0              ; r2 = OC_C6S2*x[0,2]>>16
1288         SSUB16  r5, r5, r3              ; r5 = <t[1,5]|t[0,5]>
1289         SMULWB  r9, r10,r12             ; r9 = OC_C6S2*x[1,2]>>16
1290         LDR     r7, [r1,#28]            ; r7 = <x[1,7]|x[1,6]>
1291         SMULWB  r3, r10,r8              ; r3 = OC_C6S2*x[0,6]>>16
1292         SMULWB  r10,r10,r7              ; r10= OC_C6S2*x[1,6]>>16
1293         PKHBT   r2, r2, r9, LSL #16     ; r2 = <r2|r9>
1294         SMLAWB  r3, r11,r0, r3          ; r3 = t[0,3]=r3+(OC_C2S6*x[0,2]>>16)
1295         SMLAWB  r10,r11,r12,r10         ; r10= t[1,3]=r10+(OC_C2S6*x[1,2]>>16)
1296         SMULWB  r9, r11,r8              ; r9 = OC_C2S6*x[0,6]>>16
1297         PKHBT   r3, r3, r10,LSL #16     ; r3 = <t[1,6]|t[0,6]>
1298         SMULWB  r12,r11,r7              ; r12= OC_C2S6*x[1,6]>>16
1299         ;4-7 rotation by 7pi/16
1300         LDRD    r10,OC_C7S1_8_v6        ; r10= OC_C7S1, r11= OC_C1S7
1301         PKHBT   r9, r9, r12,LSL #16     ; r9 = <r9|r12>
1302         LDR     r0, [r1],#16            ; r0 = <x[0,1]|x[0,0]>
1303         PKHTB   r7, r7, r8, ASR #16     ; r7 = <x[1,7]|x[0,7]>
1304         SSUB16  r2, r2, r9              ; r2 = <t[1,2]|t[0,2]>
1305         SMULWB  r9, r10,r7              ; r9 = OC_C7S1*x[0,7]>>16
1306         LDR     r14,[r1],#16            ; r14= <x[1,1]|x[1,0]>
1307         SMULWT  r12,r10,r7              ; r12= OC_C7S1*x[1,7]>>16
1308         SMULWT  r8, r10,r0              ; r8 = OC_C7S1*x[0,1]>>16
1309         SMULWT  r10,r10,r14             ; r10= OC_C7S1*x[1,1]>>16
1310         SMLAWT  r9, r11,r0, r9          ; r9 = t[0,7]=r9+(OC_C1S7*x[0,1]>>16)
1311         PKHBT   r8, r8, r10,LSL #16     ; r8 = <r12|r8>
1312         SMLAWT  r12,r11,r14,r12         ; r12= t[1,7]=r12+(OC_C1S7*x[1,1]>>16)
1313         PKHBT   r0, r0, r14,LSL #16     ; r0 = <x[1,0]|x[0,0]>
1314         SMULWB  r10,r11,r7              ; r10= OC_C1S7*x[0,6]>>16
1315         PKHBT   r9, r9, r12,LSL #16     ; r9 = <t[1,7]|t[0,7]>
1316         SMULWT  r12,r11,r7              ; r12= OC_C1S7*x[1,6]>>16
1317         ;0-1 butterfly
1318         LDR     r11,OC_C4S4
1319         PKHBT   r10,r10,r12,LSL #16     ; r10= <r12|r10>
1320         SADD16  r7, r0, r4              ; r7 = x[0]+x[4]
1321         SSUB16  r10,r8, r10             ; r10= <t[1,4]|t[0,4]>
1322         SSUB16  r4, r0, r4              ; r4 = x[0]-x[4]
1323         SMULWB  r8, r11,r7              ; r8 = t[0,0]=OC_C4S4*r7B>>16
1324         SMULWT  r12,r11,r7              ; r12= t[1,0]=OC_C4S4*r7T>>16
1325         SMULWB  r7, r11,r4              ; r7 = t[0,1]=OC_C4S4*r4B>>16
1326         PKHBT   r12,r8, r12,LSL #16     ; r12= <t[1,0]|t[0,0]>
1327         SMULWT  r8, r11,r4              ; r8 = t[1,1]=OC_C4S4*r4T>>16
1328 ; Stage 2:
1329         SADD16  r4, r10,r5              ; r4 = t[4]'=t[4]+t[5]
1330         PKHBT   r8, r7, r8, LSL #16     ; r8 = <t[1,0]|t[0,0]>
1331         SSUB16  r5, r10,r5              ; r5 = t[4]-t[5]
1332         SMULWB  r10,r11,r5              ; r10= t[0,5]=OC_C4S4*r5B>>16
1333         SADD16  r7, r9, r6              ; r7 = t[7]'=t[7]+t[6]
1334         SMULWT  r5, r11,r5              ; r5 = t[1,5]=OC_C4S4*r5T>>16
1335         SSUB16  r6, r9, r6              ; r6 = t[7]-t[6]
1336         SMULWB  r9, r11,r6              ; r9 = t[0,6]=OC_C4S4*r6B>>16
1337         PKHBT   r10,r10,r5, LSL #16     ; r10= <t[1,5]|t[0,5]>
1338         SMULWT  r6, r11,r6              ; r6 = t[1,6]=OC_C4S4*r6T>>16
1339 ; Stage 3:
1340         SADD16  r11,r8, r2              ; r11= t[1]'=t[1]+t[2]
1341         PKHBT   r6, r9, r6, LSL #16     ; r6 = <t[1,6]|t[0,6]>
1342         SSUB16  r2, r8, r2              ; r2 = t[2]=t[1]-t[2]
1343         LDMFD   r13!,{r0,r14}
1344         B       idct4_3core_stage3_5_v6
1345
1346 ; Another copy so the LDRD offsets are less than +/- 255.
1347         ALIGN 8
1348 OC_C7S1_8_v6
1349         DCD     12785 ; 31F1
1350 OC_C1S7_8_v6
1351         DCD     64277 ; FB15
1352 OC_C6S2_8_v6
1353         DCD     25080 ; 61F8
1354 OC_C2S6_8_v6
1355         DCD     60547 ; EC83
1356 OC_C5S3_8_v6
1357         DCD     36410 ; 8E3A
1358 OC_C3S5_8_v6
1359         DCD     54491 ; D4DB
1360
1361 idct8_8core_down_v6
1362         STMFD   r13!,{r0,r14}
1363 ; Stage 1:
1364         ;5-6 rotation by 3pi/16
1365         LDRD    r10,OC_C5S3_8_v6        ; r10= OC_C5S3, r11= OC_C3S5
1366         LDR     r4, [r1,#8]             ; r4 = <x[0,5]|x[0,4]>
1367         LDR     r7, [r1,#24]            ; r7 = <x[1,5]|x[1,4]>
1368         SMULWT  r5, r11,r4              ; r5 = OC_C3S5*x[0,5]>>16
1369         LDR     r0, [r1,#4]             ; r0 = <x[0,3]|x[0,2]>
1370         SMULWT  r3, r11,r7              ; r3 = OC_C3S5*x[1,5]>>16
1371         LDR     r12,[r1,#20]            ; r12= <x[1,3]|x[1,2]>
1372         SMULWT  r6, r11,r0              ; r6 = OC_C3S5*x[0,3]>>16
1373         SMULWT  r11,r11,r12             ; r11= OC_C3S5*x[1,3]>>16
1374         SMLAWT  r6, r10,r4, r6          ; r6 = t[0,6]=r6+(OC_C5S3*x[0,5]>>16)
1375         PKHBT   r5, r5, r3, LSL #16     ; r5 = <r3|r5>
1376         SMLAWT  r11,r10,r7, r11         ; r11= t[1,6]=r11+(OC_C5S3*x[1,5]>>16)
1377         PKHBT   r4, r4, r7, LSL #16     ; r4 = <x[1,4]|x[0,4]>
1378         SMULWT  r3, r10,r0              ; r3 = OC_C5S3*x[0,3]>>16
1379         PKHBT   r6, r6, r11,LSL #16     ; r6 = <t[1,6]|t[0,6]>
1380         SMULWT  r8, r10,r12             ; r8 = OC_C5S3*x[1,3]>>16
1381         ;2-3 rotation by 6pi/16
1382         LDRD    r10,OC_C6S2_8_v6        ; r10= OC_C6S2, r11= OC_C2S6
1383         PKHBT   r3, r3, r8, LSL #16     ; r3 = <r8|r3>
1384         LDR     r8, [r1,#12]            ; r8 = <x[0,7]|x[0,6]>
1385         SMULWB  r2, r10,r0              ; r2 = OC_C6S2*x[0,2]>>16
1386         SSUB16  r5, r5, r3              ; r5 = <t[1,5]|t[0,5]>
1387         SMULWB  r9, r10,r12             ; r9 = OC_C6S2*x[1,2]>>16
1388         LDR     r7, [r1,#28]            ; r7 = <x[1,7]|x[1,6]>
1389         SMULWB  r3, r10,r8              ; r3 = OC_C6S2*x[0,6]>>16
1390         SMULWB  r10,r10,r7              ; r10= OC_C6S2*x[1,6]>>16
1391         PKHBT   r2, r2, r9, LSL #16     ; r2 = <r2|r9>
1392         SMLAWB  r3, r11,r0, r3          ; r3 = t[0,3]=r3+(OC_C2S6*x[0,2]>>16)
1393         SMLAWB  r10,r11,r12,r10         ; r10= t[1,3]=r10+(OC_C2S6*x[1,2]>>16)
1394         SMULWB  r9, r11,r8              ; r9 = OC_C2S6*x[0,6]>>16
1395         PKHBT   r3, r3, r10,LSL #16     ; r3 = <t[1,6]|t[0,6]>
1396         SMULWB  r12,r11,r7              ; r12= OC_C2S6*x[1,6]>>16
1397         ;4-7 rotation by 7pi/16
1398         LDRD    r10,OC_C7S1_8_v6        ; r10= OC_C7S1, r11= OC_C1S7
1399         PKHBT   r9, r9, r12,LSL #16     ; r9 = <r9|r12>
1400         LDR     r0, [r1],#16            ; r0 = <x[0,1]|x[0,0]>
1401         PKHTB   r7, r7, r8, ASR #16     ; r7 = <x[1,7]|x[0,7]>
1402         SSUB16  r2, r2, r9              ; r2 = <t[1,2]|t[0,2]>
1403         SMULWB  r9, r10,r7              ; r9 = OC_C7S1*x[0,7]>>16
1404         LDR     r14,[r1],#16            ; r14= <x[1,1]|x[1,0]>
1405         SMULWT  r12,r10,r7              ; r12= OC_C7S1*x[1,7]>>16
1406         SMULWT  r8, r10,r0              ; r8 = OC_C7S1*x[0,1]>>16
1407         SMULWT  r10,r10,r14             ; r10= OC_C7S1*x[1,1]>>16
1408         SMLAWT  r9, r11,r0, r9          ; r9 = t[0,7]=r9+(OC_C1S7*x[0,1]>>16)
1409         PKHBT   r8, r8, r10,LSL #16     ; r8 = <r12|r8>
1410         SMLAWT  r12,r11,r14,r12         ; r12= t[1,7]=r12+(OC_C1S7*x[1,1]>>16)
1411         PKHBT   r0, r0, r14,LSL #16     ; r0 = <x[1,0]|x[0,0]>
1412         SMULWB  r10,r11,r7              ; r10= OC_C1S7*x[0,6]>>16
1413         PKHBT   r9, r9, r12,LSL #16     ; r9 = <t[1,7]|t[0,7]>
1414         SMULWT  r12,r11,r7              ; r12= OC_C1S7*x[1,6]>>16
1415         ;0-1 butterfly
1416         LDR     r11,OC_C4S4
1417         MOV     r14,#8
1418         PKHBT   r10,r10,r12,LSL #16     ; r10= <r12|r10>
1419         SADD16  r7, r0, r4              ; r7 = x[0]+x[4]
1420         SSUB16  r10,r8, r10             ; r10= <t[1,4]|t[0,4]>
1421         SMLAWB  r8, r11,r7, r14         ; r8 = t[0,0]+8=(OC_C4S4*r7B>>16)+8
1422         SSUB16  r4, r0, r4              ; r4 = x[0]-x[4]
1423         SMLAWT  r12,r11,r7, r14         ; r12= t[1,0]+8=(OC_C4S4*r7T>>16)+8
1424         SMLAWB  r7, r11,r4, r14         ; r7 = t[0,1]+8=(OC_C4S4*r4B>>16)+8
1425         PKHBT   r12,r8, r12,LSL #16     ; r12= <t[1,0]+8|t[0,0]+8>
1426         SMLAWT  r8, r11,r4, r14         ; r8 = t[1,1]+8=(OC_C4S4*r4T>>16)+8
1427 ; Stage 2:
1428         SADD16  r4, r10,r5              ; r4 = t[4]'=t[4]+t[5]
1429         PKHBT   r8, r7, r8, LSL #16     ; r8 = <t[1,0]+8|t[0,0]+8>
1430         SSUB16  r5, r10,r5              ; r5 = t[4]-t[5]
1431         SMULWB  r10,r11,r5              ; r10= t[0,5]=OC_C4S4*r5B>>16
1432         SADD16  r7, r9, r6              ; r7 = t[7]'=t[7]+t[6]
1433         SMULWT  r5, r11,r5              ; r5 = t[1,5]=OC_C4S4*r5T>>16
1434         SSUB16  r6, r9, r6              ; r6 = t[7]-t[6]
1435         SMULWB  r9, r11,r6              ; r9 = t[0,6]=OC_C4S4*r6B>>16
1436         PKHBT   r10,r10,r5, LSL #16     ; r10= <t[1,5]|t[0,5]>
1437         SMULWT  r6, r11,r6              ; r6 = t[1,6]=OC_C4S4*r6T>>16
1438 ; Stage 3:
1439         SADD16  r11,r8, r2              ; r11= t[1]'+8=t[1]+t[2]+8
1440         PKHBT   r6, r9, r6, LSL #16     ; r6 = <t[1,6]|t[0,6]>
1441         SSUB16  r2, r8, r2              ; r2 = t[2]+8=t[1]-t[2]+8
1442         LDMFD   r13!,{r0,r14}
1443 idct8_8core_down_stage3_5_v6
1444         SSUB16  r5, r6, r10             ; r5 = t[5]'=t[6]-t[5]
1445         SADD16  r6, r6, r10             ; r6 = t[6]=t[6]+t[5]
1446         SADD16  r10,r12,r3              ; r10= t[0]'+8=t[0]+t[3]+8
1447         SSUB16  r3, r12,r3              ; r3 = t[3]+8=t[0]-t[3]+8
1448 ; Stage 4:
1449         SADD16  r12,r10,r7              ; r12= t[0]+t[7]+8
1450         SSUB16  r7, r10,r7              ; r7 = t[0]-t[7]+8
1451         MOV     r10,r12,ASR #4
1452         MOV     r12,r12,LSL #16
1453         PKHTB   r10,r10,r12,ASR #20     ; r10= t[0]+t[7]+8>>4
1454         STR     r10,[r0], #4            ; y[0<<3] = t[0]+t[7]+8>>4
1455         SADD16  r12,r11,r6              ; r12= t[1]+t[6]+8
1456         SSUB16  r6, r11,r6              ; r6 = t[1]-t[6]+8
1457         MOV     r10,r12,ASR #4
1458         MOV     r12,r12,LSL #16
1459         PKHTB   r10,r10,r12,ASR #20     ; r10= t[1]+t[6]+8>>4
1460         STR     r10,[r0, #12]           ; y[1<<3] = t[1]+t[6]+8>>4
1461         SADD16  r12,r2, r5              ; r12= t[2]+t[5]+8
1462         SSUB16  r5, r2, r5              ; r5 = t[2]-t[5]+8
1463         MOV     r10,r12,ASR #4
1464         MOV     r12,r12,LSL #16
1465         PKHTB   r10,r10,r12,ASR #20     ; r10= t[2]+t[5]+8>>4
1466         STR     r10,[r0, #28]           ; y[2<<3] = t[2]+t[5]+8>>4
1467         SADD16  r12,r3, r4              ; r12= t[3]+t[4]+8
1468         SSUB16  r4, r3, r4              ; r4 = t[3]-t[4]+8
1469         MOV     r10,r12,ASR #4
1470         MOV     r12,r12,LSL #16
1471         PKHTB   r10,r10,r12,ASR #20     ; r10= t[3]+t[4]+8>>4
1472         STR     r10,[r0, #44]           ; y[3<<3] = t[3]+t[4]+8>>4
1473         MOV     r10,r4, ASR #4
1474         MOV     r4, r4, LSL #16
1475         PKHTB   r10,r10,r4, ASR #20     ; r10= t[3]-t[4]+8>>4
1476         STR     r10,[r0, #60]           ; y[4<<3] = t[3]-t[4]+8>>4
1477         MOV     r10,r5, ASR #4
1478         MOV     r5, r5, LSL #16
1479         PKHTB   r10,r10,r5, ASR #20     ; r10= t[2]-t[5]+8>>4
1480         STR     r10,[r0, #76]           ; y[5<<3] = t[2]-t[5]+8>>4
1481         MOV     r10,r6, ASR #4
1482         MOV     r6, r6, LSL #16
1483         PKHTB   r10,r10,r6, ASR #20     ; r10= t[1]-t[6]+8>>4
1484         STR     r10,[r0, #92]           ; y[6<<3] = t[1]-t[6]+8>>4
1485         MOV     r10,r7, ASR #4
1486         MOV     r7, r7, LSL #16
1487         PKHTB   r10,r10,r7, ASR #20     ; r10= t[0]-t[7]+8>>4
1488         STR     r10,[r0, #108]          ; y[7<<3] = t[0]-t[7]+8>>4
1489         MOV     PC,r14
1490  ]
1491
1492  [ OC_ARM_ASM_NEON
1493         EXPORT  oc_idct8x8_1_neon
1494         EXPORT  oc_idct8x8_neon
1495
1496         ALIGN 16
1497 OC_IDCT_CONSTS_NEON
1498         DCW         8
1499         DCW     64277 ; FB15 (C1S7)
1500         DCW     60547 ; EC83 (C2S6)
1501         DCW     54491 ; D4DB (C3S5)
1502         DCW     46341 ; B505 (C4S4)
1503         DCW     36410 ; 471D (C5S3)
1504         DCW     25080 ; 30FC (C6S2)
1505         DCW     12785 ; 31F1 (C7S1)
1506
1507 oc_idct8x8_1_neon
1508         ; r0 = ogg_int16_t  *_y
1509         ; r1 = ogg_uint16_t  _dc
1510         VDUP.S16        Q0, r1
1511         VMOV            Q1, Q0
1512         VST1.64         {D0, D1, D2, D3}, [r0@128]!
1513         VST1.64         {D0, D1, D2, D3}, [r0@128]!
1514         VST1.64         {D0, D1, D2, D3}, [r0@128]!
1515         VST1.64         {D0, D1, D2, D3}, [r0@128]
1516         MOV     PC, r14
1517
1518 oc_idct8x8_neon
1519         ; r0 = ogg_int16_t *_y
1520         ; r1 = ogg_int16_t *_x
1521         ; r2 = int          _last_zzi
1522         CMP     r2, #10
1523         BLE     oc_idct8x8_10_neon
1524 oc_idct8x8_slow_neon
1525         VPUSH           {D8-D15}
1526         MOV     r2, r1
1527         ADR     r3, OC_IDCT_CONSTS_NEON
1528         ; Row transforms (input is pre-transposed)
1529         VLD1.64         {D16,D17,D18,D19}, [r2@128]!
1530         VLD1.64         {D20,D21,D22,D23}, [r2@128]!
1531         VLD1.64         {D24,D25,D26,D27}, [r2@128]!
1532         VSUB.S16        Q1, Q8, Q12     ; Q8 = x[0]-x[4]
1533         VLD1.64         {D28,D29,D30,D31}, [r2@128]
1534         VADD.S16        Q8, Q8, Q12     ; Q1 = x[0]+x[4]
1535         VLD1.64         {D0,D1},           [r3@128]
1536         MOV     r12, r14
1537         BL      oc_idct8x8_stage123_neon
1538 ; Stage 4
1539         VSUB.S16        Q15,Q8, Q7      ; Q15 = y[7]=t[0]'-t[7]'
1540         VADD.S16        Q8, Q8, Q7      ; Q8  = y[0]=t[0]'+t[7]'
1541         VSUB.S16        Q14,Q9, Q3      ; Q14 = y[6]=t[1]'-t[6]''
1542         VADD.S16        Q9, Q9, Q3      ; Q9  = y[1]=t[1]'+t[6]''
1543         VSUB.S16        Q13,Q10,Q5      ; Q13 = y[5]=t[2]'-t[5]''
1544         VADD.S16        Q10,Q10,Q5      ; Q10 = y[2]=t[2]'+t[5]''
1545         VTRN.16         Q14,Q15
1546         VSUB.S16        Q12,Q11,Q4      ; Q12 = y[4]=t[3]'-t[4]'
1547         VADD.S16        Q11,Q11,Q4      ; Q11 = y[3]=t[3]'+t[4]'
1548         ; 8x8 Transpose
1549         VTRN.16         Q8, Q9
1550         VTRN.16         Q10,Q11
1551         VTRN.16         Q12,Q13
1552         VTRN.32         Q8, Q10
1553         VTRN.32         Q9, Q11
1554         VTRN.32         Q12,Q14
1555         VTRN.32         Q13,Q15
1556         VSWP            D17,D24
1557         VSUB.S16        Q1, Q8, Q12     ; Q8 = x[0]-x[4]
1558         VSWP            D19,D26
1559         VADD.S16        Q8, Q8, Q12     ; Q1 = x[0]+x[4]
1560         VSWP            D21,D28
1561         VSWP            D23,D30
1562         ; Column transforms
1563         BL      oc_idct8x8_stage123_neon
1564         CMP     r0,r1
1565         ; We have to put the return address back in the LR, or the branch
1566         ;  predictor will not recognize the function return and mis-predict the
1567         ;  entire call stack.
1568         MOV     r14, r12
1569 ; Stage 4
1570         VSUB.S16        Q15,Q8, Q7      ; Q15 = y[7]=t[0]'-t[7]'
1571         VADD.S16        Q8, Q8, Q7      ; Q8  = y[0]=t[0]'+t[7]'
1572         VSUB.S16        Q14,Q9, Q3      ; Q14 = y[6]=t[1]'-t[6]''
1573         VADD.S16        Q9, Q9, Q3      ; Q9  = y[1]=t[1]'+t[6]''
1574         VSUB.S16        Q13,Q10,Q5      ; Q13 = y[5]=t[2]'-t[5]''
1575         VADD.S16        Q10,Q10,Q5      ; Q10 = y[2]=t[2]'+t[5]''
1576         VSUB.S16        Q12,Q11,Q4      ; Q12 = y[4]=t[3]'-t[4]'
1577         VADD.S16        Q11,Q11,Q4      ; Q11 = y[3]=t[3]'+t[4]'
1578         BEQ             oc_idct8x8_slow_neon_noclear
1579         VMOV.I8         Q2,#0
1580         VPOP            {D8-D15}
1581         VMOV.I8         Q3,#0
1582         VRSHR.S16       Q8, Q8, #4      ; Q8  = y[0]+8>>4
1583         VST1.64         {D4, D5, D6, D7}, [r1@128]!
1584         VRSHR.S16       Q9, Q9, #4      ; Q9  = y[1]+8>>4
1585         VRSHR.S16       Q10,Q10,#4      ; Q10 = y[2]+8>>4
1586         VST1.64         {D4, D5, D6, D7}, [r1@128]!
1587         VRSHR.S16       Q11,Q11,#4      ; Q11 = y[3]+8>>4
1588         VRSHR.S16       Q12,Q12,#4      ; Q12 = y[4]+8>>4
1589         VST1.64         {D4, D5, D6, D7}, [r1@128]!
1590         VRSHR.S16       Q13,Q13,#4      ; Q13 = y[5]+8>>4
1591         VRSHR.S16       Q14,Q14,#4      ; Q14 = y[6]+8>>4
1592         VST1.64         {D4, D5, D6, D7}, [r1@128]
1593         VRSHR.S16       Q15,Q15,#4      ; Q15 = y[7]+8>>4
1594         VSTMIA          r0, {D16-D31}
1595         MOV     PC, r14
1596
1597 oc_idct8x8_slow_neon_noclear
1598         VPOP            {D8-D15}
1599         VRSHR.S16       Q8, Q8, #4      ; Q8  = y[0]+8>>4
1600         VRSHR.S16       Q9, Q9, #4      ; Q9  = y[1]+8>>4
1601         VRSHR.S16       Q10,Q10,#4      ; Q10 = y[2]+8>>4
1602         VRSHR.S16       Q11,Q11,#4      ; Q11 = y[3]+8>>4
1603         VRSHR.S16       Q12,Q12,#4      ; Q12 = y[4]+8>>4
1604         VRSHR.S16       Q13,Q13,#4      ; Q13 = y[5]+8>>4
1605         VRSHR.S16       Q14,Q14,#4      ; Q14 = y[6]+8>>4
1606         VRSHR.S16       Q15,Q15,#4      ; Q15 = y[7]+8>>4
1607         VSTMIA          r0, {D16-D31}
1608         MOV     PC, r14
1609
1610 oc_idct8x8_stage123_neon
1611 ; Stages 1 & 2
1612         VMULL.S16       Q4, D18,D1[3]
1613         VMULL.S16       Q5, D19,D1[3]
1614         VMULL.S16       Q7, D30,D1[3]
1615         VMULL.S16       Q6, D31,D1[3]
1616         VMULL.S16       Q2, D30,D0[1]
1617         VMULL.S16       Q3, D31,D0[1]
1618         VSHRN.S32       D8, Q4, #16
1619         VSHRN.S32       D9, Q5, #16     ; Q4 = (OC_C7S1*x[1]>>16)
1620         VSHRN.S32       D14,Q7, #16
1621         VSHRN.S32       D15,Q6, #16     ; Q7 = (OC_C7S1*x[7]>>16)
1622         VSHRN.S32       D4, Q2, #16
1623         VSHRN.S32       D5, Q3, #16     ; Q2 = (OC_C1S7*x[7]>>16)-x[7]
1624         VSUB.S16        Q4, Q4, Q15
1625         VADD.S16        Q7, Q7, Q9
1626         VSUB.S16        Q4, Q4, Q2      ; Q4 = t[4]
1627         VMULL.S16       Q2, D18,D0[1]
1628         VMULL.S16       Q9, D19,D0[1]
1629         VMULL.S16       Q5, D26,D0[3]
1630         VMULL.S16       Q3, D27,D0[3]
1631         VMULL.S16       Q6, D22,D0[3]
1632         VMULL.S16       Q12,D23,D0[3]
1633         VSHRN.S32       D4, Q2, #16
1634         VSHRN.S32       D5, Q9, #16     ; Q2 = (OC_C1S7*x[1]>>16)-x[1]
1635         VSHRN.S32       D10,Q5, #16
1636         VSHRN.S32       D11,Q3, #16     ; Q5 = (OC_C3S5*x[5]>>16)-x[5]
1637         VSHRN.S32       D12,Q6, #16
1638         VSHRN.S32       D13,Q12,#16     ; Q6 = (OC_C3S5*x[3]>>16)-x[3]
1639         VADD.S16        Q7, Q7, Q2      ; Q7 = t[7]
1640         VSUB.S16        Q5, Q5, Q11
1641         VADD.S16        Q6, Q6, Q11
1642         VADD.S16        Q5, Q5, Q13
1643         VADD.S16        Q6, Q6, Q13
1644         VMULL.S16       Q9, D22,D1[1]
1645         VMULL.S16       Q11,D23,D1[1]
1646         VMULL.S16       Q15,D26,D1[1]
1647         VMULL.S16       Q13,D27,D1[1]
1648         VMULL.S16       Q2, D20,D1[2]
1649         VMULL.S16       Q12,D21,D1[2]
1650         VSHRN.S32       D18,Q9, #16
1651         VSHRN.S32       D19,Q11,#16     ; Q9 = (OC_C5S3*x[3]>>16)-x[3]
1652         VSHRN.S32       D30,Q15,#16
1653         VSHRN.S32       D31,Q13,#16     ; Q15= (OC_C5S3*x[5]>>16)-x[5]
1654         VSHRN.S32       D4, Q2, #16
1655         VSHRN.S32       D5, Q12,#16     ; Q2 = (OC_C6S2*x[2]>>16)
1656         VSUB.S16        Q5, Q5, Q9      ; Q5 = t[5]
1657         VADD.S16        Q6, Q6, Q15     ; Q6 = t[6]
1658         VSUB.S16        Q2, Q2, Q14
1659         VMULL.S16       Q3, D28,D1[2]
1660         VMULL.S16       Q11,D29,D1[2]
1661         VMULL.S16       Q12,D28,D0[2]
1662         VMULL.S16       Q9, D29,D0[2]
1663         VMULL.S16       Q13,D20,D0[2]
1664         VMULL.S16       Q15,D21,D0[2]
1665         VSHRN.S32       D6, Q3, #16
1666         VSHRN.S32       D7, Q11,#16     ; Q3 = (OC_C6S2*x[6]>>16)
1667         VSHRN.S32       D24,Q12,#16
1668         VSHRN.S32       D25,Q9, #16     ; Q12= (OC_C2S6*x[6]>>16)-x[6]
1669         VSHRN.S32       D26,Q13,#16
1670         VSHRN.S32       D27,Q15,#16     ; Q13= (OC_C2S6*x[2]>>16)-x[2]
1671         VSUB.S16        Q9, Q4, Q5      ; Q9 = t[4]-t[5]
1672         VSUB.S16        Q11,Q7, Q6      ; Q11= t[7]-t[6]
1673         VADD.S16        Q3, Q3, Q10
1674         VADD.S16        Q4, Q4, Q5      ; Q4 = t[4]'=t[4]+t[5]
1675         VADD.S16        Q7, Q7, Q6      ; Q7 = t[7]'=t[7]+t[6]
1676         VSUB.S16        Q2, Q2, Q12     ; Q2 = t[2]
1677         VADD.S16        Q3, Q3, Q13     ; Q3 = t[3]
1678         VMULL.S16       Q12,D16,D1[0]
1679         VMULL.S16       Q13,D17,D1[0]
1680         VMULL.S16       Q14,D2, D1[0]
1681         VMULL.S16       Q15,D3, D1[0]
1682         VMULL.S16       Q5, D18,D1[0]
1683         VMULL.S16       Q6, D22,D1[0]
1684         VSHRN.S32       D24,Q12,#16
1685         VSHRN.S32       D25,Q13,#16
1686         VSHRN.S32       D28,Q14,#16
1687         VSHRN.S32       D29,Q15,#16
1688         VMULL.S16       Q13,D19,D1[0]
1689         VMULL.S16       Q15,D23,D1[0]
1690         VADD.S16        Q8, Q8, Q12     ; Q8 = t[0]
1691         VADD.S16        Q1, Q1, Q14     ; Q1 = t[1]
1692         VSHRN.S32       D10,Q5, #16
1693         VSHRN.S32       D12,Q6, #16
1694         VSHRN.S32       D11,Q13,#16
1695         VSHRN.S32       D13,Q15,#16
1696         VADD.S16        Q5, Q5, Q9      ; Q5 = t[5]'=OC_C4S4*(t[4]-t[5])>>16
1697         VADD.S16        Q6, Q6, Q11     ; Q6 = t[6]'=OC_C4S4*(t[7]-t[6])>>16
1698 ; Stage 3
1699         VSUB.S16        Q11,Q8, Q3      ; Q11 = t[3]''=t[0]-t[3]
1700         VADD.S16        Q8, Q8, Q3      ; Q8  = t[0]''=t[0]+t[3]
1701         VADD.S16        Q9, Q1, Q2      ; Q9  = t[1]''=t[1]+t[2]
1702         VADD.S16        Q3, Q6, Q5      ; Q3  = t[6]''=t[6]'+t[5]'
1703         VSUB.S16        Q10,Q1, Q2      ; Q10 = t[2]''=t[1]-t[2]
1704         VSUB.S16        Q5, Q6, Q5      ; Q5  = t[5]''=t[6]'-t[5]'
1705         MOV     PC, r14
1706
1707 oc_idct8x8_10_neon
1708         ADR     r3, OC_IDCT_CONSTS_NEON
1709         VLD1.64         {D0,D1},          [r3@128]
1710         MOV     r2, r1
1711         ; Row transforms (input is pre-transposed)
1712 ; Stage 1
1713         VLD1.64         {D16,D17,D18,D19},[r2@128]!
1714         MOV     r12, #16
1715         VMULL.S16       Q15,D16,D1[0]   ; Q15= OC_C4S4*x[0]-(x[0]<<16)
1716         VLD1.64         {D17},            [r2@64], r12
1717         VMULL.S16       Q2, D18,D0[1]   ; Q2 = OC_C1S7*x[1]-(x[1]<<16)
1718         VLD1.64         {D19},            [r2@64]
1719         VMULL.S16       Q14,D17,D0[2]   ; Q14= OC_C2S6*x[2]-(x[2]<<16)
1720         VMULL.S16       Q3, D19,D0[3]   ; Q3 = OC_C3S5*x[3]-(x[3]<<16)
1721         VMULL.S16       Q13,D19,D1[1]   ; Q13= OC_C5S3*x[3]-(x[3]<<16)
1722         VMULL.S16       Q12,D18,D1[3]   ; Q12= OC_C7S1*x[1]
1723         VMULL.S16       Q1, D17,D1[2]   ; Q1 = OC_C6S2*x[2]
1724         VSHRN.S32       D30,Q15,#16     ; D30= t[0]-x[0]
1725         VSHRN.S32       D4, Q2, #16     ; D4 = t[7]-x[1]
1726         VSHRN.S32       D31,Q14,#16     ; D31= t[3]-x[2]
1727         VSHRN.S32       D6, Q3, #16     ; D6 = t[6]-x[3]
1728         VSHRN.S32       D7, Q13,#16     ; D7 = -t[5]-x[3]
1729         VSHRN.S32       D5, Q12,#16     ; D5 = t[4]
1730         VSHRN.S32       D2, Q1, #16     ; D2 = t[2]
1731         VADD.S16        D4, D4, D18     ; D4 = t[7]
1732         VADD.S16        D6, D6, D19     ; D6 = t[6]
1733         VADD.S16        D7, D7, D19     ; D7 = -t[5]
1734         VADD.S16        Q15,Q15,Q8      ; D30= t[0]
1735                                         ; D31= t[3]
1736 ; Stages 2 & 3
1737         VSUB.S16        Q12,Q2, Q3      ; D24= t[7]-t[6]
1738                                         ; D25= t[4]'=t[4]+t[5]
1739         VADD.S16        Q13,Q2, Q3      ; D26= t[7]'=t[7]+t[6]
1740                                         ; D27= t[4]-t[5]
1741         VMULL.S16       Q11,D24,D1[0]   ; Q11= OC_C4S4*(t[7]-t[6])
1742                                         ;       -(t[7]-t[6]<<16)
1743         VMULL.S16       Q14,D27,D1[0]   ; Q14= OC_C4S4*(t[4]-t[5])
1744                                         ;       -(t[4]-t[5]<<16)
1745         VADD.S16        D16,D30,D31     ; D16= t[0]'=t[0]+t[3]
1746         VSUB.S16        D17,D30,D2      ; D17= t[2]'=t[0]-t[2]
1747         VADD.S16        D18,D30,D2      ; D18= t[1]'=t[0]+t[2]
1748         VSHRN.S32       D22,Q11,#16     ; D22= (OC_C4S4*(t[7]-t[6])>>16)
1749                                         ;       -(t[7]-t[6])
1750         VSHRN.S32       D23,Q14,#16     ; D23= (OC_C4S4*(t[4]-t[5])>>16)
1751                                         ;       -(t[4]-t[5])
1752         VSUB.S16        D19,D30,D31     ; D19= t[3]'=t[0]-t[3]
1753         VADD.S16        D22,D22,D24     ; D22= t[6]'=OC_C4S4*(t[7]-t[6])>>16
1754         VADD.S16        D23,D23,D27     ; D23= t[5]'=OC_C4S4*(t[4]-t[5])>>16
1755         VSUB.S16        D27,D22,D23     ; D27= t[5]''=t[6]'-t[5]'
1756         VADD.S16        D24,D22,D23     ; D24= t[6]''=t[6]'+t[5]'
1757 ; Stage 4
1758         VSUB.S16        Q11,Q8, Q13     ; D22= y[7]=t[0]'-t[7]'
1759                                         ; D23= y[5]=t[2]'-t[5]''
1760         VSUB.S16        Q10,Q9, Q12     ; D20= y[6]=t[1]'-t[6]'
1761                                         ; D21= y[4]=t[3]'-t[4]''
1762         VADD.S16        Q8, Q8, Q13     ; D16= y[0]=t[0]'+t[7]'
1763                                         ; D17= y[2]=t[2]'+t[5]''
1764         VADD.S16        Q9, Q9, Q12     ; D18= y[1]=t[1]'-t[6]'
1765                                         ; D19= y[3]=t[3]'-t[4]''
1766         ; 8x4 transpose
1767         VTRN.16         Q10,Q11         ; Q10= c5c4a5a4 c7c6a7a6
1768                                         ; Q11= d5d4b5b4 d7d6b7b6
1769         VTRN.16         Q8, Q9          ; Q8 = c3c2a3a2 c1c0a1a0
1770                                         ; Q9 = d3d2b3b2 d1d0b1b0
1771         VSWP            D20,D21         ; Q10= c7c6a7a6 c5c4a5a4
1772         VSWP            D22,D23         ; Q11= d7d6b7b6 d5d4b5b4
1773         VUZP.32         Q9, Q11         ; Q9 = b7b6b5b4 b3b2b1b0
1774                                         ; Q11= d7d6d5d4 d3d2d1d0
1775         VMULL.S16       Q15,D18,D0[1]
1776         VMULL.S16       Q13,D22,D1[1]
1777         VUZP.32         Q8, Q10         ; Q8 = a7a6a5a4 a3a2a1a0
1778                                         ; Q10= c7c6c5c4 c3c2c1c0
1779         ; Column transforms
1780 ; Stages 1, 2, & 3
1781         VMULL.S16       Q14,D19,D0[1]   ; Q14:Q15= OC_C1S7*x[1]-(x[1]<<16)
1782         VMULL.S16       Q12,D23,D1[1]   ; Q12:Q13= OC_C5S3*x[3]-(x[3]<<16)
1783         VMULL.S16       Q3, D22,D0[3]
1784         VMULL.S16       Q2, D23,D0[3]   ;  Q2:Q3 = OC_C3S5*x[3]-(x[3]<<16)
1785         VSHRN.S32       D30,Q15,#16
1786         VSHRN.S32       D31,Q14,#16     ; Q15= (OC_C1S7*x[1]>>16)-x[1]
1787         VSHRN.S32       D26,Q13,#16
1788         VSHRN.S32       D27,Q12,#16     ; Q13= (OC_C5S3*x[3]>>16)-x[3]
1789         VSHRN.S32       D28,Q3, #16
1790         VSHRN.S32       D29,Q2, #16     ; Q14= (OC_C3S5*x[3]>>16)-x[3]
1791         VADD.S16        Q15,Q15,Q9      ; Q15= t[7]
1792         VADD.S16        Q13,Q13,Q11     ; Q13= -t[5]
1793         VADD.S16        Q14,Q14,Q11     ; Q14= t[6]
1794         VMULL.S16       Q12,D18,D1[3]
1795         VMULL.S16       Q2, D19,D1[3]   ;  Q2:Q12= OC_C7S1*x[1]
1796         VMULL.S16       Q1, D16,D1[0]
1797         VMULL.S16       Q11,D17,D1[0]   ; Q11:Q1 = OC_C4S4*x[0]-(x[0]<<16)
1798         VMULL.S16       Q3, D20,D0[2]
1799         VMULL.S16       Q9, D21,D0[2]   ;  Q9:Q3 = OC_C2S6*x[2]-(x[2]<<16)
1800         VSHRN.S32       D24,Q12,#16
1801         VSHRN.S32       D25,Q2, #16     ; Q12= t[4]
1802         VMULL.S16       Q2, D20,D1[2]
1803         VSHRN.S32       D2, Q1, #16
1804         VSHRN.S32       D3, Q11,#16     ; Q1 = (OC_C4S4*x[0]>>16)-x[0]
1805         VMULL.S16       Q11,D21,D1[2]   ;  Q2:Q11= OC_C6S2*x[2]
1806         VSHRN.S32       D6, Q3, #16
1807         VSHRN.S32       D7, Q9, #16     ; Q3 = (OC_C2S6*x[2]>>16)-x[2]
1808         VSUB.S16        Q9, Q15,Q14     ; Q9 = t[7]-t[6]
1809         VADD.S16        Q15,Q15,Q14     ; Q15= t[7]'=t[7]+t[6]
1810         VSHRN.S32       D4, Q2, #16
1811         VSHRN.S32       D5, Q11,#16     ; Q2 = t[2]
1812         VADD.S16        Q1, Q1, Q8      ; Q1 = t[0]
1813         VADD.S16        Q8, Q12,Q13     ; Q8 = t[4]-t[5]
1814         VADD.S16        Q3, Q3, Q10     ; Q3 = t[3]
1815         VMULL.S16       Q10,D16,D1[0]
1816         VMULL.S16       Q11,D17,D1[0]   ; Q11:Q10= OC_C4S4*(t[4]-t[5])
1817                                         ;           -(t[4]-t[5]<<16)
1818         VSUB.S16        Q12,Q12,Q13     ; Q12= t[4]'=t[4]+t[5]
1819         VMULL.S16       Q14,D18,D1[0]
1820         VMULL.S16       Q13,D19,D1[0]   ; Q13:Q14= OC_C4S4*(t[6]-t[7])
1821                                         ;           -(t[6]-t[7]<<16)
1822         VSHRN.S32       D20,Q10,#16
1823         VSHRN.S32       D21,Q11,#16     ; Q10= (OC_C4S4*(t[4]-t[5])>>16)
1824                                         ;       -(t[4]-t[5])
1825         VADD.S16        Q11,Q1, Q3      ; Q11= t[0]'=t[0]+t[3]
1826         VSUB.S16        Q3, Q1, Q3      ; Q3 = t[3]'=t[0]-t[3]
1827         VSHRN.S32       D28,Q14,#16
1828         VSHRN.S32       D29,Q13,#16     ; Q14= (OC_C4S4*(t[7]-t[6])>>16)
1829                                         ;       -(t[7]-t[6])
1830         VADD.S16        Q10,Q10,Q8      ; Q10=t[5]'
1831         VADD.S16        Q14,Q14,Q9      ; Q14=t[6]'
1832         VSUB.S16        Q13,Q14,Q10     ; Q13=t[5]''=t[6]'-t[5]'
1833         VADD.S16        Q14,Q14,Q10     ; Q14=t[6]''=t[6]'+t[5]'
1834         VADD.S16        Q10,Q1, Q2      ; Q10= t[1]'=t[0]+t[2]
1835         VSUB.S16        Q2, Q1, Q2      ; Q2 = t[2]'=t[0]-t[2]
1836 ; Stage 4
1837         CMP     r0, r1
1838         VADD.S16        Q8, Q11,Q15     ; Q8  = y[0]=t[0]'+t[7]'
1839         VADD.S16        Q9, Q10,Q14     ; Q9  = y[1]=t[1]'+t[6]''
1840         VSUB.S16        Q15,Q11,Q15     ; Q15 = y[7]=t[0]'-t[7]'
1841         VSUB.S16        Q14,Q10,Q14     ; Q14 = y[6]=t[1]'-t[6]''
1842         VADD.S16        Q10,Q2, Q13     ; Q10 = y[2]=t[2]'+t[5]''
1843         VADD.S16        Q11,Q3, Q12     ; Q11 = y[3]=t[3]'+t[4]'
1844         VSUB.S16        Q12,Q3, Q12     ; Q12 = y[4]=t[3]'-t[4]'
1845         VSUB.S16        Q13,Q2, Q13     ; Q13 = y[5]=t[2]'-t[5]''
1846         BEQ     oc_idct8x8_10_neon_noclear
1847         VMOV.I8         D2, #0
1848         VRSHR.S16       Q8, Q8, #4      ; Q8  = y[0]+8>>4
1849         VST1.64         {D2}, [r1@64], r12
1850         VRSHR.S16       Q9, Q9, #4      ; Q9  = y[1]+8>>4
1851         VRSHR.S16       Q10,Q10,#4      ; Q10 = y[2]+8>>4
1852         VST1.64         {D2}, [r1@64], r12
1853         VRSHR.S16       Q11,Q11,#4      ; Q11 = y[3]+8>>4
1854         VRSHR.S16       Q12,Q12,#4      ; Q12 = y[4]+8>>4
1855         VST1.64         {D2}, [r1@64], r12
1856         VRSHR.S16       Q13,Q13,#4      ; Q13 = y[5]+8>>4
1857         VRSHR.S16       Q14,Q14,#4      ; Q14 = y[6]+8>>4
1858         VST1.64         {D2}, [r1@64]
1859         VRSHR.S16       Q15,Q15,#4      ; Q15 = y[7]+8>>4
1860         VSTMIA          r0, {D16-D31}
1861         MOV     PC, r14
1862
1863 oc_idct8x8_10_neon_noclear
1864         VRSHR.S16       Q8, Q8, #4      ; Q8  = y[0]+8>>4
1865         VRSHR.S16       Q9, Q9, #4      ; Q9  = y[1]+8>>4
1866         VRSHR.S16       Q10,Q10,#4      ; Q10 = y[2]+8>>4
1867         VRSHR.S16       Q11,Q11,#4      ; Q11 = y[3]+8>>4
1868         VRSHR.S16       Q12,Q12,#4      ; Q12 = y[4]+8>>4
1869         VRSHR.S16       Q13,Q13,#4      ; Q13 = y[5]+8>>4
1870         VRSHR.S16       Q14,Q14,#4      ; Q14 = y[6]+8>>4
1871         VRSHR.S16       Q15,Q15,#4      ; Q15 = y[7]+8>>4
1872         VSTMIA          r0, {D16-D31}
1873         MOV     PC, r14
1874  ]
1875
1876         END