~ppsspp/ppsspp/ffmpeg

« back to all changes in this revision

Viewing changes to libavcodec/arm/vc1dsp_neon.S

  • Committer: Henrik Rydgård
  • Date: 2014-01-03 10:44:32 UTC
  • Revision ID: git-v1:87c6c126784b1718bfa448ecf2e6a9fef781eb4e
Update our ffmpeg snapshot to a clone of the official repository.

This is because Maxim's at3plus support has been officially merged!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * VC1 NEON optimisations
 
3
 *
 
4
 * Copyright (c) 2010 Rob Clark <rob@ti.com>
 
5
 * Copyright (c) 2011 Mans Rullgard <mans@mansr.com>
 
6
 *
 
7
 * This file is part of FFmpeg.
 
8
 *
 
9
 * FFmpeg is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Lesser General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2.1 of the License, or (at your option) any later version.
 
13
 *
 
14
 * FFmpeg is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public
 
20
 * License along with FFmpeg; if not, write to the Free Software
 
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
22
 */
 
23
 
 
24
#include "libavutil/arm/asm.S"
 
25
#include "neon.S"
 
26
 
 
27
@ Transpose rows into columns of a matrix of 16-bit elements. For 4x4, pass
 
28
@ double-word registers, for 8x4, pass quad-word registers.
 
29
.macro transpose16 r0, r1, r2, r3
 
30
        @ At this point:
 
31
        @   row[0]  r0
 
32
        @   row[1]  r1
 
33
        @   row[2]  r2
 
34
        @   row[3]  r3
 
35
 
 
36
        vtrn.16         \r0,  \r1         @ first and second row
 
37
        vtrn.16         \r2,  \r3         @ third and fourth row
 
38
        vtrn.32         \r0,  \r2         @ first and third row
 
39
        vtrn.32         \r1,  \r3         @ second and fourth row
 
40
 
 
41
        @ At this point, if registers are quad-word:
 
42
        @   column[0]   d0
 
43
        @   column[1]   d2
 
44
        @   column[2]   d4
 
45
        @   column[3]   d6
 
46
        @   column[4]   d1
 
47
        @   column[5]   d3
 
48
        @   column[6]   d5
 
49
        @   column[7]   d7
 
50
 
 
51
        @ At this point, if registers are double-word:
 
52
        @   column[0]   d0
 
53
        @   column[1]   d1
 
54
        @   column[2]   d2
 
55
        @   column[3]   d3
 
56
.endm
 
57
 
 
58
@ ff_vc1_inv_trans_{4,8}x{4,8}_neon and overflow: The input values in the file
 
59
@ are supposed to be in a specific range as to allow for 16-bit math without
 
60
@ causing overflows, but sometimes the input values are just big enough to
 
61
@ barely cause overflow in vadd instructions like:
 
62
@
 
63
@   vadd.i16  q0, q8, q10
 
64
@   vshr.s16  q0, q0, #\rshift
 
65
@
 
66
@ To prevent these borderline cases from overflowing, we just need one more
 
67
@ bit of precision, which is accomplished by replacing the sequence above with:
 
68
@
 
69
@   vhadd.s16 q0, q8, q10
 
70
@   vshr.s16  q0, q0, #(\rshift -1)
 
71
@
 
72
@ This works because vhadd is a single instruction that adds, then shifts to
 
73
@ the right once, all before writing the result to the destination register.
 
74
@
 
75
@ Even with this workaround, there were still some files that caused overflows
 
76
@ in ff_vc1_inv_trans_8x8_neon. See the comments in ff_vc1_inv_trans_8x8_neon
 
77
@ for the additional workaround.
 
78
 
 
79
@ Takes 4 columns of 8 values each and operates on it. Modeled after the first
 
80
@ for loop in vc1_inv_trans_4x8_c.
 
81
@ Input columns: q0 q1 q2 q3
 
82
@ Output columns: q0 q1 q2 q3
 
83
@ Trashes: r12 q8 q9 q10 q11 q12 q13
 
84
.macro vc1_inv_trans_4x8_helper add rshift
 
85
        @ Compute temp1, temp2 and setup scalar #17, #22, #10
 
86
        vadd.i16        q12,   q0,  q2              @ temp1 = src[0] + src[2]
 
87
        movw            r12,   #17
 
88
        vsub.i16        q13,   q0,  q2              @ temp2 = src[0] - src[2]
 
89
        movt            r12,   #22
 
90
        vmov.32         d0[0], r12
 
91
        movw            r12,   #10
 
92
        vmov.16         d1[0], r12
 
93
 
 
94
        vmov.i16        q8,  #\add                  @ t1 will accumulate here
 
95
        vmov.i16        q9,  #\add                  @ t2 will accumulate here
 
96
 
 
97
        vmul.i16        q10, q1,  d0[1]             @ t3 = 22 * (src[1])
 
98
        vmul.i16        q11, q3,  d0[1]             @ t4 = 22 * (src[3])
 
99
 
 
100
        vmla.i16        q8,  q12, d0[0]             @ t1 = 17 * (temp1) + 4
 
101
        vmla.i16        q9,  q13, d0[0]             @ t2 = 17 * (temp2) + 4
 
102
 
 
103
        vmla.i16        q10, q3,  d1[0]             @ t3 += 10 * src[3]
 
104
        vmls.i16        q11, q1,  d1[0]             @ t4 -= 10 * src[1]
 
105
 
 
106
        vhadd.s16       q0,  q8,  q10               @ dst[0] = (t1 + t3) >> 1
 
107
        vhsub.s16       q3,  q8,  q10               @ dst[3] = (t1 - t3) >> 1
 
108
        vhsub.s16       q1,  q9,  q11               @ dst[1] = (t2 - t4) >> 1
 
109
        vhadd.s16       q2,  q9,  q11               @ dst[2] = (t2 + t4) >> 1
 
110
 
 
111
        @ Halving add/sub above already did one shift
 
112
        vshr.s16        q0,  q0,  #(\rshift - 1)    @ dst[0] >>= (rshift - 1)
 
113
        vshr.s16        q3,  q3,  #(\rshift - 1)    @ dst[3] >>= (rshift - 1)
 
114
        vshr.s16        q1,  q1,  #(\rshift - 1)    @ dst[1] >>= (rshift - 1)
 
115
        vshr.s16        q2,  q2,  #(\rshift - 1)    @ dst[2] >>= (rshift - 1)
 
116
.endm
 
117
 
 
118
@ Takes 8 columns of 4 values each and operates on it. Modeled after the second
 
119
@ for loop in vc1_inv_trans_4x8_c.
 
120
@ Input columns: d0 d2 d4 d6 d1 d3 d5 d7
 
121
@ Output columns: d16 d17 d18 d19 d21 d20 d23 d22
 
122
@ Trashes all NEON registers (and r12) except for: q4 q5 q6 q7
 
123
.macro vc1_inv_trans_8x4_helper add add1beforeshift rshift
 
124
        @ At this point:
 
125
        @   src[0]      d0 overwritten later
 
126
        @   src[8]      d2
 
127
        @   src[16]     d4 overwritten later
 
128
        @   src[24]     d6
 
129
        @   src[32]     d1 overwritten later
 
130
        @   src[40]     d3
 
131
        @   src[48]     d5 overwritten later
 
132
        @   src[56]     d7
 
133
 
 
134
        movw            r12,   #12
 
135
        vmov.i16        q14,   #\add            @ t1|t2 will accumulate here
 
136
        movt            r12,   #6
 
137
 
 
138
        vadd.i16        d20,   d0,  d1          @ temp1 = src[0] + src[32]
 
139
        vsub.i16        d21,   d0,  d1          @ temp2 = src[0] - src[32]
 
140
        vmov.i32        d0[0], r12              @ 16-bit: d0[0] = #12, d0[1] = #6
 
141
 
 
142
        vshl.i16        q15,   q2,  #4          @ t3|t4 = 16 * (src[16]|src[48])
 
143
        vswp            d4,    d5               @ q2 = src[48]|src[16]
 
144
        vmla.i16        q14,   q10, d0[0]       @ t1|t2 = 12 * (temp1|temp2) + 64
 
145
        movw            r12,   #15
 
146
        movt            r12,   #9
 
147
        vmov.i32        d0[1], r12              @ 16-bit: d0[2] = #15, d0[3] = #9
 
148
        vneg.s16        d31,   d31              @ t4 = -t4
 
149
        vmla.i16        q15,   q2,  d0[1]       @ t3|t4 += 6 * (src[48]|src[16])
 
150
 
 
151
        @ At this point:
 
152
        @   d0[2]   #15
 
153
        @   d0[3]   #9
 
154
        @   q1      src[8]|src[40]
 
