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