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