155
        @   q3      src[24]|src[56]
 
156
        @   q14     old t1|t2
 
157
        @   q15     old t3|t4
 
158
 
 
159
        vshl.i16        q8,  q1,  #4            @ t1|t2 = 16 * (src[8]|src[40])
 
160
        vswp            d2,  d3                 @ q1 = src[40]|src[8]
 
161
        vshl.i16        q12, q3,  #4            @ temp3a|temp4a = 16 * src[24]|src[56]
 
162
        vswp            d6,  d7                 @ q3 = src[56]|src[24]
 
163
        vshl.i16        q13, q1,  #2            @ temp3b|temp4b = 4 * (src[40]|src[8])
 
164
        vshl.i16        q2,  q3,  #2            @ temp1|temp2 = 4 * (src[56]|src[24])
 
165
        vswp            d3,  d6                 @ q1 = src[40]|src[56], q3 = src[8]|src[24]
 
166
        vsub.i16        q9,  q13, q12           @ t3|t4 = - (temp3a|temp4a) + (temp3b|temp4b)
 
167
        vadd.i16        q8,  q8,  q2            @ t1|t2 += temp1|temp2
 
168
        vmul.i16        q12, q3,  d0[3]         @ temp3|temp4 = 9 * src[8]|src[24]
 
169
        vmla.i16        q8,  q1,  d0[3]         @ t1|t2 += 9 * (src[40]|src[56])
 
170
        vswp            d6,  d7                 @ q3 = src[24]|src[8]
 
171
        vswp            d2,  d3                 @ q1 = src[56]|src[40]
 
172
 
 
173
        vsub.i16        q11, q14, q15           @ t8|t7 = old t1|t2 - old t3|t4
 
174
        vadd.i16        q10, q14, q15           @ t5|t6 = old t1|t2 + old t3|t4
 
175
  .if \add1beforeshift
 
176
        vmov.i16        q15, #1
 
177
  .endif
 
178
 
 
179
        vadd.i16        d18, d18, d24           @ t3 += temp3
 
180
        vsub.i16        d19, d19, d25           @ t4 -= temp4
 
181
 
 
182
        vswp            d22, d23                @ q11 = t7|t8
 
183
 
 
184
        vneg.s16        d17, d17                @ t2 = -t2
 
185
        vmla.i16        q9,  q1,  d0[2]         @ t3|t4 += 15 * src[56]|src[40]
 
186
        vmla.i16        q8,  q3,  d0[2]         @ t1|t2 += 15 * src[24]|src[8]
 
187
 
 
188
        @ At this point:
 
189
        @   t1  d16
 
190
        @   t2  d17
 
191
        @   t3  d18
 
192
        @   t4  d19
 
193
        @   t5  d20
 
194
        @   t6  d21
 
195
        @   t7  d22
 
196
        @   t8  d23
 
197
        @   #1  q15
 
198
 
 
199
  .if \add1beforeshift
 
200
        vadd.i16        q3,  q15, q10           @ line[7,6] = t5|t6 + 1
 
201
        vadd.i16        q2,  q15, q11           @ line[5,4] = t7|t8 + 1
 
202
  .endif
 
203
 
 
204
        @ Sometimes this overflows, so to get one additional bit of precision, use
 
205
        @ a single instruction that both adds and shifts right (halving).
 
206
        vhadd.s16       q1,  q9,  q11           @ line[2,3] = (t3|t4 + t7|t8) >> 1
 
207
        vhadd.s16       q0,  q8,  q10           @ line[0,1] = (t1|t2 + t5|t6) >> 1
 
208
  .if \add1beforeshift
 
209
        vhsub.s16       q2,  q2,  q9            @ line[5,4] = (t7|t8 - t3|t4 + 1) >> 1
 
210
        vhsub.s16       q3,  q3,  q8            @ line[7,6] = (t5|t6 - t1|t2 + 1) >> 1
 
211
  .else
 
212
        vhsub.s16       q2,  q11, q9            @ line[5,4] = (t7|t8 - t3|t4) >> 1
 
213
        vhsub.s16       q3,  q10, q8            @ line[7,6] = (t5|t6 - t1|t2) >> 1
 
214
  .endif
 
215
 
 
216
        vshr.s16        q9,  q1,  #(\rshift - 1)    @ one shift is already done by vhadd/vhsub above
 
217
        vshr.s16        q8,  q0,  #(\rshift - 1)
 
218
        vshr.s16        q10, q2,  #(\rshift - 1)
 
219
        vshr.s16        q11, q3,  #(\rshift - 1)
 
220
 
 
221
        @ At this point:
 
222
        @   dst[0]   d16
 
223
        @   dst[1]   d17
 
224
        @   dst[2]   d18
 
225
        @   dst[3]   d19
 
226
        @   dst[4]   d21
 
227
        @   dst[5]   d20
 
228
        @   dst[6]   d23
 
229
        @   dst[7]   d22
 
230
.endm
 
231
 
 
232
@ This is modeled after the first and second for loop in vc1_inv_trans_8x8_c.
 
233
@ Input columns:  q8, q9, q10, q11, q12, q13, q14, q15
 
234
@ Output columns: q8, q9, q10, q11, q12, q13, q14, q15
 
235
@ Trashes all NEON registers (and r12) except for: q4 q5 q6 q7
 
236
.macro vc1_inv_trans_8x8_helper add add1beforeshift rshift
 
237
        @ This actually computes half of t1, t2, t3, t4, as explained below
 
238
        @ near `tNhalf`.
 
239
        vmov.i16        q0,    #(6 / 2)         @ q0 = #6/2
 
240
        vshl.i16        q1,    q10, #3          @ t3 = 16/2 * src[16]
 
241
        vshl.i16        q3,    q14, #3          @ temp4 = 16/2 * src[48]
 
242
        vmul.i16        q2,    q10, q0          @ t4 = 6/2 * src[16]
 
243
        vmla.i16        q1,    q14, q0          @ t3 += 6/2 * src[48]
 
244
        @ unused: q0, q10, q14
 
245
        vmov.i16        q0,    #(12 / 2)        @ q0 = #12/2
 
246
        vadd.i16        q10,   q8,  q12         @ temp1 = src[0] + src[32]
 
247
        vsub.i16        q14,   q8,  q12         @ temp2 = src[0] - src[32]
 
248
        @ unused: q8, q12
 
249
        vmov.i16        q8,    #(\add / 2)      @ t1 will accumulate here
 
250
        vmov.i16        q12,   #(\add / 2)      @ t2 will accumulate here
 
251
        movw            r12,   #15
 
252
        vsub.i16        q2,    q2,  q3          @ t4 = 6/2 * src[16] - 16/2 * src[48]
 
253
        movt            r12,   #9
 
254
        @ unused: q3
 
255
        vmla.i16        q8,    q10, q0          @ t1 = 12/2 * temp1 + add
 
256
        vmla.i16        q12,   q14, q0          @ t2 = 12/2 * temp2 + add
 
257
        vmov.i32        d0[0], r12
 
258
        @ unused: q3, q10, q14
 
259
 
 
260
        @ At this point:
 
261
        @   q0          d0=#15|#9
 
262
        @   q1  old t3
 
263
        @   q2  old t4
 
264
        @   q3
 
265
        @   q8  old t1
 
266
        @   q9          src[8]
 
267
        @   q10
 
268
        @   q11         src[24]
 
269
        @   q12 old t2
 
270
        @   q13         src[40]
 
271
        @   q14
 
272
        @   q15         src[56]
 
273
 
 
274
        @ unused: q3, q10, q14
 
275
        movw            r12,   #16
 
276
        vshl.i16        q3,    q9,  #4          @ t1 = 16 * src[8]
 
277
        movt            r12,   #4
 
278
        vshl.i16        q10,   q9,  #2          @ t4 = 4 * src[8]
 
279
        vmov.i32        d1[0], r12
 
280
        vmul.i16        q14,   q9,  d0[0]       @ t2 = 15 * src[8]
 
281
        vmul.i16        q9,    q9,  d0[1]       @ t3 = 9 * src[8]
 
282
        @ unused: none
 
283
        vmla.i16        q3,    q11, d0[0]       @ t1 += 15 * src[24]
 
284
        vmls.i16        q10,   q11, d0[1]       @ t4 -= 9 * src[24]
 
285
        vmls.i16        q14,   q11, d1[1]       @ t2 -= 4 * src[24]
 
286
        vmls.i16        q9,    q11, d1[0]       @ t3 -= 16 * src[24]
 
287
        @ unused: q11
 
288
        vmla.i16        q3,    q13, d0[1]       @ t1 += 9 * src[40]
 
