]> git.sesse.net Git - x264/blob - common/arm/predict-a.S
Fix overflow in ARM NEON i16x16 planar pred
[x264] / common / arm / predict-a.S
1 /*****************************************************************************
2  * predict.S: arm intra prediction
3  *****************************************************************************
4  * Copyright (C) 2009-2011 x264 project
5  *
6  * Authors: David Conrad <lessen42@gmail.com>
7  *          Mans Rullgard <mans@mansr.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program 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
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
22  *
23  * This program is also available under a commercial proprietary license.
24  * For more information, contact us at licensing@x264.com.
25  *****************************************************************************/
26
27 #include "asm.S"
28
29 .fpu neon
30
31 .section .rodata
32 .align 4
33
34 p16weight: .short 1,2,3,4,5,6,7,8
35
36 .text
37
38 .macro ldcol.8  rd,  rs,  rt,  n=8,  hi=0
39 .if \n == 8 || \hi == 0
40     vld1.8          {\rd[0]}, [\rs], \rt
41     vld1.8          {\rd[1]}, [\rs], \rt
42     vld1.8          {\rd[2]}, [\rs], \rt
43     vld1.8          {\rd[3]}, [\rs], \rt
44 .endif
45 .if \n == 8 || \hi == 1
46     vld1.8          {\rd[4]}, [\rs], \rt
47     vld1.8          {\rd[5]}, [\rs], \rt
48     vld1.8          {\rd[6]}, [\rs], \rt
49     vld1.8          {\rd[7]}, [\rs], \rt
50 .endif
51 .endm
52
53 .macro add16x8  dq,  dl,  dh,  rl,  rh
54     vaddl.u8        \dq, \rl, \rh
55     vadd.u16        \dl, \dl, \dh
56     vpadd.u16       \dl, \dl, \dl
57     vpadd.u16       \dl, \dl, \dl
58 .endm
59
60
61 // because gcc doesn't believe in using the free shift in add
62 function x264_predict_4x4_h_armv6
63     ldrb    r1, [r0, #0*FDEC_STRIDE-1]
64     ldrb    r2, [r0, #1*FDEC_STRIDE-1]
65     ldrb    r3, [r0, #2*FDEC_STRIDE-1]
66     ldrb    ip, [r0, #3*FDEC_STRIDE-1]
67     add     r1, r1, r1, lsl #8
68     add     r2, r2, r2, lsl #8
69     add     r3, r3, r3, lsl #8
70     add     ip, ip, ip, lsl #8
71     add     r1, r1, r1, lsl #16
72     str     r1, [r0, #0*FDEC_STRIDE]
73     add     r2, r2, r2, lsl #16
74     str     r2, [r0, #1*FDEC_STRIDE]
75     add     r3, r3, r3, lsl #16
76     str     r3, [r0, #2*FDEC_STRIDE]
77     add     ip, ip, ip, lsl #16
78     str     ip, [r0, #3*FDEC_STRIDE]
79     bx      lr
80 .endfunc
81
82 function x264_predict_4x4_dc_armv6
83     mov     ip, #0
84     ldr     r1, [r0, #-FDEC_STRIDE]
85     ldrb    r2, [r0, #0*FDEC_STRIDE-1]
86     ldrb    r3, [r0, #1*FDEC_STRIDE-1]
87     usad8   r1, r1, ip
88     add     r2, r2, #4
89     ldrb    ip, [r0, #2*FDEC_STRIDE-1]
90     add     r2, r2, r3
91     ldrb    r3, [r0, #3*FDEC_STRIDE-1]
92     add     r2, r2, ip
93     add     r2, r2, r3
94     add     r1, r1, r2
95     lsr     r1, r1, #3
96     add     r1, r1, r1, lsl #8
97     add     r1, r1, r1, lsl #16
98     str     r1, [r0, #0*FDEC_STRIDE]
99     str     r1, [r0, #1*FDEC_STRIDE]
100     str     r1, [r0, #2*FDEC_STRIDE]
101     str     r1, [r0, #3*FDEC_STRIDE]
102     bx      lr
103 .endfunc
104
105 // return a1 = (a1+2*b1+c1+2)>>2  a2 = (a2+2*b2+c2+2)>>2
106 .macro PRED4x4_LOWPASS a1 b1 c1 a2 b2 c2 pb_1
107     uhadd8  \a1, \a1, \c1
108     uhadd8  \a2, \a2, \c2
109     uhadd8  \c1, \a1, \b1
110     uhadd8  \c2, \a2, \b2
111     eor     \a1, \a1, \b1
112     eor     \a2, \a2, \b2
113     and     \a1, \a1, \pb_1
114     and     \a2, \a2, \pb_1
115     uadd8   \a1, \a1, \c1
116     uadd8   \a2, \a2, \c2
117 .endm
118
119 function x264_predict_4x4_ddr_armv6
120     ldr     r1, [r0, # -FDEC_STRIDE]
121     ldrb    r2, [r0, # -FDEC_STRIDE-1]
122     ldrb    r3, [r0, #0*FDEC_STRIDE-1]
123     push    {r4-r6,lr}
124     add     r2, r2, r1, lsl #8
125     ldrb    r4, [r0, #1*FDEC_STRIDE-1]
126     add     r3, r3, r2, lsl #8
127     ldrb    r5, [r0, #2*FDEC_STRIDE-1]
128     ldrb    r6, [r0, #3*FDEC_STRIDE-1]
129     add     r4, r4, r3, lsl #8
130     add     r5, r5, r4, lsl #8
131     add     r6, r6, r5, lsl #8
132     ldr     ip, =0x01010101
133     PRED4x4_LOWPASS r1, r2, r3, r4, r5, r6, ip
134     str     r1, [r0, #0*FDEC_STRIDE]
135     lsl     r2, r1, #8
136     lsl     r3, r1, #16
137     lsl     r4, r4, #8
138     lsl     r5, r1, #24
139     add     r2, r2, r4, lsr #24
140     str     r2, [r0, #1*FDEC_STRIDE]
141     add     r3, r3, r4, lsr #16
142     str     r3, [r0, #2*FDEC_STRIDE]
143     add     r5, r5, r4, lsr #8
144     str     r5, [r0, #3*FDEC_STRIDE]
145     pop     {r4-r6,pc}
146 .endfunc
147
148 function x264_predict_4x4_ddl_neon
149     sub         r0, #FDEC_STRIDE
150     mov         ip, #FDEC_STRIDE
151     vld1.64     {d0}, [r0], ip
152     vdup.8      d3, d0[7]
153     vext.8      d1, d0, d0, #1
154     vext.8      d2, d0, d3, #2
155     vhadd.u8    d0, d0, d2
156     vrhadd.u8   d0, d0, d1
157     vst1.32     {d0[0]}, [r0,:32], ip
158     vext.8      d1, d0, d0, #1
159     vext.8      d2, d0, d0, #2
160     vst1.32     {d1[0]}, [r0,:32], ip
161     vext.8      d3, d0, d0, #3
162     vst1.32     {d2[0]}, [r0,:32], ip
163     vst1.32     {d3[0]}, [r0,:32], ip
164     bx          lr
165 .endfunc
166
167 function x264_predict_8x8_dc_neon
168     mov     ip, #0
169     ldrd    r2, [r1, #8]
170     push    {r4-r5,lr}
171     ldrd    r4, [r1, #16]
172     lsl     r3, r3, #8
173     ldrb    lr, [r1, #7]
174     usad8   r2, r2, ip
175     usad8   r3, r3, ip
176     usada8  r2, r4, ip, r2
177     add     lr, lr, #8
178     usada8  r3, r5, ip, r3
179     add     r2, r2, lr
180     mov     ip, #FDEC_STRIDE
181     add     r2, r2, r3
182     lsr     r2, r2, #4
183
184     vdup.8   d0, r2
185 .rept 8
186     vst1.64 {d0}, [r0,:64], ip
187 .endr
188     pop    {r4-r5,pc}
189 .endfunc
190
191 function x264_predict_8x8_h_neon
192     add         r1, r1, #7
193     mov         ip, #FDEC_STRIDE
194     vld1.64     {d16}, [r1]
195     vdup.8      d0, d16[7]
196     vdup.8      d1, d16[6]
197     vst1.64     {d0}, [r0,:64], ip
198     vdup.8      d2, d16[5]
199     vst1.64     {d1}, [r0,:64], ip
200     vdup.8      d3, d16[4]
201     vst1.64     {d2}, [r0,:64], ip
202     vdup.8      d4, d16[3]
203     vst1.64     {d3}, [r0,:64], ip
204     vdup.8      d5, d16[2]
205     vst1.64     {d4}, [r0,:64], ip
206     vdup.8      d6, d16[1]
207     vst1.64     {d5}, [r0,:64], ip
208     vdup.8      d7, d16[0]
209     vst1.64     {d6}, [r0,:64], ip
210     vst1.64     {d7}, [r0,:64], ip
211     bx          lr
212 .endfunc
213
214
215 function x264_predict_8x8c_dc_top_neon
216     sub         r2,  r0,  #FDEC_STRIDE
217     mov         r1,  #FDEC_STRIDE
218     vld1.8      {d0}, [r2,:64]
219     vpaddl.u8   d0,  d0
220     vpadd.u16   d0,  d0,  d0
221     vrshrn.u16  d0,  q0,  #2
222     vdup.8      d1,  d0[1]
223     vdup.8      d0,  d0[0]
224     vtrn.32     d0,  d1
225     b           pred8x8_dc_end
226     .endfunc
227
228 function x264_predict_8x8c_dc_left_neon
229     mov         r1,  #FDEC_STRIDE
230     sub         r2,  r0,  #1
231     ldcol.8     d0,  r2,  r1
232     vpaddl.u8   d0,  d0
233     vpadd.u16   d0,  d0,  d0
234     vrshrn.u16  d0,  q0,  #2
235     vdup.8      d1,  d0[1]
236     vdup.8      d0,  d0[0]
237     b           pred8x8_dc_end
238 .endfunc
239
240 function x264_predict_8x8c_dc_neon
241     sub         r2,  r0,  #FDEC_STRIDE
242     mov         r1,  #FDEC_STRIDE
243     vld1.8      {d0}, [r2,:64]
244     sub         r2,  r0,  #1
245     ldcol.8     d1,  r2,  r1
246     vtrn.32     d0,  d1
247     vpaddl.u8   q0,  q0
248     vpadd.u16   d0,  d0,  d1
249     vpadd.u16   d1,  d0,  d0
250     vrshrn.u16  d2,  q0,  #3
251     vrshrn.u16  d3,  q0,  #2
252     vdup.8      d0,  d2[4]
253     vdup.8      d1,  d3[3]
254     vdup.8      d4,  d3[2]
255     vdup.8      d5,  d2[5]
256     vtrn.32     q0,  q2
257 pred8x8_dc_end:
258     add         r2,  r0,  r1,  lsl #2
259 .rept 4
260     vst1.8      {d0}, [r0,:64], r1
261     vst1.8      {d1}, [r2,:64], r1
262 .endr
263     bx          lr
264 .endfunc
265
266 function x264_predict_8x8c_h_neon
267     sub         r1, r0, #1
268     mov         ip, #FDEC_STRIDE
269 .rept 4
270     vld1.8      {d0[]}, [r1], ip
271     vld1.8      {d2[]}, [r1], ip
272     vst1.64     {d0}, [r0,:64], ip
273     vst1.64     {d2}, [r0,:64], ip
274 .endr
275     bx          lr
276 .endfunc
277
278 function x264_predict_8x8c_v_neon
279     sub         r0, r0, #FDEC_STRIDE
280     mov         ip, #FDEC_STRIDE
281     vld1.64     {d0}, [r0,:64], ip
282 .rept 8
283     vst1.64     {d0}, [r0,:64], ip
284 .endr
285     bx          lr
286 .endfunc
287
288 function x264_predict_8x8c_p_neon
289     sub         r3,  r0,  #FDEC_STRIDE
290     mov         r1,  #FDEC_STRIDE
291     add         r2,  r3,  #4
292     sub         r3,  r3,  #1
293     vld1.32     {d0[0]}, [r3]
294     vld1.32     {d2[0]}, [r2,:32], r1
295     ldcol.8     d0,  r3,  r1,  4,  hi=1
296     add         r3,  r3,  r1
297     ldcol.8     d3,  r3,  r1,  4
298     vaddl.u8    q8,  d2,  d3
299     vrev32.8    d0,  d0
300     vtrn.32     d2,  d3
301     vsubl.u8    q2,  d2,  d0
302     movrel      r3,  p16weight
303     vld1.16     {q0}, [r3,:128]
304     vmul.s16    d4,  d4,  d0
305     vmul.s16    d5,  d5,  d0
306     vpadd.i16   d4,  d4,  d5
307     vpaddl.s16  d4,  d4
308     vshl.i32    d5,  d4,  #4
309     vadd.s32    d4,  d4,  d5
310     vrshrn.s32  d4,  q2,  #5
311     mov         r3,  #0
312     vtrn.16     d4,  d5
313     vadd.i16    d2,  d4,  d5
314     vshl.i16    d3,  d2,  #2
315     vrev64.16   d16, d16
316     vsub.i16    d3,  d3,  d2
317     vadd.i16    d16, d16, d0
318     vshl.i16    d2,  d16, #4
319     vsub.i16    d2,  d2,  d3
320     vshl.i16    d3,  d4,  #3
321     vext.16     q0,  q0,  q0,  #7
322     vsub.i16    d6,  d5,  d3
323     vmov.16     d0[0], r3
324     vmul.i16    q0,  q0,  d4[0]
325     vdup.16     q1,  d2[0]
326     vdup.16     q2,  d4[0]
327     vdup.16     q3,  d6[0]
328     vshl.i16    q2,  q2,  #3
329     vadd.i16    q1,  q1,  q0
330     vadd.i16    q3,  q3,  q2
331     mov         r3,  #8
332 1:
333     vqshrun.s16 d0,  q1,  #5
334     vadd.i16    q1,  q1,  q3
335     vst1.8      {d0}, [r0,:64], r1
336     subs        r3,  r3,  #1
337     bne         1b
338     bx          lr
339 .endfunc
340
341
342 function x264_predict_16x16_dc_top_neon
343     sub         r2,  r0,  #FDEC_STRIDE
344     mov         r1,  #FDEC_STRIDE
345     vld1.8      {q0}, [r2,:128]
346     add16x8     q0,  d0,  d1,  d0,  d1
347     vrshrn.u16  d0,  q0,  #4
348     vdup.8      q0,  d0[0]
349     b           pred16x16_dc_end
350 .endfunc
351
352 function x264_predict_16x16_dc_left_neon
353     mov         r1,  #FDEC_STRIDE
354     sub         r2,  r0,  #1
355     ldcol.8     d0,  r2,  r1
356     ldcol.8     d1,  r2,  r1
357     add16x8     q0,  d0,  d1,  d0,  d1
358     vrshrn.u16  d0,  q0,  #4
359     vdup.8      q0,  d0[0]
360     b           pred16x16_dc_end
361 .endfunc
362
363 function x264_predict_16x16_dc_neon
364     sub         r3, r0, #FDEC_STRIDE
365     sub         r0, r0, #1
366     vld1.64     {d0-d1}, [r3,:128]
367     ldrb        ip, [r0], #FDEC_STRIDE
368     vaddl.u8    q0, d0, d1
369     ldrb        r1, [r0], #FDEC_STRIDE
370     vadd.u16    d0, d0, d1
371     vpadd.u16   d0, d0, d0
372     vpadd.u16   d0, d0, d0
373 .rept 4
374     ldrb        r2, [r0], #FDEC_STRIDE
375     add         ip, ip, r1
376     ldrb        r3, [r0], #FDEC_STRIDE
377     add         ip, ip, r2
378     ldrb        r1, [r0], #FDEC_STRIDE
379     add         ip, ip, r3
380 .endr
381     ldrb        r2, [r0], #FDEC_STRIDE
382     add         ip, ip, r1
383     ldrb        r3, [r0], #FDEC_STRIDE
384     add         ip, ip, r2
385
386     sub         r0, r0, #FDEC_STRIDE*16
387     add         ip, ip, r3
388     vdup.16     d1, ip
389     vadd.u16    d0, d0, d1
390     mov         r1, #FDEC_STRIDE
391     add         r0, r0, #1
392     vrshr.u16   d0, d0, #5
393     vdup.8      q0, d0[0]
394 pred16x16_dc_end:
395 .rept 16
396     vst1.64     {d0-d1}, [r0,:128], r1
397 .endr
398     bx          lr
399 .endfunc
400
401 function x264_predict_16x16_h_neon
402     sub         r1, r0, #1
403     mov         ip, #FDEC_STRIDE
404 .rept 8
405     vld1.8      {d0[]}, [r1], ip
406     vmov        d1, d0
407     vld1.8      {d2[]}, [r1], ip
408     vmov        d3, d2
409     vst1.64     {d0-d1}, [r0,:128], ip
410     vst1.64     {d2-d3}, [r0,:128], ip
411 .endr
412     bx          lr
413 .endfunc
414
415 function x264_predict_16x16_v_neon
416     sub         r0, r0, #FDEC_STRIDE
417     mov         ip, #FDEC_STRIDE
418     vld1.64     {d0-d1}, [r0,:128], ip
419 .rept 16
420     vst1.64     {d0-d1}, [r0,:128], ip
421 .endr
422     bx          lr
423 .endfunc
424
425 function x264_predict_16x16_p_neon
426     sub         r3,  r0,  #FDEC_STRIDE
427     mov         r1,  #FDEC_STRIDE
428     add         r2,  r3,  #8
429     sub         r3,  r3,  #1
430     vld1.8      {d0}, [r3]
431     vld1.8      {d2}, [r2,:64], r1
432     ldcol.8     d1,  r3,  r1
433     add         r3,  r3,  r1
434     ldcol.8     d3,  r3,  r1
435     vrev64.8    q0,  q0
436     vaddl.u8    q8,  d2,  d3
437     vsubl.u8    q2,  d2,  d0
438     vsubl.u8    q3,  d3,  d1
439     movrel      r3,  p16weight
440     vld1.8      {q0}, [r3,:128]
441     vmul.s16    q2,  q2,  q0
442     vmul.s16    q3,  q3,  q0
443     vadd.i16    d4,  d4,  d5
444     vadd.i16    d5,  d6,  d7
445     vpadd.i16   d4,  d4,  d5
446     vpadd.i16   d4,  d4,  d4
447     vshll.s16   q3,  d4,  #2
448     vaddw.s16   q2,  q3,  d4
449     vrshrn.s32  d4,  q2,  #6
450     mov         r3,  #0
451     vtrn.16     d4,  d5
452     vadd.i16    d2,  d4,  d5
453     vshl.i16    d3,  d2,  #3
454     vrev64.16   d16, d17
455     vsub.i16    d3,  d3,  d2
456     vadd.i16    d16, d16, d0
457     vshl.i16    d2,  d16, #4
458     vsub.i16    d2,  d2,  d3
459     vshl.i16    d3,  d4,  #4
460     vext.16     q0,  q0,  q0,  #7
461     vsub.i16    d6,  d5,  d3
462     vmov.16     d0[0], r3
463     vmul.i16    q0,  q0,  d4[0]
464     vdup.16     q1,  d2[0]
465     vdup.16     q2,  d4[0]
466     vdup.16     q3,  d6[0]
467     vshl.i16    q2,  q2,  #3
468     vadd.i16    q1,  q1,  q0
469     vadd.i16    q3,  q3,  q2
470     mov         r3,  #16
471 1:
472     vqshrun.s16 d0,  q1,  #5
473     vadd.i16    q1,  q1,  q2
474     vqshrun.s16 d1,  q1,  #5
475     vadd.i16    q1,  q1,  q3
476     vst1.8      {q0}, [r0,:128], r1
477     subs        r3,  r3,  #1
478     bne         1b
479     bx          lr
480 .endfunc