Fix TEXTRELs in the ARM asm.
[profile/ivi/libvpx.git] / vp8 / common / arm / neon / mbloopfilter_neon.asm
1 ;
2 ;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 ;
4 ;  Use of this source code is governed by a BSD-style license
5 ;  that can be found in the LICENSE file in the root of the source
6 ;  tree. An additional intellectual property rights grant can be found
7 ;  in the file PATENTS.  All contributing project authors may
8 ;  be found in the AUTHORS file in the root of the source tree.
9 ;
10
11
12     EXPORT  |vp8_mbloop_filter_horizontal_edge_y_neon|
13     EXPORT  |vp8_mbloop_filter_horizontal_edge_uv_neon|
14     EXPORT  |vp8_mbloop_filter_vertical_edge_y_neon|
15     EXPORT  |vp8_mbloop_filter_vertical_edge_uv_neon|
16     ARM
17
18     AREA ||.text||, CODE, READONLY, ALIGN=2
19
20 ; void vp8_mbloop_filter_horizontal_edge_y_neon(unsigned char *src, int pitch,
21 ;                                               const unsigned char *blimit,
22 ;                                               const unsigned char *limit,
23 ;                                               const unsigned char *thresh)
24 ; r0    unsigned char *src,
25 ; r1    int pitch,
26 ; r2    unsigned char blimit
27 ; r3    unsigned char limit
28 ; sp    unsigned char thresh,
29 |vp8_mbloop_filter_horizontal_edge_y_neon| PROC
30     push        {lr}
31     add         r1, r1, r1                  ; double stride
32     ldr         r12, [sp, #4]               ; load thresh
33     sub         r0, r0, r1, lsl #1          ; move src pointer down by 4 lines
34     vdup.u8     q2, r12                     ; thresh
35     add         r12, r0, r1,  lsr #1        ; move src pointer up by 1 line
36
37     vld1.u8     {q3}, [r0@128], r1              ; p3
38     vld1.u8     {q4}, [r12@128], r1             ; p2
39     vld1.u8     {q5}, [r0@128], r1              ; p1
40     vld1.u8     {q6}, [r12@128], r1             ; p0
41     vld1.u8     {q7}, [r0@128], r1              ; q0
42     vld1.u8     {q8}, [r12@128], r1             ; q1
43     vld1.u8     {q9}, [r0@128], r1              ; q2
44     vld1.u8     {q10}, [r12@128], r1            ; q3
45
46     bl          vp8_mbloop_filter_neon
47
48     sub         r12, r12, r1, lsl #2
49     add         r0, r12, r1, lsr #1
50
51     vst1.u8     {q4}, [r12@128],r1         ; store op2
52     vst1.u8     {q5}, [r0@128],r1          ; store op1
53     vst1.u8     {q6}, [r12@128], r1        ; store op0
54     vst1.u8     {q7}, [r0@128],r1          ; store oq0
55     vst1.u8     {q8}, [r12@128]            ; store oq1
56     vst1.u8     {q9}, [r0@128]             ; store oq2
57
58     pop         {pc}
59     ENDP        ; |vp8_mbloop_filter_horizontal_edge_y_neon|
60
61 ; void vp8_mbloop_filter_horizontal_edge_uv_neon(unsigned char *u, int pitch,
62 ;                                                const unsigned char *blimit,
63 ;                                                const unsigned char *limit,
64 ;                                                const unsigned char *thresh,
65 ;                                                unsigned char *v)
66 ; r0    unsigned char *u,
67 ; r1    int pitch,
68 ; r2    unsigned char blimit
69 ; r3    unsigned char limit
70 ; sp    unsigned char thresh,
71 ; sp+4  unsigned char *v
72
73 |vp8_mbloop_filter_horizontal_edge_uv_neon| PROC
74     push        {lr}
75     ldr         r12, [sp, #4]                 ; load thresh
76     sub         r0, r0, r1, lsl #2            ; move u pointer down by 4 lines
77     vdup.u8     q2, r12                       ; thresh
78     ldr         r12, [sp, #8]                 ; load v ptr
79     sub         r12, r12, r1, lsl #2          ; move v pointer down by 4 lines
80
81     vld1.u8     {d6}, [r0@64], r1              ; p3
82     vld1.u8     {d7}, [r12@64], r1              ; p3
83     vld1.u8     {d8}, [r0@64], r1              ; p2
84     vld1.u8     {d9}, [r12@64], r1              ; p2
85     vld1.u8     {d10}, [r0@64], r1             ; p1
86     vld1.u8     {d11}, [r12@64], r1             ; p1
87     vld1.u8     {d12}, [r0@64], r1             ; p0
88     vld1.u8     {d13}, [r12@64], r1             ; p0
89     vld1.u8     {d14}, [r0@64], r1             ; q0
90     vld1.u8     {d15}, [r12@64], r1             ; q0
91     vld1.u8     {d16}, [r0@64], r1             ; q1
92     vld1.u8     {d17}, [r12@64], r1             ; q1
93     vld1.u8     {d18}, [r0@64], r1             ; q2
94     vld1.u8     {d19}, [r12@64], r1             ; q2
95     vld1.u8     {d20}, [r0@64], r1             ; q3
96     vld1.u8     {d21}, [r12@64], r1             ; q3
97
98     bl          vp8_mbloop_filter_neon
99
100     sub         r0, r0, r1, lsl #3
101     sub         r12, r12, r1, lsl #3
102
103     add         r0, r0, r1
104     add         r12, r12, r1
105
106     vst1.u8     {d8}, [r0@64], r1              ; store u op2
107     vst1.u8     {d9}, [r12@64], r1              ; store v op2
108     vst1.u8     {d10}, [r0@64], r1             ; store u op1
109     vst1.u8     {d11}, [r12@64], r1             ; store v op1
110     vst1.u8     {d12}, [r0@64], r1             ; store u op0
111     vst1.u8     {d13}, [r12@64], r1             ; store v op0
112     vst1.u8     {d14}, [r0@64], r1             ; store u oq0
113     vst1.u8     {d15}, [r12@64], r1             ; store v oq0
114     vst1.u8     {d16}, [r0@64], r1             ; store u oq1
115     vst1.u8     {d17}, [r12@64], r1             ; store v oq1
116     vst1.u8     {d18}, [r0@64], r1             ; store u oq2
117     vst1.u8     {d19}, [r12@64], r1             ; store v oq2
118
119     pop         {pc}
120     ENDP        ; |vp8_mbloop_filter_horizontal_edge_uv_neon|
121
122 ; void vp8_mbloop_filter_vertical_edge_y_neon(unsigned char *src, int pitch,
123 ;                                             const unsigned char *blimit,
124 ;                                             const unsigned char *limit,
125 ;                                             const unsigned char *thresh)
126 ; r0    unsigned char *src,
127 ; r1    int pitch,
128 ; r2    unsigned char blimit
129 ; r3    unsigned char limit
130 ; sp    unsigned char thresh,
131 |vp8_mbloop_filter_vertical_edge_y_neon| PROC
132     push        {lr}
133     ldr         r12, [sp, #4]               ; load thresh
134     sub         r0, r0, #4                  ; move src pointer down by 4 columns
135     vdup.s8     q2, r12                     ; thresh
136     add         r12, r0, r1, lsl #3         ; move src pointer down by 8 lines
137
138     vld1.u8     {d6}, [r0], r1              ; load first 8-line src data
139     vld1.u8     {d7}, [r12], r1             ; load second 8-line src data
140     vld1.u8     {d8}, [r0], r1
141     vld1.u8     {d9}, [r12], r1
142     vld1.u8     {d10}, [r0], r1
143     vld1.u8     {d11}, [r12], r1
144     vld1.u8     {d12}, [r0], r1
145     vld1.u8     {d13}, [r12], r1
146     vld1.u8     {d14}, [r0], r1
147     vld1.u8     {d15}, [r12], r1
148     vld1.u8     {d16}, [r0], r1
149     vld1.u8     {d17}, [r12], r1
150     vld1.u8     {d18}, [r0], r1
151     vld1.u8     {d19}, [r12], r1
152     vld1.u8     {d20}, [r0], r1
153     vld1.u8     {d21}, [r12], r1
154
155     ;transpose to 8x16 matrix
156     vtrn.32     q3, q7
157     vtrn.32     q4, q8
158     vtrn.32     q5, q9
159     vtrn.32     q6, q10
160
161     vtrn.16     q3, q5
162     vtrn.16     q4, q6
163     vtrn.16     q7, q9
164     vtrn.16     q8, q10
165
166     vtrn.8      q3, q4
167     vtrn.8      q5, q6
168     vtrn.8      q7, q8
169     vtrn.8      q9, q10
170
171     sub         r0, r0, r1, lsl #3
172
173     bl          vp8_mbloop_filter_neon
174
175     sub         r12, r12, r1, lsl #3
176
177     ;transpose to 16x8 matrix
178     vtrn.32     q3, q7
179     vtrn.32     q4, q8
180     vtrn.32     q5, q9
181     vtrn.32     q6, q10
182
183     vtrn.16     q3, q5
184     vtrn.16     q4, q6
185     vtrn.16     q7, q9
186     vtrn.16     q8, q10
187
188     vtrn.8      q3, q4
189     vtrn.8      q5, q6
190     vtrn.8      q7, q8
191     vtrn.8      q9, q10
192
193     ;store op2, op1, op0, oq0, oq1, oq2
194     vst1.8      {d6}, [r0], r1
195     vst1.8      {d7}, [r12], r1
196     vst1.8      {d8}, [r0], r1
197     vst1.8      {d9}, [r12], r1
198     vst1.8      {d10}, [r0], r1
199     vst1.8      {d11}, [r12], r1
200     vst1.8      {d12}, [r0], r1
201     vst1.8      {d13}, [r12], r1
202     vst1.8      {d14}, [r0], r1
203     vst1.8      {d15}, [r12], r1
204     vst1.8      {d16}, [r0], r1
205     vst1.8      {d17}, [r12], r1
206     vst1.8      {d18}, [r0], r1
207     vst1.8      {d19}, [r12], r1
208     vst1.8      {d20}, [r0]
209     vst1.8      {d21}, [r12]
210
211     pop         {pc}
212     ENDP        ; |vp8_mbloop_filter_vertical_edge_y_neon|
213
214 ; void vp8_mbloop_filter_vertical_edge_uv_neon(unsigned char *u, int pitch,
215 ;                                              const unsigned char *blimit,
216 ;                                              const unsigned char *limit,
217 ;                                              const unsigned char *thresh,
218 ;                                              unsigned char *v)
219 ; r0    unsigned char *u,
220 ; r1    int pitch,
221 ; r2    const signed char *flimit,
222 ; r3    const signed char *limit,
223 ; sp    const signed char *thresh,
224 ; sp+4  unsigned char *v
225 |vp8_mbloop_filter_vertical_edge_uv_neon| PROC
226     push        {lr}
227     ldr         r12, [sp, #4]               ; load thresh
228     sub         r0, r0, #4                  ; move u pointer down by 4 columns
229     vdup.u8     q2, r12                     ; thresh
230     ldr         r12, [sp, #8]               ; load v ptr
231     sub         r12, r12, #4                ; move v pointer down by 4 columns
232
233     vld1.u8     {d6}, [r0], r1              ;load u data
234     vld1.u8     {d7}, [r12], r1             ;load v data
235     vld1.u8     {d8}, [r0], r1
236     vld1.u8     {d9}, [r12], r1
237     vld1.u8     {d10}, [r0], r1
238     vld1.u8     {d11}, [r12], r1
239     vld1.u8     {d12}, [r0], r1
240     vld1.u8     {d13}, [r12], r1
241     vld1.u8     {d14}, [r0], r1
242     vld1.u8     {d15}, [r12], r1
243     vld1.u8     {d16}, [r0], r1
244     vld1.u8     {d17}, [r12], r1
245     vld1.u8     {d18}, [r0], r1
246     vld1.u8     {d19}, [r12], r1
247     vld1.u8     {d20}, [r0], r1
248     vld1.u8     {d21}, [r12], r1
249
250     ;transpose to 8x16 matrix
251     vtrn.32     q3, q7
252     vtrn.32     q4, q8
253     vtrn.32     q5, q9
254     vtrn.32     q6, q10
255
256     vtrn.16     q3, q5
257     vtrn.16     q4, q6
258     vtrn.16     q7, q9
259     vtrn.16     q8, q10
260
261     vtrn.8      q3, q4
262     vtrn.8      q5, q6
263     vtrn.8      q7, q8
264     vtrn.8      q9, q10
265
266     sub         r0, r0, r1, lsl #3
267
268     bl          vp8_mbloop_filter_neon
269
270     sub         r12, r12, r1, lsl #3
271
272     ;transpose to 16x8 matrix
273     vtrn.32     q3, q7
274     vtrn.32     q4, q8
275     vtrn.32     q5, q9
276     vtrn.32     q6, q10
277
278     vtrn.16     q3, q5
279     vtrn.16     q4, q6
280     vtrn.16     q7, q9
281     vtrn.16     q8, q10
282
283     vtrn.8      q3, q4
284     vtrn.8      q5, q6
285     vtrn.8      q7, q8
286     vtrn.8      q9, q10
287
288     ;store op2, op1, op0, oq0, oq1, oq2
289     vst1.8      {d6}, [r0], r1
290     vst1.8      {d7}, [r12], r1
291     vst1.8      {d8}, [r0], r1
292     vst1.8      {d9}, [r12], r1
293     vst1.8      {d10}, [r0], r1
294     vst1.8      {d11}, [r12], r1
295     vst1.8      {d12}, [r0], r1
296     vst1.8      {d13}, [r12], r1
297     vst1.8      {d14}, [r0], r1
298     vst1.8      {d15}, [r12], r1
299     vst1.8      {d16}, [r0], r1
300     vst1.8      {d17}, [r12], r1
301     vst1.8      {d18}, [r0], r1
302     vst1.8      {d19}, [r12], r1
303     vst1.8      {d20}, [r0]
304     vst1.8      {d21}, [r12]
305
306     pop         {pc}
307     ENDP        ; |vp8_mbloop_filter_vertical_edge_uv_neon|
308
309 ; void vp8_mbloop_filter_neon()
310 ; This is a helper function for the macroblock loopfilters. The individual
311 ; functions do the necessary load, transpose (if necessary), preserve (if
312 ; necessary) and store.
313
314 ; r0,r1 PRESERVE
315 ; r2    mblimit
316 ; r3    limit
317
318 ; q2    thresh
319 ; q3    p3 PRESERVE
320 ; q4    p2
321 ; q5    p1
322 ; q6    p0
323 ; q7    q0
324 ; q8    q1
325 ; q9    q2
326 ; q10   q3 PRESERVE
327
328 |vp8_mbloop_filter_neon| PROC
329
330     ; vp8_filter_mask
331     vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
332     vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
333     vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
334     vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
335     vabd.u8     q1, q9, q8                  ; abs(q2 - q1)
336     vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
337
338     vmax.u8     q11, q11, q12
339     vmax.u8     q12, q13, q14
340     vmax.u8     q1, q1, q0
341     vmax.u8     q15, q11, q12
342
343     vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
344
345     ; vp8_hevmask
346     vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh) * -1
347     vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh) * -1
348     vmax.u8     q15, q15, q1
349
350     vdup.u8     q1, r3                      ; limit
351     vdup.u8     q2, r2                      ; mblimit
352
353     vmov.u8     q0, #0x80                   ; 0x80
354
355     vcge.u8     q15, q1, q15
356
357     vabd.u8     q1, q5, q8                  ; a = abs(p1 - q1)
358     vqadd.u8    q12, q12, q12               ; b = abs(p0 - q0) * 2
359     vmov.u16    q11, #3                     ; #3
360
361     ; vp8_filter
362     ; convert to signed
363     veor        q7, q7, q0                  ; qs0
364     vshr.u8     q1, q1, #1                  ; a = a / 2
365     veor        q6, q6, q0                  ; ps0
366     veor        q5, q5, q0                  ; ps1
367
368     vqadd.u8    q12, q12, q1                ; a = b + a
369
370     veor        q8, q8, q0                  ; qs1
371     veor        q4, q4, q0                  ; ps2
372     veor        q9, q9, q0                  ; qs2
373
374     vorr        q14, q13, q14               ; vp8_hevmask
375
376     vcge.u8     q12, q2, q12                ; (a > flimit * 2 + limit) * -1
377
378     vsubl.s8    q2, d14, d12                ; qs0 - ps0
379     vsubl.s8    q13, d15, d13
380
381     vqsub.s8    q1, q5, q8                  ; vp8_filter = clamp(ps1-qs1)
382
383     vmul.i16    q2, q2, q11                 ; 3 * ( qs0 - ps0)
384
385     vand        q15, q15, q12               ; vp8_filter_mask
386
387     vmul.i16    q13, q13, q11
388
389     vmov.u8     q12, #3                     ; #3
390
391     vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
392     vaddw.s8    q13, q13, d3
393
394     vmov.u8     q11, #4                     ; #4
395
396     ; vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0))
397     vqmovn.s16  d2, q2
398     vqmovn.s16  d3, q13
399
400     vand        q1, q1, q15                 ; vp8_filter &= mask
401
402     vmov.u16    q15, #63                    ; #63
403
404     vand        q13, q1, q14                ; Filter2 &= hev
405
406     vqadd.s8    q2, q13, q11                ; Filter1 = clamp(Filter2+4)
407     vqadd.s8    q13, q13, q12               ; Filter2 = clamp(Filter2+3)
408
409     vmov        q0, q15
410
411     vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
412     vshr.s8     q13, q13, #3                ; Filter2 >>= 3
413
414     vmov        q11, q15
415     vmov        q12, q15
416
417     vqsub.s8    q7, q7, q2                  ; qs0 = clamp(qs0 - Filter1)
418
419     vqadd.s8    q6, q6, q13                 ; ps0 = clamp(ps0 + Filter2)
420
421     vbic        q1, q1, q14                 ; vp8_filter &= ~hev
422
423     ; roughly 1/7th difference across boundary
424     ; roughly 2/7th difference across boundary
425     ; roughly 3/7th difference across boundary
426
427     vmov.u8     d5, #9                      ; #9
428     vmov.u8     d4, #18                     ; #18
429
430     vmov        q13, q15
431     vmov        q14, q15
432
433     vmlal.s8    q0, d2, d5                  ; 63 + Filter2 * 9
434     vmlal.s8    q11, d3, d5
435     vmov.u8     d5, #27                     ; #27
436     vmlal.s8    q12, d2, d4                 ; 63 + Filter2 * 18
437     vmlal.s8    q13, d3, d4
438     vmlal.s8    q14, d2, d5                 ; 63 + Filter2 * 27
439     vmlal.s8    q15, d3, d5
440
441     vqshrn.s16  d0, q0, #7                  ; u = clamp((63 + Filter2 * 9)>>7)
442     vqshrn.s16  d1, q11, #7
443     vqshrn.s16  d24, q12, #7                ; u = clamp((63 + Filter2 * 18)>>7)
444     vqshrn.s16  d25, q13, #7
445     vqshrn.s16  d28, q14, #7                ; u = clamp((63 + Filter2 * 27)>>7)
446     vqshrn.s16  d29, q15, #7
447
448     vmov.u8     q1, #0x80                   ; 0x80
449
450     vqsub.s8    q11, q9, q0                 ; s = clamp(qs2 - u)
451     vqadd.s8    q0, q4, q0                  ; s = clamp(ps2 + u)
452     vqsub.s8    q13, q8, q12                ; s = clamp(qs1 - u)
453     vqadd.s8    q12, q5, q12                ; s = clamp(ps1 + u)
454     vqsub.s8    q15, q7, q14                ; s = clamp(qs0 - u)
455     vqadd.s8    q14, q6, q14                ; s = clamp(ps0 + u)
456
457     veor        q9, q11, q1                 ; *oq2 = s^0x80
458     veor        q4, q0, q1                  ; *op2 = s^0x80
459     veor        q8, q13, q1                 ; *oq1 = s^0x80
460     veor        q5, q12, q1                 ; *op2 = s^0x80
461     veor        q7, q15, q1                 ; *oq0 = s^0x80
462     veor        q6, q14, q1                 ; *op0 = s^0x80
463
464     bx          lr
465     ENDP        ; |vp8_mbloop_filter_neon|
466
467 ;-----------------
468
469     END