289
        vmla.i16        q10,   q13, d0[0]       @ t4 += 15 * src[40]
 
290
        vmls.i16        q14,   q13, d1[0]       @ t2 -= 16 * src[40]
 
291
        vmla.i16        q9,    q13, d1[1]       @ t3 += 4 * src[40]
 
292
        @ unused: q11, q13
 
293
 
 
294
        @ Compute t5, t6, t7, t8 from old t1, t2, t3, t4. Actually, it computes
 
295
        @ half of t5, t6, t7, t8 since t1, t2, t3, t4 are halved.
 
296
        vadd.i16        q11,   q8,  q1          @ t5 = t1 + t3
 
297
        vsub.i16        q1,    q8,  q1          @ t8 = t1 - t3
 
298
        vadd.i16        q13,   q12, q2          @ t6 = t2 + t4
 
299
        vsub.i16        q2,    q12, q2          @ t7 = t2 - t4
 
300
        @ unused: q8, q12
 
301
 
 
302
  .if \add1beforeshift
 
303
        vmov.i16        q12,   #1
 
304
  .endif
 
305
 
 
306
        @ unused: q8
 
307
        vmla.i16        q3,    q15, d1[1]       @ t1 += 4 * src[56]
 
308
        vmls.i16        q14,   q15, d0[1]       @ t2 -= 9 * src[56]
 
309
        vmla.i16        q9,    q15, d0[0]       @ t3 += 15 * src[56]
 
310
        vmls.i16        q10,   q15, d1[0]       @ t4 -= 16 * src[56]
 
311
        @ unused: q0, q8, q15
 
312
 
 
313
        @ At this point:
 
314
        @   t1      q3
 
315
        @   t2      q14
 
316
        @   t3      q9
 
317
        @   t4      q10
 
318
        @   t5half  q11
 
319
        @   t6half  q13
 
320
        @   t7half  q2
 
321
        @   t8half  q1
 
322
        @   #1      q12
 
323
        @
 
324
        @ tNhalf is half of the value of tN (as described in vc1_inv_trans_8x8_c).
 
325
        @ This is done because sometimes files have input that causes tN + tM to
 
326
        @ overflow. To avoid this overflow, we compute tNhalf, then compute
 
327
        @ tNhalf + tM (which doesn't overflow), and then we use vhadd to compute
 
328
        @ (tNhalf + (tNhalf + tM)) >> 1 which does not overflow because it is
 
329
        @ one instruction.
 
330
 
 
331
        @ For each pair of tN and tM, do:
 
332
        @   lineA = t5half + t1
 
333
        @   if add1beforeshift:  t1 -= 1
 
334
        @   lineA = (t5half + lineA) >> 1
 
335
        @   lineB = t5half - t1
 
336
        @   lineB = (t5half + lineB) >> 1
 
337
        @   lineA >>= rshift - 1
 
338
        @   lineB >>= rshift - 1
 
339
 
 
340
        vadd.i16        q8,  q11, q3                @ q8 = t5half + t1
 
341
  .if \add1beforeshift
 
342
        vsub.i16        q3,  q3,  q12               @ q3 = t1 - 1
 
343
  .endif
 
344
 
 
345
        vadd.i16        q0,  q13, q14               @ q0  = t6half + t2
 
346
  .if \add1beforeshift
 
347
        vsub.i16        q14, q14, q12               @ q14 = t2 - 1
 
348
  .endif
 
349
 
 
350
        vadd.i16        q15, q2,  q9                @ q15 = t7half + t3
 
351
  .if \add1beforeshift
 
352
        vsub.i16        q9,  q9,  q12               @ q9  = t3 - 1
 
353
  .endif
 
354
        @ unused: none
 
355
 
 
356
        vhadd.s16       q8,  q11, q8                @ q8  = (t5half + t5half + t1) >> 1
 
357
        vsub.i16        q3,  q11, q3                @ q3  = t5half - t1 + 1
 
358
 
 
359
        vhadd.s16       q0,  q13, q0                @ q0  = (t6half + t6half + t2) >> 1
 
360
        vsub.i16        q14, q13, q14               @ q14 = t6half - t2 + 1
 
361
 
 
362
        vhadd.s16       q15, q2,  q15               @ q15 = (t7half + t7half + t3) >> 1
 
363
        vsub.i16        q9,  q2,  q9                @ q9  = t7half - t3 + 1
 
364
 
 
365
        vhadd.s16       q3,  q11, q3                @ q3  = (t5half + t5half - t1 + 1) >> 1
 
366
        @ unused: q11
 
367
 
 
368
        vadd.i16        q11, q1,  q10               @ q11 = t8half + t4
 
369
  .if \add1beforeshift
 
370
        vsub.i16        q10, q10, q12               @ q10 = t4 - 1
 
371
  .endif
 
372
        @ unused: q12
 
373
 
 
374
        vhadd.s16       q14, q13, q14               @ q14 = (t6half + t6half - t2 + 1) >> 1
 
375
        @ unused: q12, q13
 
376
        vhadd.s16       q13, q2,  q9                @ q9  = (t7half + t7half - t3 + 1) >> 1
 
377
        @ unused: q12, q2, q9
 
378
 
 
379
        vsub.i16        q10, q1,  q10               @ q10 = t8half - t4 + 1
 
380
        vhadd.s16       q11, q1,  q11               @ q11 = (t8half + t8half + t4) >> 1
 
381
 
 
382
        vshr.s16        q8,  q8,  #(\rshift - 1)    @ q8  = line[0]
 
383
        vhadd.s16       q12, q1,  q10               @ q12 = (t8half + t8half - t4 + 1) >> 1
 
384
        vshr.s16        q9,  q0,  #(\rshift - 1)    @ q9  = line[1]
 
385
        vshr.s16        q10, q15, #(\rshift - 1)    @ q10 = line[2]
 
386
        vshr.s16        q11, q11, #(\rshift - 1)    @ q11 = line[3]
 
387
        vshr.s16        q12, q12, #(\rshift - 1)    @ q12 = line[4]
 
388
        vshr.s16        q13, q13, #(\rshift - 1)    @ q13 = line[5]
 
389
        vshr.s16        q14, q14, #(\rshift - 1)    @ q14 = line[6]
 
390
        vshr.s16        q15, q3,  #(\rshift - 1)    @ q15 = line[7]
 
391
.endm
 
392
 
 
393
@ (int16_t *block [r0])
 
394
function ff_vc1_inv_trans_8x8_neon, export=1
 
395
        vld1.64         {q8-q9},   [r0,:128]!
 
396
        vld1.64         {q10-q11}, [r0,:128]!
 
397
        vld1.64         {q12-q13}, [r0,:128]!
 
398
        vld1.64         {q14-q15}, [r0,:128]
 
399
        sub             r0, r0, #(16 * 2 * 3)   @ restore r0
 
400
 
 
401
        @ At this point:
 
402
        @   src[0]  q8
 
403
        @   src[8]  q9
 
404
        @   src[16] q10
 
405
        @   src[24] q11
 
406
        @   src[32] q12
 
407
        @   src[40] q13
 
408
        @   src[48] q14
 
409
        @   src[56] q15
 
410
 
 
411
        vc1_inv_trans_8x8_helper add=4 add1beforeshift=0 rshift=3
 
412
 
 
413
        @ Transpose result matrix of 8x8
 
414
        swap4           d17, d19, d21, d23, d24, d26, d28, d30
 
415
        transpose16_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15
 
416
 
 
417
        vc1_inv_trans_8x8_helper add=64 add1beforeshift=1 rshift=7
 
418
 
 
419
        vst1.64         {q8-q9},   [r0,:128]!
 
420
        vst1.64         {q10-q11}, [r0,:128]!
 
421
        vst1.64         {q12-q13}, [r0,:128]!
 
422
        vst1.64         {q14-q15}, [r0,:128]
 
423
 
 
424
        bx              lr
 
425
endfunc
 
426
 
 
427
@ (uint8_t *dest [r0], int linesize [r1], int16_t *block [r2])
 
428
function ff_vc1_inv_trans_8x4_neon, export=1
 
429
        vld1.64         {q0-q1}, [r2,:128]!     @ load 8 * 4 * 2 = 64 bytes / 16 bytes per quad = 4 quad registers
 
430
        vld1.64         {q2-q3}, [r2,:128]
 
431
 
 
432
        transpose16     q0 q1 q2 q3             @ transpose rows to columns
 
433
 
 
434
        @ At this point:
 
435
        @   src[0]   d0
 
436
        @   src[1]   d2
 
437
        @   src[2]   d4
 
438
        @   src[3]   d6
 
439
        @   src[4]   d1
 
440
        @   src[5]   d3
 
441
        @   src[6]   d5
 
442
        @   src[7]   d7
 
443
 
 
444
        vc1_inv_trans_8x4_helper    add=4 add1beforeshift=0 rshift=3
 
445
 
 
446
        @ Move output to more standardized registers
 
447
        vmov        d0, d16
 
448
        vmov        d2, d17
 
449
        vmov        d4, d18
 
450
        vmov        d6, d19
 
451
        vmov        d1, d21
 
452
        vmov        d3, d20
 
453
        vmov        d5, d23
 
454
        vmov        d7, d22
 
455
 
 
456
        @ At this point:
 
457
        @   dst[0]   d0
 
458
        @   dst[1]   d2
 
459
        @   dst[2]   d4
 
460
        @   dst[3]   d6
 
461
        @   dst[4]   d1
 
462
        @   dst[5]   d3
 
463
        @   dst[6]   d5
 
464
        @   dst[7]   d7
 
465
 
 
466
        transpose16     q0 q1 q2 q3   @ turn columns into rows
 
467
 
 
468
        @ At this point:
 
469
        @   row[0] q0
 
470
        @   row[1] q1
 
471
        @   row[2] q2
 
472
        @   row[3] q3
 
473
 
 
474
        vc1_inv_trans_4x8_helper    add=64 rshift=7
 
475
 
 
476
        @ At this point:
 
477
        @   line[0].l   d0
 
478
        @   line[0].h   d1
 
479
        @   line[1].l   d2
 
480
        @   line[1].h   d3
 
481
        @   line[2].l   d4
 
482
        @   line[2].h   d5
 
483
        @   line[3].l   d6
 
484
        @   line[3].h   d7
 
485
 
 
486
        @ unused registers: q12, q13, q14, q15
 
487
 
 
488
        vld1.64         {d28}, [r0,:64], r1     @ read dest
 
489
        vld1.64         {d29}, [r0,:64], r1
 
490
        vld1.64         {d30}, [r0,:64], r1
 
491
        vld1.64         {d31}, [r0,:64], r1
 
492
        sub             r0,  r0,  r1, lsl #2    @ restore original r0 value
 
493
 
 
494
        vaddw.u8        q0,  q0,  d28           @ line[0] += dest[0]
 
495
        vaddw.u8        q1,  q1,  d29           @ line[1] += dest[1]
 
496
        vaddw.u8        q2,  q2,  d30           @ line[2] += dest[2]
 
497
        vaddw.u8        q3,  q3,  d31           @ line[3] += dest[3]
 
498
 
 
499
        vqmovun.s16     d0,  q0                 @ line[0]
 
500
        vqmovun.s16     d1,  q1                 @ line[1]
 
501
        vqmovun.s16     d2,  q2                 @ line[2]
 
502
        vqmovun.s16     d3,  q3                 @ line[3]
 
503
 
 
504
        vst1.64         {d0},  [r0,:64], r1     @ write dest
 
505
        vst1.64         {d1},  [r0,:64], r1
 
506
        vst1.64         {d2},  [r0,:64], r1
 
507
        vst1.64         {d3},  [r0,:64]
 
508
 
 
509
        bx              lr
 
510
endfunc
 
511
 
 
512
@ (uint8_t *dest [r0], int linesize [r1], int16_t *block [r2])
 
513
function ff_vc1_inv_trans_4x8_neon, export=1
 
514
        mov             r12, #(8 * 2)  @ 8 elements per line, each element 2 bytes
 
515
        vld4.16         {d0[],  d2[],  d4[],  d6[]},  [r2,:64], r12     @ read each column into a q register
 
516
        vld4.16         {d0[1], d2[1], d4[1], d6[1]}, [r2,:64], r12
 
517
        vld4.16         {d0[2], d2[2], d4[2], d6[2]}, [r2,:64], r12
 
518
        vld4.16         {d0[3], d2[3], d4[3], d6[3]}, [r2,:64], r12
 
519
        vld4.16         {d1[],  d3[],  d5[],  d7[]},  [r2,:64], r12
 
520
        vld4.16         {d1[1], d3[1], d5[1], d7[1]}, [r2,:64], r12
 
521
        vld4.16         {d1[2], d3[2], d5[2], d7[2]}, [r2,:64], r12
 
522
        vld4.16         {d1[3], d3[3], d5[3], d7[3]}, [r2,:64]
 
523
 
 
524
        vc1_inv_trans_4x8_helper    add=4 rshift=3
 
525
 
 
526
        @ At this point:
 
527
        @   dst[0] = q0
 
528
        @   dst[1] = q1
 
529
        @   dst[2] = q2
 
530
        @   dst[3] = q3
 
531
 
 
532
        transpose16     q0 q1 q2 q3     @ Transpose rows (registers) into columns
 
533
 
 
534
        vc1_inv_trans_8x4_helper    add=64 add1beforeshift=1 rshift=7
 
535
 
 
536
        vld1.32         {d28[]},  [r0,:32], r1  @ read dest
 
537
        vld1.32         {d28[1]}, [r0,:32], r1
 
538
        vld1.32         {d29[]},  [r0,:32], r1
 
539
        vld1.32         {d29[1]}, [r0,:32], r1
 
540
 
 
541
        vld1.32         {d30[]},  [r0,:32], r1
 
542
        vld1.32         {d30[0]}, [r0,:32], r1
 
543
        vld1.32         {d31[]},  [r0,:32], r1
 
544
        vld1.32         {d31[0]}, [r0,:32], r1
 
545
        sub             r0,  r0,  r1, lsl #3    @ restore original r0 value
 
546
 
 
547
        vaddw.u8        q8,  q8,  d28           @ line[0,1] += dest[0,1]
 
548
        vaddw.u8        q9,  q9,  d29           @ line[2,3] += dest[2,3]
 
549
        vaddw.u8        q10, q10, d30           @ line[5,4] += dest[5,4]
 
550
        vaddw.u8        q11, q11, d31           @ line[7,6] += dest[7,6]
 
551
 
 
552
        vqmovun.s16     d16, q8                 @ clip(line[0,1])
 
553
        vqmovun.s16     d18, q9                 @ clip(line[2,3])
 
554
        vqmovun.s16     d20, q10                @ clip(line[5,4])
 
555
        vqmovun.s16     d22, q11                @ clip(line[7,6])
 
556
 
 
557
        vst1.32         {d16[0]}, [r0,:32], r1  @ write dest
 
558
        vst1.32         {d16[1]}, [r0,:32], r1
 
559
        vst1.32         {d18[0]}, [r0,:32], r1
 
560
        vst1.32         {d18[1]}, [r0,:32], r1
 
561
 
 
562
        vst1.32         {d20[1]}, [r0,:32], r1
 
563
        vst1.32         {d20[0]}, [r0,:32], r1
 
564
        vst1.32         {d22[1]}, [r0,:32], r1
 
565
        vst1.32         {d22[0]}, [r0,:32]
 
566
 
 
567
        bx              lr
 
568
endfunc
 
569
 
 
570
@ Setup constants in registers which are used by vc1_inv_trans_4x4_helper
 
571
.macro vc1_inv_trans_4x4_helper_setup
 
572
        vmov.i16        q13, #17
 
573
        vmov.i16        q14, #22
 
574
        vmov.i16        d30, #10                @ only need double-word, not quad-word
 
575
.endm
 
576
 
 
577
@ This is modeled after the first for loop in vc1_inv_trans_4x4_c.
 
578
.macro vc1_inv_trans_4x4_helper add rshift
 
579
        vmov.i16        q2,  #\add              @ t1|t2 will accumulate here
 
580
 
 
581
        vadd.i16        d16, d0,  d1            @ temp1 = src[0] + src[2]
 
582
        vsub.i16        d17, d0,  d1            @ temp2 = src[0] - src[2]
 
583
        vmul.i16        q3,  q14, q1            @ t3|t4 = 22 * (src[1]|src[3])
 
584
        vmla.i16        q2,  q13, q8            @ t1|t2 = 17 * (temp1|temp2) + add
 
585
        vmla.i16        d6,  d30, d3            @ t3 += 10 * src[3]
 
586
        vmls.i16        d7,  d30, d2            @ t4 -= 10 * src[1]
 
587
 
 
588
        vadd.i16        q0,  q2,  q3            @ dst[0,2] = (t1|t2 + t3|t4)
 
589
        vsub.i16        q1,  q2,  q3            @ dst[3,1] = (t1|t2 - t3|t4)
 
590
        vshr.s16        q0,  q0,  #\rshift      @ dst[0,2] >>= rshift
 
591
        vshr.s16        q1,  q1,  #\rshift      @ dst[3,1] >>= rshift
 
592
.endm
 
593
 
 
594
@ (uint8_t *dest [r0], int linesize [r1], int16_t *block [r2])
 
595
function ff_vc1_inv_trans_4x4_neon, export=1
 
596
        mov             r12, #(8 * 2)  @ 8 elements per line, each element 2 bytes
 
597
        vld4.16         {d0[],  d1[],  d2[],  d3[]},  [r2,:64], r12     @ read each column into a register
 
598
        vld4.16         {d0[1], d1[1], d2[1], d3[1]}, [r2,:64], r12
 
599
        vld4.16         {d0[2], d1[2], d2[2], d3[2]}, [r2,:64], r12
 
600
        vld4.16         {d0[3], d1[3], d2[3], d3[3]}, [r2,:64]
 
601
 
 
602
        vswp            d1,  d2         @ so that we can later access column 1 and column 3 as a single q1 register
 
603
 
 
604
        vc1_inv_trans_4x4_helper_setup
 
605
 
 
606
        @ At this point:
 
607
        @   src[0] = d0
 
608
        @   src[1] = d2
 
609
        @   src[2] = d1
 
610
        @   src[3] = d3
 
611
 
 
612
        vc1_inv_trans_4x4_helper add=4 rshift=3      @ compute t1, t2, t3, t4 and combine them into dst[0-3]
 
613
 
 
614
        @ At this point:
 
615
        @   dst[0] = d0
 
616
        @   dst[1] = d3
 
617
        @   dst[2] = d1
 
618
        @   dst[3] = d2
 
619
 
 
620
        transpose16     d0 d3 d1 d2     @ Transpose rows (registers) into columns
 
621
 
 
622
        @ At this point:
 
623
        @   src[0]  = d0
 
624
        @   src[8]  = d3
 
625
        @   src[16] = d1
 
626
        @   src[24] = d2
 
627
 
 
628
        vswp            d2,  d3         @ so that we can later access column 1 and column 3 in order as a single q1 register
 
629
 
 
630
        @ At this point:
 
631
        @   src[0]  = d0
 
632
        @   src[8]  = d2
 
633
        @   src[16] = d1
 
634
        @   src[24] = d3
 
635
 
 
636
        vc1_inv_trans_4x4_helper add=64 rshift=7              @ compute t1, t2, t3, t4 and combine them into dst[0-3]
 
637
 
 
638
        @ At this point:
 
639
        @   line[0] = d0
 
640
        @   line[1] = d3
 
641
        @   line[2] = d1
 
642
        @   line[3] = d2
 
643
 
 
644
        vld1.32         {d18[]},  [r0,:32], r1  @ read dest
 
645
        vld1.32         {d19[]},  [r0,:32], r1
 
646
        vld1.32         {d18[1]}, [r0,:32], r1
 
647
        vld1.32         {d19[0]}, [r0,:32], r1
 
648
        sub             r0,  r0,  r1, lsl #2    @ restore original r0 value
 
649
 
 
650
        vaddw.u8        q0,  q0,  d18           @ line[0,2] += dest[0,2]
 
651
        vaddw.u8        q1,  q1,  d19           @ line[3,1] += dest[3,1]
 
652
 
 
653
        vqmovun.s16     d0,  q0                 @ clip(line[0,2])
 
654
        vqmovun.s16     d1,  q1                 @ clip(line[3,1])
 
655
 
 
656
        vst1.32         {d0[0]},  [r0,:32], r1  @ write dest
 
657
        vst1.32         {d1[1]},  [r0,:32], r1
 
658
        vst1.32         {d0[1]},  [r0,:32], r1
 
659
        vst1.32         {d1[0]},  [r0,:32]
 
660
 
 
661
        bx              lr
 
662
endfunc
 
663
 
 
664
@ The absolute value of multiplication constants from vc1_mspel_filter and vc1_mspel_{ver,hor}_filter_16bits.
 
665
@ The sign is embedded in the code below that carries out the multiplication (mspel_filter{,.16}).
 
666
#define MSPEL_MODE_1_MUL_CONSTANTS  4 53 18 3
 
667
#define MSPEL_MODE_2_MUL_CONSTANTS  1 9  9  1
 
668
#define MSPEL_MODE_3_MUL_CONSTANTS  3 18 53 4
 
669
 
 
670
@ These constants are from reading the source code of vc1_mspel_mc and determining the value that
 
671
@ is added to `rnd` to result in the variable `r`, and the value of the variable `shift`.
 
672
#define MSPEL_MODES_11_ADDSHIFT_CONSTANTS   15 5
 
673
#define MSPEL_MODES_12_ADDSHIFT_CONSTANTS   3  3
 
674
#define MSPEL_MODES_13_ADDSHIFT_CONSTANTS   15 5
 
675
#define MSPEL_MODES_21_ADDSHIFT_CONSTANTS   MSPEL_MODES_12_ADDSHIFT_CONSTANTS
 
676
#define MSPEL_MODES_22_ADDSHIFT_CONSTANTS   0  1
 
677
#define MSPEL_MODES_23_ADDSHIFT_CONSTANTS   3  3
 
678
#define MSPEL_MODES_31_ADDSHIFT_CONSTANTS   MSPEL_MODES_13_ADDSHIFT_CONSTANTS
 
679
#define MSPEL_MODES_32_ADDSHIFT_CONSTANTS   MSPEL_MODES_23_ADDSHIFT_CONSTANTS
 
680
#define MSPEL_MODES_33_ADDSHIFT_CONSTANTS   15 5
 
681
 
 
682
@ The addition and shift constants from vc1_mspel_filter.
 
683
#define MSPEL_MODE_1_ADDSHIFT_CONSTANTS     32 6
 
684
#define MSPEL_MODE_2_ADDSHIFT_CONSTANTS     8  4
 
685
#define MSPEL_MODE_3_ADDSHIFT_CONSTANTS     32 6
 
686
 
 
687
@ Setup constants in registers for a subsequent use of mspel_filter{,.16}.
 
688
.macro mspel_constants typesize reg_a reg_b reg_c reg_d filter_a filter_b filter_c filter_d reg_add filter_add_register
 
689
  @ Define double-word register aliases. Typesize should be i8 or i16.
 
690
  ra .dn \reg_a\().\typesize
 
691
  rb .dn \reg_b\().\typesize
 
692
  rc .dn \reg_c\().\typesize
 
693
  rd .dn \reg_d\().\typesize
 
694
 
 
695
  @ Only set the register if the value is not 1 and unique
 
696
  .if \filter_a != 1
 
697
        vmov            ra,  #\filter_a              @ ra = filter_a
 
698
  .endif
 
699
        vmov            rb,  #\filter_b              @ rb = filter_b
 
700
  .if \filter_b != \filter_c
 
701
        vmov            rc,  #\filter_c              @ rc = filter_c
 
702
  .endif
 
703
  .if \filter_d != 1
 
704
        vmov            rd,  #\filter_d              @ rd = filter_d
 
705
  .endif
 
706
  @ vdup to double the size of typesize
 
707
  .ifc \typesize,i8
 
708
        vdup.16         \reg_add,  \filter_add_register     @ reg_add = filter_add_register
 
709
  .else
 
710
        vdup.32         \reg_add,  \filter_add_register     @ reg_add = filter_add_register
 
711
  .endif
 
712
 
 
713
  .unreq ra
 
714
  .unreq rb
 
715
  .unreq rc
 
716
  .unreq rd
 
717
.endm
 
718
 
 
719
@ After mspel_constants has been used, do the filtering.
 
720
.macro mspel_filter acc dest src0 src1 src2 src3 filter_a filter_b filter_c filter_d reg_a reg_b reg_c reg_d reg_add filter_shift narrow=1
 
721
  .if \filter_a != 1
 
722
        @ If filter_a != 1, then we need a move and subtract instruction
 
723
        vmov            \acc,  \reg_add                     @ acc = reg_add
 
724
        vmlsl.u8        \acc,  \reg_a,  \src0               @ acc -= filter_a * src[-stride]
 
725
  .else
 
726
        @ If filter_a is 1, then just subtract without an extra move
 
727
        vsubw.u8        \acc,  \reg_add,  \src0             @ acc = reg_add - src[-stride]      @ since filter_a == 1
 
728
  .endif
 
729
        vmlal.u8        \acc,  \reg_b,  \src1               @ acc += filter_b * src[0]
 
730
  .if \filter_b != \filter_c
 
731
        vmlal.u8        \acc,  \reg_c,  \src2               @ acc += filter_c * src[stride]
 
732
  .else
 
733
        @ If filter_b is the same as filter_c, use the same reg_b register
 
734
        vmlal.u8        \acc,  \reg_b,  \src2               @ acc += filter_c * src[stride]     @ where filter_c == filter_b
 
735
  .endif
 
736
  .if \filter_d != 1
 
737
        @ If filter_d != 1, then do a multiply accumulate
 
738
        vmlsl.u8        \acc,  \reg_d,  \src3               @ acc -= filter_d * src[stride * 2]
 
739
  .else
 
740
        @ If filter_d is 1, then just do a subtract
 
741
        vsubw.u8        \acc,  \acc,    \src3               @ acc -= src[stride * 2]            @ since filter_d == 1
 
742
  .endif
 
743
  .if \narrow
 
744
        vqshrun.s16     \dest, \acc,    #\filter_shift      @ dest = clip_uint8(acc >> filter_shift)
 
745
  .else
 
746
        vshr.s16        \dest, \acc,    #\filter_shift      @ dest = acc >> filter_shift
 
747
  .endif
 
748
.endm
 
749
 
 
750
@ This is similar to mspel_filter, but the input is 16-bit instead of 8-bit and narrow=0 is not supported.
 
751
.macro mspel_filter.16 acc0 acc1 acc0_0 acc0_1 dest src0 src1 src2 src3 src4 src5 src6 src7 filter_a filter_b filter_c filter_d reg_a reg_b reg_c reg_d reg_add filter_shift
 
752
  .if \filter_a != 1
 
753
        vmov            \acc0,  \reg_add
 
754
        vmov            \acc1,  \reg_add
 
755
        vmlsl.s16       \acc0,  \reg_a,  \src0
 
756
        vmlsl.s16       \acc1,  \reg_a,  \src1
 
757
  .else
 
758
        vsubw.s16       \acc0,  \reg_add,  \src0
 
759
        vsubw.s16       \acc1,  \reg_add,  \src1
 
760
  .endif
 
761
        vmlal.s16       \acc0,  \reg_b,  \src2
 
762
        vmlal.s16       \acc1,  \reg_b,  \src3
 
763
  .if \filter_b != \filter_c
 
764
        vmlal.s16       \acc0,  \reg_c,  \src4
 
765
        vmlal.s16       \acc1,  \reg_c,  \src5
 
766
  .else
 
767
        vmlal.s16       \acc0,  \reg_b,  \src4
 
768
        vmlal.s16       \acc1,  \reg_b,  \src5
 
769
  .endif
 
770
  .if \filter_d != 1
 
771
        vmlsl.s16       \acc0,  \reg_d,  \src6
 
772
        vmlsl.s16       \acc1,  \reg_d,  \src7
 
773
  .else
 
774
        vsubw.s16       \acc0,  \acc0,   \src6
 
775
        vsubw.s16       \acc1,  \acc1,   \src7
 
776
  .endif
 
777
        @ Use acc0_0 and acc0_1 as temp space
 
778
        vqshrun.s32     \acc0_0, \acc0,  #\filter_shift     @ Shift and narrow with saturation from s32 to u16
 
779
        vqshrun.s32     \acc0_1, \acc1,  #\filter_shift
 
780
        vqmovn.u16      \dest,  \acc0                       @ Narrow with saturation from u16 to u8
 
781
.endm
 
782
 
 
783
@ Register usage for put_vc1_mspel_mc functions. Registers marked 'hv' are only used in put_vc1_mspel_mc_hv.
 
784
@
 
785
@   r0        adjusted dst
 
786
@   r1        adjusted src
 
787
@   r2        stride
 
788
@   r3        adjusted rnd
 
789
@   r4 [hv]   tmp
 
790
@   r11 [hv]  sp saved
 
791
@   r12       loop counter
 
792
@   d0        src[-stride]
 
793
@   d1        src[0]
 
794
@   d2        src[stride]
 
795
@   d3        src[stride * 2]
 
796
@   q0 [hv]   src[-stride]
 
797
@   q1 [hv]   src[0]
 
798
@   q2 [hv]   src[stride]
 
799
@   q3 [hv]   src[stride * 2]
 
800
@   d21       often result from mspel_filter
 
801
@   q11       accumulator 0
 
802
@   q12 [hv]  accumulator 1
 
803
@   q13       accumulator initial value
 
804
@   d28       filter_a
 
805
@   d29       filter_b
 
806
@   d30       filter_c
 
807
@   d31       filter_d
 
808
 
 
809
@ (uint8_t *dst [r0], const uint8_t *src [r1], ptrdiff_t stride [r2], int rnd [r3])
 
810
.macro put_vc1_mspel_mc_hv hmode vmode filter_h_a filter_h_b filter_h_c filter_h_d filter_v_a filter_v_b filter_v_c filter_v_d filter_add filter_shift
 
811
function ff_put_vc1_mspel_mc\hmode\()\vmode\()_neon, export=1
 
812
        push            {r4, r11, lr}
 
813
        mov             r11, sp                 @ r11 = stack pointer before realignmnet
 
814
A       bic             sp,  sp,  #15           @ sp = round down to multiple of 16 bytes
 
815
T       bic             r4,  r11, #15
 
816
T       mov             sp,  r4
 
817
        sub             sp,  sp,  #(8*2*16)     @ make space for 8 rows * 2 byte per element * 16 elements per row (to fit 11 actual elements per row)
 
818
        mov             r4,  sp                 @ r4 = int16_t tmp[8 * 16]
 
819
 
 
820
        sub             r1,  r1,  #1            @ src -= 1
 
821
  .if \filter_add != 0
 
822
        add             r3,  r3,  #\filter_add  @ r3 = filter_add + rnd
 
823
  .endif
 
824
        mov             r12, #8                 @ loop counter
 
825
        sub             r1,  r1,  r2            @ r1 = &src[-stride]      @ slide back
 
826
 
 
827
        @ Do vertical filtering from src into tmp
 
828
        mspel_constants i8 d28 d29 d30 d31 \filter_v_a \filter_v_b \filter_v_c \filter_v_d q13 r3
 
829
 
 
830
        vld1.64         {d0,d1}, [r1], r2
 
831
        vld1.64         {d2,d3}, [r1], r2
 
832
        vld1.64         {d4,d5}, [r1], r2
 
833
 
 
834
1:
 
835
        subs            r12,  r12,  #4
 
836
 
 
837
        vld1.64         {d6,d7}, [r1], r2
 
838
        mspel_filter    q11 q11 d0 d2 d4 d6 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
839
        mspel_filter    q12 q12 d1 d3 d5 d7 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
840
        vst1.64         {q11,q12}, [r4,:128]!   @ store and increment
 
841
 
 
842
        vld1.64         {d0,d1}, [r1], r2
 
843
        mspel_filter    q11 q11 d2 d4 d6 d0 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
844
        mspel_filter    q12 q12 d3 d5 d7 d1 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
845
        vst1.64         {q11,q12}, [r4,:128]!   @ store and increment
 
846
 
 
847
        vld1.64         {d2,d3}, [r1], r2
 
848
        mspel_filter    q11 q11 d4 d6 d0 d2 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
849
        mspel_filter    q12 q12 d5 d7 d1 d3 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
850
        vst1.64         {q11,q12}, [r4,:128]!   @ store and increment
 
851
 
 
852
        vld1.64         {d4,d5}, [r1], r2
 
853
        mspel_filter    q11 q11 d6 d0 d2 d4 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
854
        mspel_filter    q12 q12 d7 d1 d3 d5 \filter_v_a \filter_v_b \filter_v_c \filter_v_d d28 d29 d30 d31 q13 \filter_shift narrow=0
 
855
        vst1.64         {q11,q12}, [r4,:128]!   @ store and increment
 
856
 
 
857
        bne             1b
 
858
 
 
859
        rsb             r3,   r3,  #(64 + \filter_add)      @ r3 = (64 + filter_add) - r3
 
860
        mov             r12,  #8                @ loop counter
 
861
        mov             r4,   sp                @ r4 = tmp
 
862
 
 
863
        @ Do horizontal filtering from temp to dst
 
864
        mspel_constants i16 d28 d29 d30 d31 \filter_h_a \filter_h_b \filter_h_c \filter_h_d q13 r3
 
865
 
 
866
2:
 
867
        subs            r12,  r12,  #1
 
868
 
 
869
        vld1.64         {q0,q1}, [r4,:128]!     @ read one line of tmp
 
870
        vext.16         q2,   q0,   q1,  #2
 
871
        vext.16         q3,   q0,   q1,  #3
 
872
        vext.16         q1,   q0,   q1,  #1     @ do last because it writes to q1 which is read by the other vext instructions
 
873
 
 
874
        mspel_filter.16 q11 q12 d22 d23 d21 d0 d1 d2 d3 d4 d5 d6 d7 \filter_h_a \filter_h_b \filter_h_c \filter_h_d d28 d29 d30 d31 q13 7
 
875
 
 
876
        vst1.64         {d21}, [r0,:64], r2     @ store and increment dst
 
877
 
 
878
        bne             2b
 
879
 
 
880
        mov             sp,  r11
 
881
        pop             {r4, r11, pc}
 
882
endfunc
 
883
.endm
 
884
 
 
885
@ Use C preprocessor and assembler macros to expand to functions for horizontal and vertical filtering.
 
886
#define PUT_VC1_MSPEL_MC_HV(hmode, vmode)   \
 
887
    put_vc1_mspel_mc_hv hmode vmode \
 
888
        MSPEL_MODE_ ## hmode ## _MUL_CONSTANTS \
 
889
        MSPEL_MODE_ ## vmode ## _MUL_CONSTANTS \
 
890
        MSPEL_MODES_ ## hmode ## vmode ## _ADDSHIFT_CONSTANTS
 
891
 
 
892
PUT_VC1_MSPEL_MC_HV(1, 1)
 
893
PUT_VC1_MSPEL_MC_HV(1, 2)
 
894
PUT_VC1_MSPEL_MC_HV(1, 3)
 
895
PUT_VC1_MSPEL_MC_HV(2, 1)
 
896
PUT_VC1_MSPEL_MC_HV(2, 2)
 
897
PUT_VC1_MSPEL_MC_HV(2, 3)
 
898
PUT_VC1_MSPEL_MC_HV(3, 1)
 
899
PUT_VC1_MSPEL_MC_HV(3, 2)
 
900
PUT_VC1_MSPEL_MC_HV(3, 3)
 
901
 
 
902
#undef PUT_VC1_MSPEL_MC_HV
 
903
 
 
904
.macro  put_vc1_mspel_mc_h_only hmode filter_a filter_b filter_c filter_d filter_add filter_shift
 
905
function ff_put_vc1_mspel_mc\hmode\()0_neon, export=1
 
906
        rsb             r3,   r3,   #\filter_add        @ r3 = filter_add - r = filter_add - rnd
 
907
        mov             r12,  #8                        @ loop counter
 
908
        sub             r1,   r1,   #1                  @ slide back, using immediate
 
909
 
 
910
        mspel_constants i8 d28 d29 d30 d31 \filter_a \filter_b \filter_c \filter_d q13 r3
 
911
 
 
912
1:
 
913
        subs            r12,  r12,  #1
 
914
 
 
915
        vld1.64         {d0,d1}, [r1], r2               @ read 16 bytes even though we only need 11, also src += stride
 
916
        vext.8          d2,   d0,   d1,  #2
 
917
        vext.8          d3,   d0,   d1,  #3
 
918
        vext.8          d1,   d0,   d1,  #1             @ do last because it writes to d1 which is read by the other vext instructions
 
919
 
 
920
        mspel_filter    q11 d21 d0 d1 d2 d3 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift
 
921
 
 
922
        vst1.64         {d21}, [r0,:64], r2             @ store and increment dst
 
923
 
 
924
        bne             1b
 
925
 
 
926
        bx              lr
 
927
endfunc
 
928
.endm
 
929
 
 
930
@ Use C preprocessor and assembler macros to expand to functions for horizontal only filtering.
 
931
#define PUT_VC1_MSPEL_MC_H_ONLY(hmode) \
 
932
        put_vc1_mspel_mc_h_only hmode MSPEL_MODE_ ## hmode ## _MUL_CONSTANTS MSPEL_MODE_ ## hmode ## _ADDSHIFT_CONSTANTS
 
933
 
 
934
PUT_VC1_MSPEL_MC_H_ONLY(1)
 
935
PUT_VC1_MSPEL_MC_H_ONLY(2)
 
936
PUT_VC1_MSPEL_MC_H_ONLY(3)
 
937
 
 
938
#undef PUT_VC1_MSPEL_MC_H_ONLY
 
939
 
 
940
@ (uint8_t *dst [r0], const uint8_t *src [r1], ptrdiff_t stride [r2], int rnd [r3])
 
941
.macro put_vc1_mspel_mc_v_only vmode filter_a filter_b filter_c filter_d filter_add filter_shift
 
942
function ff_put_vc1_mspel_mc0\vmode\()_neon, export=1
 
943
        add             r3,   r3,   #\filter_add - 1    @ r3 = filter_add - r = filter_add - (1 - rnd) = filter_add - 1 + rnd
 
944
        mov             r12,  #8                        @ loop counter
 
945
        sub             r1,   r1,   r2                  @ r1 = &src[-stride]      @ slide back
 
946
 
 
947
        mspel_constants i8 d28 d29 d30 d31 \filter_a \filter_b \filter_c \filter_d q13 r3
 
948
 
 
949
        vld1.64         {d0},  [r1], r2                 @ d0 = src[-stride]
 
950
        vld1.64         {d1},  [r1], r2                 @ d1 = src[0]
 
951
        vld1.64         {d2},  [r1], r2                 @ d2 = src[stride]
 
952
 
 
953
1:
 
954
        subs            r12,  r12,  #4
 
955
 
 
956
        vld1.64         {d3},  [r1], r2                 @ d3 = src[stride * 2]
 
957
        mspel_filter    q11 d21 d0 d1 d2 d3 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift
 
958
        vst1.64         {d21}, [r0,:64], r2             @ store and increment dst
 
959
 
 
960
        vld1.64         {d0},  [r1], r2                 @ d0 = next line
 
961
        mspel_filter    q11 d21 d1 d2 d3 d0 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift
 
962
        vst1.64         {d21}, [r0,:64], r2             @ store and increment dst
 
963
 
 
964
        vld1.64         {d1},  [r1], r2                 @ d1 = next line
 
965
        mspel_filter    q11 d21 d2 d3 d0 d1 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift
 
966
        vst1.64         {d21}, [r0,:64], r2             @ store and increment dst
 
967
 
 
968
        vld1.64         {d2},  [r1], r2                 @ d2 = next line
 
969
        mspel_filter    q11 d21 d3 d0 d1 d2 \filter_a \filter_b \filter_c \filter_d d28 d29 d30 d31 q13 \filter_shift
 
970
        vst1.64         {d21}, [r0,:64], r2             @ store and increment dst
 
971
 
 
972
        bne             1b
 
973
 
 
974
        bx              lr
 
975
endfunc
 
976
.endm
 
977
 
 
978
@ Use C preprocessor and assembler macros to expand to functions for vertical only filtering.
 
979
#define PUT_VC1_MSPEL_MC_V_ONLY(vmode) \
 
980
        put_vc1_mspel_mc_v_only vmode MSPEL_MODE_ ## vmode ## _MUL_CONSTANTS MSPEL_MODE_ ## vmode ## _ADDSHIFT_CONSTANTS
 
981
 
 
982
PUT_VC1_MSPEL_MC_V_ONLY(1)
 
983
PUT_VC1_MSPEL_MC_V_ONLY(2)
 
984
PUT_VC1_MSPEL_MC_V_ONLY(3)
 
985
 
 
986
#undef PUT_VC1_MSPEL_MC_V_ONLY
 
987
 
 
988
function ff_put_pixels8x8_neon, export=1
 
989
        vld1.64         {d0}, [r1], r2
 
990
        vld1.64         {d1}, [r1], r2
 
991
        vld1.64         {d2}, [r1], r2
 
992
        vld1.64         {d3}, [r1], r2
 
993
        vld1.64         {d4}, [r1], r2
 
994
        vld1.64         {d5}, [r1], r2
 
995
        vld1.64         {d6}, [r1], r2
 
996
        vld1.64         {d7}, [r1]
 
997
        vst1.64         {d0}, [r0,:64], r2
 
998
        vst1.64         {d1}, [r0,:64], r2
 
999
        vst1.64         {d2}, [r0,:64], r2
 
1000
        vst1.64         {d3}, [r0,:64], r2
 
1001
        vst1.64         {d4}, [r0,:64], r2
 
1002
        vst1.64         {d5}, [r0,:64], r2
 
1003
        vst1.64         {d6}, [r0,:64], r2
 
1004
        vst1.64         {d7}, [r0,:64]
 
1005
        bx              lr
 
1006
endfunc
 
1007
 
 
1008
function ff_vc1_inv_trans_8x8_dc_neon, export=1
 
1009
        ldrsh           r2, [r2]              @ int dc = block[0];
 
1010
 
 
1011
        vld1.64         {d0},  [r0,:64], r1
 
1012
        vld1.64         {d1},  [r0,:64], r1
 
1013
        vld1.64         {d4},  [r0,:64], r1
 
1014
        vld1.64         {d5},  [r0,:64], r1
 
1015
 
 
1016
        add             r2, r2, r2, lsl #1    @ dc = (3 * dc +  1) >> 1;
 
1017
        vld1.64         {d6},  [r0,:64], r1
 
1018
        add             r2, r2, #1
 
1019
        vld1.64         {d7},  [r0,:64], r1
 
1020
        vld1.64         {d16}, [r0,:64], r1
 
1021
        vld1.64         {d17}, [r0,:64], r1
 
1022
        asr             r2, r2, #1
 
1023
 
 
1024
        sub             r0,  r0,  r1, lsl #3  @ restore r0 to original value
 
1025
 
 
1026
        add             r2, r2, r2, lsl #1    @ dc = (3 * dc + 16) >> 5;
 
1027
        add             r2, r2, #16
 
1028
        asr             r2, r2, #5
 
1029
 
 
1030
        vdup.16         q1,  r2               @ dc
 
1031
 
 
1032
        vaddw.u8        q9,   q1,  d0
 
1033
        vaddw.u8        q10,  q1,  d1
 
1034
        vaddw.u8        q11,  q1,  d4
 
1035
        vaddw.u8        q12,  q1,  d5
 
1036
        vqmovun.s16     d0,  q9
 
1037
        vqmovun.s16     d1,  q10
 
1038
        vqmovun.s16     d4,  q11
 
1039
        vst1.64         {d0},  [r0,:64], r1
 
1040
        vqmovun.s16     d5,  q12
 
1041
        vst1.64         {d1},  [r0,:64], r1
 
1042
        vaddw.u8        q13,  q1,  d6
 
1043
        vst1.64         {d4},  [r0,:64], r1
 
1044
        vaddw.u8        q14,  q1,  d7
 
1045
        vst1.64         {d5},  [r0,:64], r1
 
1046
        vaddw.u8        q15,  q1,  d16
 
1047
        vaddw.u8        q1,   q1,  d17        @ this destroys q1
 
1048
        vqmovun.s16     d6,  q13
 
1049
        vqmovun.s16     d7,  q14
 
1050
        vqmovun.s16     d16, q15
 
1051
        vqmovun.s16     d17, q1
 
1052
        vst1.64         {d6},  [r0,:64], r1
 
1053
        vst1.64         {d7},  [r0,:64], r1
 
1054
        vst1.64         {d16}, [r0,:64], r1
 
1055
        vst1.64         {d17}, [r0,:64]
 
1056
        bx              lr
 
1057
endfunc
 
1058
 
 
1059
function ff_vc1_inv_trans_8x4_dc_neon, export=1
 
1060
        ldrsh           r2, [r2]              @ int dc = block[0];
 
1061
 
 
1062
        vld1.64         {d0},  [r0,:64], r1
 
1063
        vld1.64         {d1},  [r0,:64], r1
 
1064
        vld1.64         {d4},  [r0,:64], r1
 
1065
        vld1.64         {d5},  [r0,:64], r1
 
1066
 
 
1067
        add             r2, r2, r2, lsl #1    @ dc = ( 3 * dc +  1) >> 1;
 
1068
 
 
1069
        sub             r0,  r0,  r1, lsl #2  @ restore r0 to original value
 
1070
 
 
1071
        add             r2, r2, #1
 
1072
        asr             r2, r2, #1
 
1073
 
 
1074
        add             r2, r2, r2, lsl #4    @ dc = (17 * dc + 64) >> 7;
 
1075
        add             r2, r2, #64
 
1076
        asr             r2, r2, #7
 
1077
 
 
1078
        vdup.16         q1,  r2               @ dc
 
1079
 
 
1080
        vaddw.u8        q3,  q1,  d0
 
1081
        vaddw.u8        q8,  q1,  d1
 
1082
        vaddw.u8        q9,  q1,  d4
 
1083
        vaddw.u8        q10, q1,  d5
 
1084
        vqmovun.s16     d0,  q3
 
1085
        vqmovun.s16     d1,  q8
 
1086
        vqmovun.s16     d4,  q9
 
1087
        vst1.64         {d0},  [r0,:64], r1
 
1088
        vqmovun.s16     d5,  q10
 
1089
        vst1.64         {d1},  [r0,:64], r1
 
1090
        vst1.64         {d4},  [r0,:64], r1
 
1091
        vst1.64         {d5},  [r0,:64]
 
1092
        bx              lr
 
1093
endfunc
 
1094
 
 
1095
function ff_vc1_inv_trans_4x8_dc_neon, export=1
 
1096
        ldrsh           r2, [r2]              @ int dc = block[0];
 
1097
 
 
1098
        vld1.32         {d0[]},   [r0,:32], r1
 
1099
        vld1.32         {d1[]},   [r0,:32], r1
 
1100
        vld1.32         {d0[1]},  [r0,:32], r1
 
1101
        vld1.32         {d1[1]},  [r0,:32], r1
 
1102
 
 
1103
        add             r2, r2, r2, lsl #4    @ dc = (17 * dc +  4) >> 3;
 
1104
        vld1.32         {d4[]},   [r0,:32], r1
 
1105
        add             r2, r2, #4
 
1106
        vld1.32         {d5[]},   [r0,:32], r1
 
1107
        vld1.32         {d4[1]},  [r0,:32], r1
 
1108
        asr             r2, r2, #3
 
1109
        vld1.32         {d5[1]},  [r0,:32], r1
 
1110
 
 
1111
        add             r2, r2, r2, lsl #1    @ dc = (12 * dc + 64) >> 7;
 
1112
 
 
1113
        sub             r0,  r0,  r1, lsl #3  @ restore r0 to original value
 
1114
 
 
1115
        lsl             r2, r2, #2
 
1116
        add             r2, r2, #64
 
1117
        asr             r2, r2, #7
 
1118
 
 
1119
        vdup.16         q1,  r2               @ dc
 
1120
 
 
1121
        vaddw.u8        q3,  q1,  d0
 
1122
        vaddw.u8        q8,  q1,  d1
 
1123
        vaddw.u8        q9,  q1,  d4
 
1124
        vaddw.u8        q10, q1,  d5
 
1125
        vqmovun.s16     d0,  q3
 
1126
        vst1.32         {d0[0]},  [r0,:32], r1
 
1127
        vqmovun.s16     d1,  q8
 
1128
        vst1.32         {d1[0]},  [r0,:32], r1
 
1129
        vqmovun.s16     d4,  q9
 
1130
        vst1.32         {d0[1]},  [r0,:32], r1
 
1131
        vqmovun.s16     d5,  q10
 
1132
        vst1.32         {d1[1]},  [r0,:32], r1
 
1133
        vst1.32         {d4[0]},  [r0,:32], r1
 
1134
        vst1.32         {d5[0]},  [r0,:32], r1
 
1135
        vst1.32         {d4[1]},  [r0,:32], r1
 
1136
        vst1.32         {d5[1]},  [r0,:32]
 
1137
        bx              lr
 
1138
endfunc
 
1139
 
 
1140
function ff_vc1_inv_trans_4x4_dc_neon, export=1
 
1141
        ldrsh           r2, [r2]              @ int dc = block[0];
 
1142
 
 
1143
        vld1.32         {d0[]},   [r0,:32], r1
 
1144
        vld1.32         {d1[]},   [r0,:32], r1
 
1145
        vld1.32         {d0[1]},  [r0,:32], r1
 
1146
        vld1.32         {d1[1]},  [r0,:32], r1
 
1147
 
 
1148
        add             r2, r2, r2, lsl #4    @ dc = (17 * dc +  4) >> 3;
 
1149
 
 
1150
        sub             r0,  r0,  r1, lsl #2  @ restore r0 to original value
 
1151
 
 
1152
        add             r2, r2, #4
 
1153
        asr             r2, r2, #3
 
1154
 
 
1155
        add             r2, r2, r2, lsl #4    @ dc = (17 * dc + 64) >> 7;
 
1156
        add             r2, r2, #64
 
1157
        asr             r2, r2, #7
 
1158
 
 
1159
        vdup.16         q1,  r2               @ dc
 
1160
 
 
1161
        vaddw.u8        q2,  q1,  d0
 
1162
        vaddw.u8        q3,  q1,  d1
 
1163
        vqmovun.s16     d0,  q2
 
1164
        vst1.32         {d0[0]},  [r0,:32], r1
 
1165
        vqmovun.s16     d1,  q3
 
1166
        vst1.32         {d1[0]},  [r0,:32], r1
 
1167
        vst1.32         {d0[1]},  [r0,:32], r1
 
1168
        vst1.32         {d1[1]},  [r0,:32]
 
1169
        bx              lr
 
1170
endfunc