1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define ENTRY(f) .text; .align 4; .globl f; .type f,#function; f: .fnstart
18#define PRIVATE(f) .text; .align 4; .type f,#function; f: .fnstart
19#define END(f) .fnend; .size f, .-f;
20
21.eabi_attribute 25,1 @Tag_ABI_align8_preserved
22.arm
23
24/* Number of fractional bits to preserve in intermediate results.  The
25 * intermediate storage is 16-bit, and we started with 8 bit data (the integer
26 * part), so this should be between 0 and 8.
27 */
28.set FRACTION_BITS, 7
29
30.set MAX_R, 25
31
32
33/* A quick way of making a line of code conditional on some other condition.
34 * Use `.set cc, 1` or `.set cc, 0` to enable or disable lines prefixed with
35 * `ifcc`:
36 */
37.macro ifcc zzz:vararg
38.if cc
39            \zzz
40.endif
41.endm
42
43/* Fetch 16 columns of bytes (regardless of image format), convolve these
44 * vertically, and leave them in the register file.  If working near the top or
45 * bottom of an image then clamp the addressing while loading the data in.
46 *
47 * The convolution is fully unrolled for windows up to max_r, with the
48 * outermost edges calculated first.  This way it's possible to branch directly
49 * into the relevant part of the code for an arbitrary convolution radius.  Two
50 * variants of the loop are produced; one eliminates the clamping code for a
51 * slight speed advantage.
52 *
53 * Where the macro is called with reg=x, the specified register is taken to
54 * contain a pre-calculated pointer into one of the two loops.
55 *
56 * Input:
57 *      r1 -- src
58 *      r2 -- pitch
59 *      r5 -- r
60 *      r6 -- rup
61 *      r7 -- rdn
62 *      r12 -- switch index
63 *      q0-q3 -- coefficient table
64 * Output:
65 *      r1 += 16
66 *      q10,q11 -- 16 convolved columns
67 * Modifies:
68 *      r10 = upper row pointer
69 *      r11 = lower row pointer
70 *      q12-q15 = temporary sums
71 */
72.macro fetch, max_r=MAX_R, labelc=1, labelnc=2, reg=r12 /*{{{*/
73  .ifc \reg,r12 ; .set cc, 1 ; .else ; .set cc, 0 ; .endif
74
75            vld1.8      {d30,d31}, [r1]
76            mls         r10, r2, r6, r1
77
78            vmovl.u8    q14, d30
79            pld         [r1, #32]
80            vmovl.u8    q15, d31
81  .if \max_r < 16 // approximate
82    ifcc    adr         \reg, 1f
83  .else
84    ifcc    ldr         \reg, 2f
851:  ifcc    add         \reg, \reg, pc
86  .endif
87
88            vmull.u16   q12, d28, d0[0]
89    ifcc    sub         \reg, r5, LSL #6
90            vmull.u16   q13, d29, d0[0]
91            mla         r11, r2, r7, r1
92            vmull.u16   q14, d30, d0[0]
93            add         r1, r1, #16
94            vmull.u16   q15, d31, d0[0]
95            bx          \reg
96
97     ifcc   .align 2
98  2: ifcc   .word       1f-1b-8
99
100  .irp rowclamp, 1, 0
101    .set cc, \rowclamp
102    .align 4
103    .irp dreg, 6, 5, 4, 3, 2, 1, 0 ; .irp lane, 3, 2, 1, 0
104      .set i, \dreg * 4 + \lane
105      .if 0 < i && i <= \max_r
106        .if \rowclamp
107            vld1.8      {d20,d21}, [r10]
108            vld1.8      {d22,d23}, [r11]
109            cmp         r6, #i
110        .else
111            vld1.8      {d20,d21}, [r10], r2
112            vld1.8      {d22,d23}, [r11]
113            sub         r11, r11, r2
114        .endif
115            vswp        d21, d22
116            pld         [r10, #32]
117            vaddl.u8    q10, d20, d21
118    ifcc    addhs       r10, r10, r2
119            vaddl.u8    q11, d22, d23
120    ifcc    cmp         r7, #i
121            vmlal.u16   q12, d20, d\dreg[\lane]
122            pld         [r11, #32]
123            vmlal.u16   q13, d21, d\dreg[\lane]
124    ifcc    subhs       r11, r11, r2
125            vmlal.u16   q14, d22, d\dreg[\lane]
126    ifcc    nop
127            vmlal.u16   q15, d23, d\dreg[\lane]
128        .endif
129    .endr ; .endr
130    .if \rowclamp == 1
131        1: \labelc :
132            b           2f
133    .else
134        2: \labelnc :
135    .endif
136  .endr
137
138            vqrshrn.u32 d20, q12, #16 - FRACTION_BITS
139            vqrshrn.u32 d21, q13, #16 - FRACTION_BITS
140            vqrshrn.u32 d22, q14, #16 - FRACTION_BITS
141            vqrshrn.u32 d23, q15, #16 - FRACTION_BITS
142.endm /*}}}*/
143
144/* Some portion of the convolution window (as much as will fit, and all of it
145 * for the uchar1 cases) is kept in the register file to avoid unnecessary
146 * memory accesses.  This forces the horizontal loops to be unrolled because
147 * there's no indexed addressing into the register file.
148 *
149 * As in the fetch macro, the operations are ordered from outside to inside, so
150 * that jumping into the middle of the block bypasses the unwanted window taps.
151 *
152 * There are several variants of the macro because of the fixed offets of the
153 * taps -- the wider the maximum radius the further the centre tap is from the
154 * most recently fetched data.  This means that pre-filling the window requires
155 * more data that won't be used and it means that rotating the window involves
156 * more mov operations.
157 *
158 * When the buffer gets too big the buffer at [r9] is used.
159 *
160 * Input:
161 *      q4-q11 -- convoltion window
162 *      r9 -- pointer to additional convolution window data
163 * Output:
164 *      r9 -- updated buffer pointer (if used)
165 *      d31 -- result to be stored
166 * Modifies:
167 *      r12 -- temp buffer pointer
168 *      q12-q13 -- temporaries for load and vext operations.
169 *      q14-q15 -- intermediate sums
170 */
171#define TUNED_LIST1 8, 16
172.macro hconv1_8/*{{{*/
173            vmull.u16   q14, d18, d0[0]
174            vmull.u16   q15, d19, d0[0]
175
176            ldr         r12, [pc, r5, LSL #2]
177            add         pc, pc, r12
178            bkpt
179    100:    .word 101f-100b
180            .word 102f-100b
181            .word 103f-100b
182            .word 104f-100b
183            .word 105f-100b
184            .word 106f-100b
185            .word 107f-100b
186            .word 108f-100b
187    108:    vmlal.u16   q14, d16, d2[0]
188            vmlal.u16   q15, d17, d2[0]
189            vmlal.u16   q14, d20, d2[0]
190            vmlal.u16   q15, d21, d2[0]
191    107:    vext.u16    q12, q8, q9, #1
192            vext.u16    q13, q9, q10, #7
193            vmlal.u16   q14, d24, d1[3]
194            vmlal.u16   q15, d25, d1[3]
195            vmlal.u16   q14, d26, d1[3]
196            vmlal.u16   q15, d27, d1[3]
197    106:    vext.u16    q12, q8, q9, #2
198            vext.u16    q13, q9, q10, #6
199            vmlal.u16   q14, d24, d1[2]
200            vmlal.u16   q15, d25, d1[2]
201            vmlal.u16   q14, d26, d1[2]
202            vmlal.u16   q15, d27, d1[2]
203    105:    vext.u16    q12, q8, q9, #3
204            vext.u16    q13, q9, q10, #5
205            vmlal.u16   q14, d24, d1[1]
206            vmlal.u16   q15, d25, d1[1]
207            vmlal.u16   q14, d26, d1[1]
208            vmlal.u16   q15, d27, d1[1]
209    104:    //vext.u16    q12, q8, q9, #4
210            //vext.u16    q13, q9, q10, #4
211            vmlal.u16   q14, d17, d1[0]
212            vmlal.u16   q15, d18, d1[0]
213            vmlal.u16   q14, d19, d1[0]
214            vmlal.u16   q15, d20, d1[0]
215    103:    vext.u16    q12, q8, q9, #5
216            vext.u16    q13, q9, q10, #3
217            vmlal.u16   q14, d24, d0[3]
218            vmlal.u16   q15, d25, d0[3]
219            vmlal.u16   q14, d26, d0[3]
220            vmlal.u16   q15, d27, d0[3]
221    102:    vext.u16    q12, q8, q9, #6
222            vext.u16    q13, q9, q10, #2
223            vmlal.u16   q14, d24, d0[2]
224            vmlal.u16   q15, d25, d0[2]
225            vmlal.u16   q14, d26, d0[2]
226            vmlal.u16   q15, d27, d0[2]
227    101:    vext.u16    q12, q8, q9, #7
228            vext.u16    q13, q9, q10, #1
229            vmlal.u16   q14, d24, d0[1]
230            vmlal.u16   q15, d25, d0[1]
231            vmlal.u16   q14, d26, d0[1]
232            vmlal.u16   q15, d27, d0[1]
233
234            vqrshrn.u32 d28, q14, #16
235            vqrshrn.u32 d29, q15, #16
236            vqrshrn.u16 d31, q14, #FRACTION_BITS
237
238            vmov        q8, q9
239            vmov        q9, q10
240            vmov        q10, q11
241.endm/*}}}*/
242
243.macro hconv1_16/*{{{*/
244            vmull.u16   q14, d16, d0[0]
245            vmull.u16   q15, d17, d0[0]
246
247            ldr         r12, [pc, r5, LSL #2]
248            add         pc, pc, r12
249            bkpt
250    100:    .word 101f-100b
251            .word 102f-100b
252            .word 103f-100b
253            .word 104f-100b
254            .word 105f-100b
255            .word 106f-100b
256            .word 107f-100b
257            .word 108f-100b
258            .word 109f-100b
259            .word 110f-100b
260            .word 111f-100b
261            .word 112f-100b
262            .word 113f-100b
263            .word 114f-100b
264            .word 115f-100b
265            .word 116f-100b
266    116:    //vext.u16    q12, q6, q7, #0
267            //vext.u16    q13, q10, q11, #0
268            vmlal.u16   q14, d12, d4[0]
269            vmlal.u16   q15, d13, d4[0]
270            vmlal.u16   q14, d20, d4[0]
271            vmlal.u16   q15, d21, d4[0]
272    115:    vext.u16    q12, q6, q7, #1
273            vext.u16    q13, q9, q10, #7
274            vmlal.u16   q14, d24, d3[3]
275            vmlal.u16   q15, d25, d3[3]
276            vmlal.u16   q14, d26, d3[3]
277            vmlal.u16   q15, d27, d3[3]
278    114:    vext.u16    q12, q6, q7, #2
279            vext.u16    q13, q9, q10, #6
280            vmlal.u16   q14, d24, d3[2]
281            vmlal.u16   q15, d25, d3[2]
282            vmlal.u16   q14, d26, d3[2]
283            vmlal.u16   q15, d27, d3[2]
284    113:    vext.u16    q12, q6, q7, #3
285            vext.u16    q13, q9, q10, #5
286            vmlal.u16   q14, d24, d3[1]
287            vmlal.u16   q15, d25, d3[1]
288            vmlal.u16   q14, d26, d3[1]
289            vmlal.u16   q15, d27, d3[1]
290    112:    //vext.u16    q12, q6, q7, #4
291            //vext.u16    q13, q9, q10, #4
292            vmlal.u16   q14, d13, d3[0]
293            vmlal.u16   q15, d14, d3[0]
294            vmlal.u16   q14, d19, d3[0]
295            vmlal.u16   q15, d20, d3[0]
296    111:    vext.u16    q12, q6, q7, #5
297            vext.u16    q13, q9, q10, #3
298            vmlal.u16   q14, d24, d2[3]
299            vmlal.u16   q15, d25, d2[3]
300            vmlal.u16   q14, d26, d2[3]
301            vmlal.u16   q15, d27, d2[3]
302    110:    vext.u16    q12, q6, q7, #6
303            vext.u16    q13, q9, q10, #2
304            vmlal.u16   q14, d24, d2[2]
305            vmlal.u16   q15, d25, d2[2]
306            vmlal.u16   q14, d26, d2[2]
307            vmlal.u16   q15, d27, d2[2]
308    109:    vext.u16    q12, q6, q7, #7
309            vext.u16    q13, q9, q10, #1
310            vmlal.u16   q14, d24, d2[1]
311            vmlal.u16   q15, d25, d2[1]
312            vmlal.u16   q14, d26, d2[1]
313            vmlal.u16   q15, d27, d2[1]
314    108:    //vext.u16    q12, q7, q8, #0
315            //vext.u16    q13, q9, q10, #0
316            vmlal.u16   q14, d14, d2[0]
317            vmlal.u16   q15, d15, d2[0]
318            vmlal.u16   q14, d18, d2[0]
319            vmlal.u16   q15, d19, d2[0]
320    107:    vext.u16    q12, q7, q8, #1
321            vext.u16    q13, q8, q9, #7
322            vmlal.u16   q14, d24, d1[3]
323            vmlal.u16   q15, d25, d1[3]
324            vmlal.u16   q14, d26, d1[3]
325            vmlal.u16   q15, d27, d1[3]
326    106:    vext.u16    q12, q7, q8, #2
327            vext.u16    q13, q8, q9, #6
328            vmlal.u16   q14, d24, d1[2]
329            vmlal.u16   q15, d25, d1[2]
330            vmlal.u16   q14, d26, d1[2]
331            vmlal.u16   q15, d27, d1[2]
332    105:    vext.u16    q12, q7, q8, #3
333            vext.u16    q13, q8, q9, #5
334            vmlal.u16   q14, d24, d1[1]
335            vmlal.u16   q15, d25, d1[1]
336            vmlal.u16   q14, d26, d1[1]
337            vmlal.u16   q15, d27, d1[1]
338    104:    //vext.u16    q12, q7, q8, #4
339            //vext.u16    q13, q8, q9, #4
340            vmlal.u16   q14, d15, d1[0]
341            vmlal.u16   q15, d16, d1[0]
342            vmlal.u16   q14, d17, d1[0]
343            vmlal.u16   q15, d18, d1[0]
344    103:    vext.u16    q12, q7, q8, #5
345            vext.u16    q13, q8, q9, #3
346            vmlal.u16   q14, d24, d0[3]
347            vmlal.u16   q15, d25, d0[3]
348            vmlal.u16   q14, d26, d0[3]
349            vmlal.u16   q15, d27, d0[3]
350    102:    vext.u16    q12, q7, q8, #6
351            vext.u16    q13, q8, q9, #2
352            vmlal.u16   q14, d24, d0[2]
353            vmlal.u16   q15, d25, d0[2]
354            vmlal.u16   q14, d26, d0[2]
355            vmlal.u16   q15, d27, d0[2]
356    101:    vext.u16    q12, q7, q8, #7
357            vext.u16    q13, q8, q9, #1
358            vmlal.u16   q14, d24, d0[1]
359            vmlal.u16   q15, d25, d0[1]
360            vmlal.u16   q14, d26, d0[1]
361            vmlal.u16   q15, d27, d0[1]
362
363            vqrshrn.u32 d28, q14, #16
364            vqrshrn.u32 d29, q15, #16
365            vqrshrn.u16 d31, q14, #FRACTION_BITS
366
367            vmov        q6, q7
368            vmov        q7, q8
369            vmov        q8, q9
370            vmov        q9, q10
371            vmov        q10, q11
372.endm/*}}}*/
373
374.macro hconv1_25/*{{{*/
375            vext.u16    q12, q6, q7, #7
376            vmull.u16   q14, d24, d0[0]
377            vmull.u16   q15, d25, d0[0]
378
379            ldr         r12, [pc, r5, LSL #2]
380            add         pc, pc, r12
381            bkpt
382    100:    .word 101f-100b
383            .word 102f-100b
384            .word 103f-100b
385            .word 104f-100b
386            .word 105f-100b
387            .word 106f-100b
388            .word 107f-100b
389            .word 108f-100b
390            .word 109f-100b
391            .word 110f-100b
392            .word 111f-100b
393            .word 112f-100b
394            .word 113f-100b
395            .word 114f-100b
396            .word 115f-100b
397            .word 116f-100b
398            .word 117f-100b
399            .word 118f-100b
400            .word 119f-100b
401            .word 120f-100b
402            .word 121f-100b
403            .word 122f-100b
404            .word 123f-100b
405            .word 124f-100b
406            .word 125f-100b
407    125:    vext.u16    q12, q3, q4, #6
408            vext.u16    q13, q10, q11, #0
409            vmlal.u16   q14, d24, d6[1]
410            vmlal.u16   q15, d25, d6[1]
411            vmlal.u16   q14, d26, d6[1]
412            vmlal.u16   q15, d27, d6[1]
413    124:    vext.u16    q12, q3, q4, #7
414            vext.u16    q13, q9, q10, #7
415            vmlal.u16   q14, d24, d6[0]
416            vmlal.u16   q15, d25, d6[0]
417            vmlal.u16   q14, d26, d6[0]
418            vmlal.u16   q15, d27, d6[0]
419    123:    vext.u16    q12, q4, q5, #0
420            vext.u16    q13, q9, q10, #6
421            vmlal.u16   q14, d24, d5[3]
422            vmlal.u16   q15, d25, d5[3]
423            vmlal.u16   q14, d26, d5[3]
424            vmlal.u16   q15, d27, d5[3]
425    122:    vext.u16    q12, q4, q5, #1
426            vext.u16    q13, q9, q10, #5
427            vmlal.u16   q14, d24, d5[2]
428            vmlal.u16   q15, d25, d5[2]
429            vmlal.u16   q14, d26, d5[2]
430            vmlal.u16   q15, d27, d5[2]
431    121:    vext.u16    q12, q4, q5, #2
432            vext.u16    q13, q9, q10, #4
433            vmlal.u16   q14, d24, d5[1]
434            vmlal.u16   q15, d25, d5[1]
435            vmlal.u16   q14, d26, d5[1]
436            vmlal.u16   q15, d27, d5[1]
437    120:    vext.u16    q12, q4, q5, #3
438            vext.u16    q13, q9, q10, #3
439            vmlal.u16   q14, d24, d5[0]
440            vmlal.u16   q15, d25, d5[0]
441            vmlal.u16   q14, d26, d5[0]
442            vmlal.u16   q15, d27, d5[0]
443    119:    vext.u16    q12, q4, q5, #4
444            vext.u16    q13, q9, q10, #2
445            vmlal.u16   q14, d24, d4[3]
446            vmlal.u16   q15, d25, d4[3]
447            vmlal.u16   q14, d26, d4[3]
448            vmlal.u16   q15, d27, d4[3]
449    118:    vext.u16    q12, q4, q5, #5
450            vext.u16    q13, q9, q10, #1
451            vmlal.u16   q14, d24, d4[2]
452            vmlal.u16   q15, d25, d4[2]
453            vmlal.u16   q14, d26, d4[2]
454            vmlal.u16   q15, d27, d4[2]
455    117:    vext.u16    q12, q4, q5, #6
456            vext.u16    q13, q9, q10, #0
457            vmlal.u16   q14, d24, d4[1]
458            vmlal.u16   q15, d25, d4[1]
459            vmlal.u16   q14, d26, d4[1]
460            vmlal.u16   q15, d27, d4[1]
461    116:    vext.u16    q12, q4, q5, #7
462            vext.u16    q13, q8, q9, #7
463            vmlal.u16   q14, d24, d4[0]
464            vmlal.u16   q15, d25, d4[0]
465            vmlal.u16   q14, d26, d4[0]
466            vmlal.u16   q15, d27, d4[0]
467    115:    vext.u16    q12, q5, q6, #0
468            vext.u16    q13, q8, q9, #6
469            vmlal.u16   q14, d24, d3[3]
470            vmlal.u16   q15, d25, d3[3]
471            vmlal.u16   q14, d26, d3[3]
472            vmlal.u16   q15, d27, d3[3]
473    114:    vext.u16    q12, q5, q6, #1
474            vext.u16    q13, q8, q9, #5
475            vmlal.u16   q14, d24, d3[2]
476            vmlal.u16   q15, d25, d3[2]
477            vmlal.u16   q14, d26, d3[2]
478            vmlal.u16   q15, d27, d3[2]
479    113:    vext.u16    q12, q5, q6, #2
480            vext.u16    q13, q8, q9, #4
481            vmlal.u16   q14, d24, d3[1]
482            vmlal.u16   q15, d25, d3[1]
483            vmlal.u16   q14, d26, d3[1]
484            vmlal.u16   q15, d27, d3[1]
485    112:    vext.u16    q12, q5, q6, #3
486            vext.u16    q13, q8, q9, #3
487            vmlal.u16   q14, d24, d3[0]
488            vmlal.u16   q15, d25, d3[0]
489            vmlal.u16   q14, d26, d3[0]
490            vmlal.u16   q15, d27, d3[0]
491    111:    vext.u16    q12, q5, q6, #4
492            vext.u16    q13, q8, q9, #2
493            vmlal.u16   q14, d24, d2[3]
494            vmlal.u16   q15, d25, d2[3]
495            vmlal.u16   q14, d26, d2[3]
496            vmlal.u16   q15, d27, d2[3]
497    110:    vext.u16    q12, q5, q6, #5
498            vext.u16    q13, q8, q9, #1
499            vmlal.u16   q14, d24, d2[2]
500            vmlal.u16   q15, d25, d2[2]
501            vmlal.u16   q14, d26, d2[2]
502            vmlal.u16   q15, d27, d2[2]
503    109:    vext.u16    q12, q5, q6, #6
504            vext.u16    q13, q8, q9, #0
505            vmlal.u16   q14, d24, d2[1]
506            vmlal.u16   q15, d25, d2[1]
507            vmlal.u16   q14, d26, d2[1]
508            vmlal.u16   q15, d27, d2[1]
509    108:    vext.u16    q12, q5, q6, #7
510            vext.u16    q13, q7, q8, #7
511            vmlal.u16   q14, d24, d2[0]
512            vmlal.u16   q15, d25, d2[0]
513            vmlal.u16   q14, d26, d2[0]
514            vmlal.u16   q15, d27, d2[0]
515    107:    vext.u16    q12, q6, q7, #0
516            vext.u16    q13, q7, q8, #6
517            vmlal.u16   q14, d24, d1[3]
518            vmlal.u16   q15, d25, d1[3]
519            vmlal.u16   q14, d26, d1[3]
520            vmlal.u16   q15, d27, d1[3]
521    106:    vext.u16    q12, q6, q7, #1
522            vext.u16    q13, q7, q8, #5
523            vmlal.u16   q14, d24, d1[2]
524            vmlal.u16   q15, d25, d1[2]
525            vmlal.u16   q14, d26, d1[2]
526            vmlal.u16   q15, d27, d1[2]
527    105:    vext.u16    q12, q6, q7, #2
528            vext.u16    q13, q7, q8, #4
529            vmlal.u16   q14, d24, d1[1]
530            vmlal.u16   q15, d25, d1[1]
531            vmlal.u16   q14, d26, d1[1]
532            vmlal.u16   q15, d27, d1[1]
533    104:    vext.u16    q12, q6, q7, #3
534            vext.u16    q13, q7, q8, #3
535            vmlal.u16   q14, d24, d1[0]
536            vmlal.u16   q15, d25, d1[0]
537            vmlal.u16   q14, d26, d1[0]
538            vmlal.u16   q15, d27, d1[0]
539    103:    vext.u16    q12, q6, q7, #4
540            vext.u16    q13, q7, q8, #2
541            vmlal.u16   q14, d24, d0[3]
542            vmlal.u16   q15, d25, d0[3]
543            vmlal.u16   q14, d26, d0[3]
544            vmlal.u16   q15, d27, d0[3]
545    102:    vext.u16    q12, q6, q7, #5
546            vext.u16    q13, q7, q8, #1
547            vmlal.u16   q14, d24, d0[2]
548            vmlal.u16   q15, d25, d0[2]
549            vmlal.u16   q14, d26, d0[2]
550            vmlal.u16   q15, d27, d0[2]
551    101:    vext.u16    q12, q6, q7, #6
552            vext.u16    q13, q7, q8, #0
553            vmlal.u16   q14, d24, d0[1]
554            vmlal.u16   q15, d25, d0[1]
555            vmlal.u16   q14, d26, d0[1]
556            vmlal.u16   q15, d27, d0[1]
557
558            vqrshrn.u32 d28, q14, #16
559            vqrshrn.u32 d29, q15, #16
560            vqrshrn.u16 d31, q14, #FRACTION_BITS
561
562            vmov        d7, d9
563            vmov        q4, q5
564            vmov        q5, q6
565            vmov        q6, q7
566            vmov        q7, q8
567            vmov        q8, q9
568            vmov        q9, q10
569            vmov        q10, q11
570.endm/*}}}*/
571
572#define TUNED_LIST4 6, 12
573.macro hconv4_6/*{{{*/
574            vmull.u16   q14, d14, d0[0]
575            vmull.u16   q15, d15, d0[0]
576
577            ldr         r12, [pc, r5, LSL #2]
578            add         pc, pc, r12
579            bkpt
580    100:    .word 101f-100b
581            .word 102f-100b
582            .word 103f-100b
583            .word 104f-100b
584            .word 105f-100b
585            .word 106f-100b
586    106:    vmlal.u16   q14, d8,  d1[2]
587            vmlal.u16   q15, d9,  d1[2]
588            vmlal.u16   q14, d20, d1[2]
589            vmlal.u16   q15, d21, d1[2]
590    105:    vmlal.u16   q14, d9,  d1[1]
591            vmlal.u16   q15, d10, d1[1]
592            vmlal.u16   q14, d19, d1[1]
593            vmlal.u16   q15, d20, d1[1]
594    104:    vmlal.u16   q14, d10, d1[0]
595            vmlal.u16   q15, d11, d1[0]
596            vmlal.u16   q14, d18, d1[0]
597            vmlal.u16   q15, d19, d1[0]
598    103:    vmlal.u16   q14, d11, d0[3]
599            vmlal.u16   q15, d12, d0[3]
600            vmlal.u16   q14, d17, d0[3]
601            vmlal.u16   q15, d18, d0[3]
602    102:    vmlal.u16   q14, d12, d0[2]
603            vmlal.u16   q15, d13, d0[2]
604            vmlal.u16   q14, d16, d0[2]
605            vmlal.u16   q15, d17, d0[2]
606    101:    vmlal.u16   q14, d13, d0[1]
607            vmlal.u16   q15, d14, d0[1]
608            vmlal.u16   q14, d15, d0[1]
609            vmlal.u16   q15, d16, d0[1]
610
611            vqrshrn.u32 d28, q14, #16
612            vqrshrn.u32 d29, q15, #16
613            vqrshrn.u16 d31, q14, #FRACTION_BITS
614
615            vmov        q4, q5
616            vmov        q5, q6
617            vmov        q6, q7
618            vmov        q7, q8
619            vmov        q8, q9
620            vmov        q9, q10
621            vmov        q10, q11
622.endm/*}}}*/
623
624.macro hconv4_12/*{{{*/
625            vmull.u16   q14, d8, d0[0]
626            vmull.u16   q15, d9, d0[0]
627
628            ldr         r12, [pc, r5, LSL #2]
629            add         pc, pc, r12
630            bkpt
631    100:    .word 101f-100b
632            .word 102f-100b
633            .word 103f-100b
634            .word 104f-100b
635            .word 105f-100b
636            .word 106f-100b
637            .word 107f-100b
638            .word 108f-100b
639            .word 109f-100b
640            .word 110f-100b
641            .word 111f-100b
642            .word 112f-100b
643    112:    add         r12, r9, #0x1a0
644            bic         r12, r12, #0x200
645            vld1.u16    {d24,d25}, [r12:128]
646            vmlal.u16   q14, d24, d3[0]
647            vmlal.u16   q15, d25, d3[0]
648            vmlal.u16   q14, d20, d3[0]
649            vmlal.u16   q15, d21, d3[0]
650    111:    add         r12, r9, #0x1a8
651            bic         r12, r12, #0x200
652            vld1.u16    {d24}, [r12:64]!
653            bic         r12, r12, #0x200
654            vld1.u16    {d25}, [r12:64]
655            vmlal.u16   q14, d24, d2[3]
656            vmlal.u16   q15, d25, d2[3]
657            vmlal.u16   q14, d19, d2[3]
658            vmlal.u16   q15, d20, d2[3]
659    110:    add         r12, r9, #0x1b0
660            bic         r12, r12, #0x200
661            vld1.u16    {d24,d25}, [r12:128]
662            vmlal.u16   q14, d24, d2[2]
663            vmlal.u16   q15, d25, d2[2]
664            vmlal.u16   q14, d18, d2[2]
665            vmlal.u16   q15, d19, d2[2]
666    109:    add         r12, r9, #0x1b8
667            bic         r12, r12, #0x200
668            vld1.u16    {d24}, [r12:64]!
669            bic         r12, r12, #0x200
670            vld1.u16    {d25}, [r12:64]
671            vmlal.u16   q14, d24, d2[1]
672            vmlal.u16   q15, d25, d2[1]
673            vmlal.u16   q14, d17, d2[1]
674            vmlal.u16   q15, d18, d2[1]
675    108:    add         r12, r9, #0x1c0
676            bic         r12, r12, #0x200
677            vld1.u16    {d24,d25}, [r12:128]
678            vmlal.u16   q14, d24, d2[0]
679            vmlal.u16   q15, d25, d2[0]
680            vmlal.u16   q14, d16, d2[0]
681            vmlal.u16   q15, d17, d2[0]
682    107:    add         r12, r9, #0x1c8
683            bic         r12, r12, #0x200
684            vld1.u16    {d24}, [r12:64]!
685            bic         r12, r12, #0x200
686            vld1.u16    {d25}, [r12:64]
687            vmlal.u16   q14, d24, d1[3]
688            vmlal.u16   q15, d25, d1[3]
689            vmlal.u16   q14, d15, d1[3]
690            vmlal.u16   q15, d16, d1[3]
691    106:    add         r12, r9, #0x1d0
692            bic         r12, r12, #0x200
693            vld1.u16    {d24,d25}, [r12:128]
694            vmlal.u16   q14, d24, d1[2]
695            vmlal.u16   q15, d25, d1[2]
696            vmlal.u16   q14, d14, d1[2]
697            vmlal.u16   q15, d15, d1[2]
698    105:    add         r12, r9, #0x1d8
699            bic         r12, r12, #0x200
700            vld1.u16    {d24}, [r12:64]!
701            bic         r12, r12, #0x200
702            vld1.u16    {d25}, [r12:64]
703            vmlal.u16   q14, d24, d1[1]
704            vmlal.u16   q15, d25, d1[1]
705            vmlal.u16   q14, d13, d1[1]
706            vmlal.u16   q15, d14, d1[1]
707    104:    add         r12, r9, #0x1e0
708            bic         r12, r12, #0x200
709            vld1.u16    {d24,d25}, [r12:128]
710            vmlal.u16   q14, d24, d1[0]
711            vmlal.u16   q15, d25, d1[0]
712            vmlal.u16   q14, d12, d1[0]
713            vmlal.u16   q15, d13, d1[0]
714    103:    add         r12, r9, #0x1e8
715            bic         r12, r12, #0x200
716            vld1.u16    {d24}, [r12:64]!
717            bic         r12, r12, #0x200
718            vld1.u16    {d25}, [r12:64]
719            vmlal.u16   q14, d24, d0[3]
720            vmlal.u16   q15, d25, d0[3]
721            vmlal.u16   q14, d11, d0[3]
722            vmlal.u16   q15, d12, d0[3]
723    102:    add         r12, r9, #0x1f0
724            bic         r12, r12, #0x200
725            vld1.u16    {d24,d25}, [r12:128]
726            vmlal.u16   q14, d24, d0[2]
727            vmlal.u16   q15, d25, d0[2]
728            vmlal.u16   q14, d10, d0[2]
729            vmlal.u16   q15, d11, d0[2]
730    101:    add         r12, r9, #0x1f8
731            bic         r12, r12, #0x200
732            vld1.u16    {d24}, [r12:64]
733            vmlal.u16   q14, d24, d0[1]
734            vmlal.u16   q15, d8,  d0[1]
735            vmlal.u16   q14, d9,  d0[1]
736            vmlal.u16   q15, d10, d0[1]
737
738            vqrshrn.u32 d28, q14, #16
739            vqrshrn.u32 d29, q15, #16
740            vqrshrn.u16 d31, q14, #FRACTION_BITS
741
742            vst1.u8     {q4}, [r9:128]!
743            bic         r9, r9, #0x200
744            vmov        q4, q5
745            vmov        q5, q6
746            vmov        q6, q7
747            vmov        q7, q8
748            vmov        q8, q9
749            vmov        q9, q10
750            vmov        q10, q11
751.endm/*}}}*/
752
753.macro hconv4_25/*{{{*/
754            add         r12, r9, #0x198
755            bic         r12, r12, #0x200
756            vld1.u16    {d24}, [r12:64]!
757            bic         r12, r12, #0x200
758            vld1.u16    {d25}, [r12:64]
759            vmull.u16   q14, d24, d0[0]
760            vmull.u16   q15, d25, d0[0]
761
762            ldr         r12, [pc, r5, LSL #2]
763            add         pc, pc, r12
764            bkpt
765    100:    .word 101f-100b
766            .word 102f-100b
767            .word 103f-100b
768            .word 104f-100b
769            .word 105f-100b
770            .word 106f-100b
771            .word 107f-100b
772            .word 108f-100b
773            .word 109f-100b
774            .word 110f-100b
775            .word 111f-100b
776            .word 112f-100b
777            .word 113f-100b
778            .word 114f-100b
779            .word 115f-100b
780            .word 116f-100b
781            .word 117f-100b
782            .word 118f-100b
783            .word 119f-100b
784            .word 120f-100b
785            .word 121f-100b
786            .word 122f-100b
787            .word 123f-100b
788            .word 124f-100b
789            .word 125f-100b
790    125:    add         r12, r9, #0x0d0
791            bic         r12, r12, #0x200
792            vld1.u16    {d24,d25}, [r12:128]
793            vmlal.u16   q14, d24, d6[1]
794            vmlal.u16   q15, d25, d6[1]
795            vmlal.u16   q14, d20, d6[1]
796            vmlal.u16   q15, d21, d6[1]
797    124:    add         r12, r9, #0x0d8
798            bic         r12, r12, #0x200
799            vld1.u16    {d24}, [r12:64]!
800            bic         r12, r12, #0x200
801            vld1.u16    {d25}, [r12]
802            vmlal.u16   q14, d24, d6[0]
803            vmlal.u16   q15, d25, d6[0]
804            vmlal.u16   q14, d19, d6[0]
805            vmlal.u16   q15, d20, d6[0]
806    123:    add         r12, r9, #0x0e0
807            bic         r12, r12, #0x200
808            vld1.u16    {d24,d25}, [r12:128]
809            vmlal.u16   q14, d24, d5[3]
810            vmlal.u16   q15, d25, d5[3]
811            vmlal.u16   q14, d18, d5[3]
812            vmlal.u16   q15, d19, d5[3]
813    122:    add         r12, r9, #0x0e8
814            bic         r12, r12, #0x200
815            vld1.u16    {d24}, [r12:64]!
816            bic         r12, r12, #0x200
817            vld1.u16    {d25}, [r12]
818            vmlal.u16   q14, d24, d5[2]
819            vmlal.u16   q15, d25, d5[2]
820            vmlal.u16   q14, d17, d5[2]
821            vmlal.u16   q15, d18, d5[2]
822    121:    add         r12, r9, #0x0f0
823            bic         r12, r12, #0x200
824            vld1.u16    {d24,d25}, [r12:128]
825            vmlal.u16   q14, d24, d5[1]
826            vmlal.u16   q15, d25, d5[1]
827            vmlal.u16   q14, d16, d5[1]
828            vmlal.u16   q15, d17, d5[1]
829    120:    add         r12, r9, #0x0f8
830            bic         r12, r12, #0x200
831            vld1.u16    {d24}, [r12:64]!
832            bic         r12, r12, #0x200
833            vld1.u16    {d25}, [r12]
834            vmlal.u16   q14, d24, d5[0]
835            vmlal.u16   q15, d25, d5[0]
836            vmlal.u16   q14, d15, d5[0]
837            vmlal.u16   q15, d16, d5[0]
838    119:    add         r12, r9, #0x100
839            bic         r12, r12, #0x200
840            vld1.u16    {d24,d25}, [r12:128]
841            vmlal.u16   q14, d24, d4[3]
842            vmlal.u16   q15, d25, d4[3]
843            vmlal.u16   q14, d14, d4[3]
844            vmlal.u16   q15, d15, d4[3]
845    118:    add         r12, r9, #0x108
846            bic         r12, r12, #0x200
847            vld1.u16    {d24}, [r12:64]!
848            bic         r12, r12, #0x200
849            vld1.u16    {d25}, [r12]
850            vmlal.u16   q14, d24, d4[2]
851            vmlal.u16   q15, d25, d4[2]
852            vmlal.u16   q14, d13, d4[2]
853            vmlal.u16   q15, d14, d4[2]
854    117:    add         r12, r9, #0x110
855            bic         r12, r12, #0x200
856            vld1.u16    {d24,d25}, [r12:128]
857            vmlal.u16   q14, d24, d4[1]
858            vmlal.u16   q15, d25, d4[1]
859            vmlal.u16   q14, d12, d4[1]
860            vmlal.u16   q15, d13, d4[1]
861    116:    add         r12, r9, #0x118
862            bic         r12, r12, #0x200
863            vld1.u16    {d24}, [r12:64]!
864            bic         r12, r12, #0x200
865            vld1.u16    {d25}, [r12]
866            vmlal.u16   q14, d24, d4[0]
867            vmlal.u16   q15, d25, d4[0]
868            vmlal.u16   q14, d11, d4[0]
869            vmlal.u16   q15, d12, d4[0]
870    115:    add         r12, r9, #0x120
871            bic         r12, r12, #0x200
872            vld1.u16    {d24,d25}, [r12:128]
873            vmlal.u16   q14, d24, d3[3]
874            vmlal.u16   q15, d25, d3[3]
875            vmlal.u16   q14, d10, d3[3]
876            vmlal.u16   q15, d11, d3[3]
877    114:    add         r12, r9, #0x128
878            bic         r12, r12, #0x200
879            vld1.u16    {d24}, [r12:64]!
880            bic         r12, r12, #0x200
881            vld1.u16    {d25}, [r12]
882            vmlal.u16   q14, d24, d3[2]
883            vmlal.u16   q15, d25, d3[2]
884            vmlal.u16   q14, d9,  d3[2]
885            vmlal.u16   q15, d10, d3[2]
886    113:    add         r12, r9, #0x130
887            bic         r12, r12, #0x200
888            vld1.u16    {d24,d25}, [r12:128]
889            vmlal.u16   q14, d24, d3[1]
890            vmlal.u16   q15, d25, d3[1]
891            vmlal.u16   q14, d8,  d3[1]
892            vmlal.u16   q15, d9,  d3[1]
893    112:    add         r12, r9, #0x138
894            bic         r12, r12, #0x200
895            vld1.u16    {d24}, [r12:64]!
896            bic         r12, r12, #0x200
897            vld1.u16    {d25}, [r12]
898                                            add         r12, r9, #0x1f8
899                                            bic         r12, r12, #0x200
900                                            vld1.u16    {d26}, [r12:64]
901            vmlal.u16   q14, d24, d3[0]
902            vmlal.u16   q15, d25, d3[0]
903            vmlal.u16   q14, d26, d3[0]   @ Could be d7, without the load, right?
904            vmlal.u16   q15, d8,  d3[0]
905    111:    add         r12, r9, #0x140
906            bic         r12, r12, #0x200
907            vld1.u16    {d24,d25}, [r12:128]
908                                            add         r12, r9, #0x1f0
909                                            bic         r12, r12, #0x200
910                                            vld1.u16    {d26,d27}, [r12:128]
911            vmlal.u16   q14, d24, d2[3]
912            vmlal.u16   q15, d25, d2[3]
913            vmlal.u16   q14, d26, d2[3]
914            vmlal.u16   q15, d27, d2[3]
915    110:    add         r12, r9, #0x148
916            bic         r12, r12, #0x200
917            vld1.u16    {d24}, [r12:64]!
918            bic         r12, r12, #0x200
919            vld1.u16    {d25}, [r12]
920                                            add         r12, r9, #0x1e8
921                                            bic         r12, r12, #0x200
922                                            vld1.u16    {d26}, [r12:64]!
923                                            bic         r12, r12, #0x200
924                                            vld1.u16    {d27}, [r12:64]
925            vmlal.u16   q14, d24, d2[2]
926            vmlal.u16   q15, d25, d2[2]
927            vmlal.u16   q14, d26, d2[2]
928            vmlal.u16   q15, d27, d2[2]
929    109:    add         r12, r9, #0x150
930            bic         r12, r12, #0x200
931            vld1.u16    {d24,d25}, [r12:128]
932                                            add         r12, r9, #0x1e0
933                                            bic         r12, r12, #0x200
934                                            vld1.u16    {d26,d27}, [r12:128]
935            vmlal.u16   q14, d24, d2[1]
936            vmlal.u16   q15, d25, d2[1]
937            vmlal.u16   q14, d26, d2[1]
938            vmlal.u16   q15, d27, d2[1]
939    108:    add         r12, r9, #0x158
940            bic         r12, r12, #0x200
941            vld1.u16    {d24}, [r12:64]!
942            bic         r12, r12, #0x200
943            vld1.u16    {d25}, [r12]
944                                            add         r12, r9, #0x1d8
945                                            bic         r12, r12, #0x200
946                                            vld1.u16    {d26}, [r12:64]!
947                                            bic         r12, r12, #0x200
948                                            vld1.u16    {d27}, [r12:64]
949            vmlal.u16   q14, d24, d2[0]
950            vmlal.u16   q15, d25, d2[0]
951            vmlal.u16   q14, d26, d2[0]
952            vmlal.u16   q15, d27, d2[0]
953    107:    add         r12, r9, #0x160
954            bic         r12, r12, #0x200
955            vld1.u16    {d24,d25}, [r12:128]
956                                            add         r12, r9, #0x1d0
957                                            bic         r12, r12, #0x200
958                                            vld1.u16    {d26,d27}, [r12:128]
959            vmlal.u16   q14, d24, d1[3]
960            vmlal.u16   q15, d25, d1[3]
961            vmlal.u16   q14, d26, d1[3]
962            vmlal.u16   q15, d27, d1[3]
963    106:    add         r12, r9, #0x168
964            bic         r12, r12, #0x200
965            vld1.u16    {d24}, [r12:64]!
966            bic         r12, r12, #0x200
967            vld1.u16    {d25}, [r12]
968                                            add         r12, r9, #0x1c8
969                                            bic         r12, r12, #0x200
970                                            vld1.u16    {d26}, [r12:64]!
971                                            bic         r12, r12, #0x200
972                                            vld1.u16    {d27}, [r12:64]
973            vmlal.u16   q14, d24, d1[2]
974            vmlal.u16   q15, d25, d1[2]
975            vmlal.u16   q14, d26, d1[2]
976            vmlal.u16   q15, d27, d1[2]
977    105:    add         r12, r9, #0x170
978            bic         r12, r12, #0x200
979            vld1.u16    {d24,d25}, [r12:128]
980                                            add         r12, r9, #0x1c0
981                                            bic         r12, r12, #0x200
982                                            vld1.u16    {d26,d27}, [r12:128]
983            vmlal.u16   q14, d24, d1[1]
984            vmlal.u16   q15, d25, d1[1]
985            vmlal.u16   q14, d26, d1[1]
986            vmlal.u16   q15, d27, d1[1]
987    104:    add         r12, r9, #0x178
988            bic         r12, r12, #0x200
989            vld1.u16    {d24}, [r12:64]!
990            bic         r12, r12, #0x200
991            vld1.u16    {d25}, [r12]
992                                            add         r12, r9, #0x1b8
993                                            bic         r12, r12, #0x200
994                                            vld1.u16    {d26}, [r12:64]!
995                                            bic         r12, r12, #0x200
996                                            vld1.u16    {d27}, [r12:64]
997            vmlal.u16   q14, d24, d1[0]
998            vmlal.u16   q15, d25, d1[0]
999            vmlal.u16   q14, d26, d1[0]
1000            vmlal.u16   q15, d27, d1[0]
1001    103:    add         r12, r9, #0x180
1002            bic         r12, r12, #0x200
1003            vld1.u16    {d24,d25}, [r12:128]
1004                                            add         r12, r9, #0x1b0
1005                                            bic         r12, r12, #0x200
1006                                            vld1.u16    {d26,d27}, [r12:128]
1007            vmlal.u16   q14, d24, d0[3]
1008            vmlal.u16   q15, d25, d0[3]
1009            vmlal.u16   q14, d26, d0[3]
1010            vmlal.u16   q15, d27, d0[3]
1011    102:    add         r12, r9, #0x188
1012            bic         r12, r12, #0x200
1013            vld1.u16    {d24}, [r12:64]!
1014            bic         r12, r12, #0x200
1015            vld1.u16    {d25}, [r12]
1016                                            add         r12, r9, #0x1a8
1017                                            bic         r12, r12, #0x200
1018                                            vld1.u16    {d26}, [r12:64]!
1019                                            bic         r12, r12, #0x200
1020                                            vld1.u16    {d27}, [r12:64]
1021            vmlal.u16   q14, d24, d0[2]
1022            vmlal.u16   q15, d25, d0[2]
1023            vmlal.u16   q14, d26, d0[2]
1024            vmlal.u16   q15, d27, d0[2]
1025    101:    add         r12, r9, #0x190
1026            bic         r12, r12, #0x200
1027            vld1.u16    {d24,d25}, [r12:128]!
1028            bic         r12, r12, #0x200
1029            vld1.u16    {d26,d27}, [r12:128]
1030            vmlal.u16   q14, d24, d0[1]
1031            vmlal.u16   q15, d25, d0[1]
1032            vmlal.u16   q14, d26, d0[1]
1033            vmlal.u16   q15, d27, d0[1]
1034
1035            vqrshrn.u32 d28, q14, #16
1036            vqrshrn.u32 d29, q15, #16
1037            vqrshrn.u16 d31, q14, #FRACTION_BITS
1038
1039            vst1.u8     {q4}, [r9:128]!
1040            bic         r9, r9, #0x200
1041            vmov        q4, q5
1042            vmov        q5, q6
1043            vmov        q6, q7
1044            vmov        q7, q8
1045            vmov        q8, q9
1046            vmov        q9, q10
1047            vmov        q10, q11
1048.endm/*}}}*/
1049
1050/* Dedicated function wrapper for the fetch macro, for the cases where
1051 * performance isn't that important, to keep code size down.
1052 */
1053PRIVATE(fetch_generic_asm)
1054            push        {r10,r11}
1055            fetch
1056            pop         {r10,r11}
1057            bx          lr
1058END(fetch_generic_asm)
1059
1060/* Given values in q10 and q11, and an index in r11, sweep the (r11&15)th value
1061 * across to fill the rest of the register pair.  Used for filling the right
1062 * hand edge of the window when starting too close to the right hand edge of
1063 * the image.
1064 * Also returns a dup-ed copy of the last element in q12 for the tail-fill
1065 * case (this happens incidentally in common path, but must be done
1066 * deliberately in the fast-out path).
1067 */
1068PRIVATE(prefetch_clampright1)
1069            ands        r12, r11, #15
1070            beq         1f
1071            sub         r12, r12, #1
1072            sub         sp, sp, #64
1073            vst1.u16    {q10,q11}, [sp]
1074            add         r12, sp, r12, LSL #1
1075            vld1.u16    {d24[]}, [r12]
1076            vld1.u16    {d25[]}, [r12]
1077            vst1.u16    {q12}, [r12]!
1078            vst1.u16    {q12}, [r12]
1079            vld1.u16    {q10,q11}, [sp]
1080            add         sp, sp, #64
1081            bx          lr
10821:          vdup.u16    q12, d23[3]
1083            bx          lr
1084END(prefetch_clampright1)
1085
1086PRIVATE(prefetch_clampright4)
1087            ands        r12, r11, #15
1088            beq         1f
1089            sub         r12, r12, #4
1090            sub         sp, sp, #64
1091            vst1.u16    {q10,q11}, [sp]
1092            add         r12, sp, r12, LSL #1
1093            vld1.u64    {d24}, [r12]
1094            vld1.u64    {d25}, [r12]
1095            vst1.u16    {q12}, [r12]!
1096            vst1.u16    {q12}, [r12]
1097            vld1.u16    {q10,q11}, [sp]
1098            add         sp, sp, #64
1099            bx          lr
11001:          vmov.u16    d24, d23
1101            vmov.u16    d25, d23
1102            bx          lr
1103END(prefetch_clampright4)
1104
1105
1106/* Helpers for prefetch, below.
1107 */
1108.macro prefetch_out qa, qb, store, qsa, qsb, qsb_hi
1109  .if \store > 0
1110    .ifc \qsa,\qsb
1111            vst1.u16    {\qsa}, [r9:128]!
1112            vst1.u16    {\qsb}, [r9:128]!
1113    .else
1114            vst1.u16    {\qsa,\qsb}, [r9:256]!
1115    .endif
1116  .elseif \store == 0
1117            vmov.u16    \qa, \qsa
1118            vmov.u16    \qb, \qsb
1119  .else
1120            vmov.u16    \qb, \qsb_hi
1121  .endif
1122.endm
1123
1124.macro prefetch_one  qa, qb, rem, c, store=0, step=1
1125.set i, (need - 16) - \rem
1126.if i >= 0
11271:          cmp         r10, #i+16
1128            blo         2f
1129            prefetch_out \qa, \qb, \store, q9, q9, d19
1130            b           1f
11312:          cmp         r11, #i+16
1132            bls         3f
1133            prefetch_out \qa, \qb, \store, q10, q11, d23
1134            bl          fetch_generic_asm
1135            b           2f
11363:          bl          prefetch_clampright\step
1137            prefetch_out \qa, \qb, \store, q10, q11, d23
11384:          b           4f+4
1139            @q12 contains pad word from prefetch_clampright call
1140            prefetch_out \qa, \qb, \store, q12, q12, d25
1141  .if \rem > 0
1142            b           4f+4
1143  .else
11441:
11452:
11463:
11474:          nop
1148  .endif
1149.endif
1150.endm
1151
1152/* Fill the convolution window with context data.  The aim here is to load
1153 * exactly rlf + rrt columns, and in the main loop to read as many columns as
1154 * will be written.  This is complicated by the need to handle cases when the
1155 * input starts very close to the left or right (or both) edges of the image,
1156 * and where these do not fall on 16-byte boundaries.
1157 *
1158 * Input:
1159 *      r1 -- src
1160 *      r2 -- pitch
1161 *      r3 -- count
1162 *      r4 -- inlen
1163 *      r5 -- r
1164 *      r6 -- rup
1165 *      r7 -- rdn
1166 *      r8 -- rlf
1167 *      r9 -- buffer (if needed)
1168 * Output:
1169 *      r1 += rlf + min(count, rrt)
1170 * Modifies:
1171 *      r10 -- fill start index in the window
1172 *      r11 -- fill stop index in the window
1173 *      r12 -- scratch
1174 */
1175.macro prefetch step=1, max_r=25
1176.set need, ((\max_r + \max_r) * \step + 15) & ~15
1177  .if \step == 1
1178            rsb         r10, r8, #need - (\max_r * \step)
1179  .else
1180            mov         r10, r8, LSL #2
1181            rsb         r10, r10, #need - (\max_r * \step)
1182  .endif
1183            add         r11, r10, r4
1184            cmp         r11, #need
1185            movhi       r11, #need
1186
1187            bl          fetch_generic_asm
1188  .if \step == 1
1189            vdup.u16    q9, d20[0]
1190  .else
1191            vmov.u16    d18, d20
1192            vmov.u16    d19, d20
1193  .endif
1194            ands        r12, r10, #15
1195            beq         2f
1196            sub         sp, sp, #32
1197            vst1.u16    {q10,q11}, [sp]
1198            sub         r12, sp, r12, LSL #1
1199            sub         sp, sp, #16
1200            vst1.u16    {q9}, [sp]
1201            sub         sp, sp, #16
1202            vst1.u16    {q9}, [sp]
1203            vld1.u16    {q10,q11}, [r12]
1204            add         sp, sp, #64
1205            sub         r1, r1, r10
1206            bic         r10, r10, #15
1207            add         r1, r1, r10
12082:
1209  .if \step > 1
1210            /* it's only in the uchar2 and uchar4 cases where the register file
1211             * is insufficient (given MAX_R <= 25).
1212             */
1213            prefetch_one xx, xx, 192, c=\max_r, step=\step, store=1
1214            prefetch_one xx, xx, 176, c=\max_r, step=\step, store=1
1215            prefetch_one xx, xx, 160, c=\max_r, step=\step, store=1
1216            prefetch_one xx, xx, 144, c=\max_r, step=\step, store=1
1217            prefetch_one xx, xx, 128, c=\max_r, step=\step, store=1
1218            prefetch_one xx, xx, 112, c=\max_r, step=\step, store=1
1219            prefetch_one xx, xx,  96, c=\max_r, step=\step, store=1
1220            prefetch_one xx, xx,  80, c=\max_r, step=\step, store=1
1221            prefetch_one xx, xx,  64, c=\max_r, step=\step, store=1
1222            prefetch_one xx, xx,  48, c=\max_r, step=\step, store=1
1223  .else
1224            /* q3 normally contains the coefficient table, but it's not fully
1225             * used.  In the uchar1, r=25 case the other half of q3 is used for
1226             * the last two window taps to avoid falling out to memory.
1227             */
1228            prefetch_one xx, d7,  48, c=\max_r, step=\step, store=-1
1229  .endif
1230            prefetch_one q4, q5,  32, c=\max_r, step=\step, store=0
1231            prefetch_one q6, q7,  16, c=\max_r, step=\step, store=0
1232            prefetch_one q8, q9,   0, c=\max_r, step=\step, store=0
1233
1234  .if \step == 1
1235            add         r10, r8, #\max_r * \step
1236  .else
1237            mov         r10, r8, LSL #2
1238            add         r10, r10, #\max_r * \step
1239  .endif
1240            subs        r4, r4, r10
1241            movlo       r4, #0
1242.endm
1243
1244/* The main loop.
1245 *
1246 * Input:
1247 *      r0 = dst
1248 *      r1 = src
1249 *      r2 = pitch
1250 *      r3 = count
1251 *      r4 = inlen
1252 *      r5 = r
1253 *      r6 = rup
1254 *      r7 = rdn
1255 *      r9 = buffer
1256 * Modifies
1257 *      r8 = fetch code pointer
1258 */
1259.macro mainloop core, step=1, max_r=25, labelc="", labelnc=""
1260            ldr         r8, 3f
12611:          add         r8, r8, pc
1262            sub         r8, r5, LSL #5
1263            sub         r8, r5, LSL #4
1264            cmp         r5, r6
1265            cmpeq       r5, r7
1266            beq         5f
1267
1268            /* if (r != rup || r != rdn) then the address-clamping table should
1269             * be used rather than the short-cut version.
1270             */
1271            ldr         r8, 3f+4
12722:          add         r8, r8, pc
1273            sub         r8, r5, LSL #6
1274            b           5f
1275            .align 3
12763:          .word       \labelnc-1b-8
1277            .word       \labelc-2b-8
1278            .align 4
12793:          fetch max_r=\max_r, labelc=\labelc, labelnc=\labelnc, reg=r8
1280
1281            /* For each call to fetch two are made to \core.  It would be
1282             * preferable to have twice the work done in \core, but the
1283             * register file is too small for this to be straightforward.
1284             */
1285            \core
1286            vst1.u8     {d31}, [r0]!
1287            \core
1288            vst1.u8     {d31}, [r0]!
1289
1290            sub         r3, r3, #16
12915:          subs        r4, r4, #16
1292            bhs         3b
1293            adds        r4, r4, #16
1294            bne         1f
1295  .if \step==1
1296            vdup.u16    q10, d19[3]
1297            vdup.u16    q11, d19[3]
1298  .else
1299            vmov.u64    d20, d19
1300            vmov.u64    d21, d19
1301            vmov.u64    d22, d19
1302            vmov.u64    d23, d19
1303  .endif
1304            b           4f
1305
13061:          sub         r1, r1, #16
1307            add         r1, r1, r4
1308            bl          fetch_generic_asm
1309
1310  .if \step==1
1311            vdup.u16    q12, d23[3]
1312  .else
1313            vmov.u64    d24, d23
1314            vmov.u64    d25, d23
1315  .endif
1316            rsb         r4, r4, #0
1317            tst         r4, #8
1318            beq         1f
1319            vmov        q10, q11
1320            vmov        q11, q12
13211:          tst         r4, #4
1322            beq         1f
1323            vext.u16    q10, q10, q11, #4
1324            vext.u16    q11, q11, q12, #4
13251:          tst         r4, #2
1326            beq         1f
1327            vext.u16    q10, q10, q11, #2
1328            vext.u16    q11, q11, q12, #2
13291:          tst         r4, #1
1330            beq         4f
1331            vext.u16    q10, q10, q11, #1
1332            vext.u16    q11, q11, q12, #1
13334:          cmp         r3, #0
1334            beq         5f
13353:          \core
1336  .if \step==1
1337            vdup.u16    q11, d23[3]
1338  .else
1339            vmov.u64    d22, d23
1340  .endif
1341            subs        r3, r3, #8
1342            blo         4f
1343            vst1.u8     {d31}, [r0]!
1344            beq         5f
1345            b           3b
13464:          tst         r3, #4
1347            beq         1f
1348            vst1.u32    {d31[0]}, [r0]!
1349            vext.u8     d31, d31, d31, #4
13501:          tst         r3, #2
1351            beq         1f
1352            vst1.u16    {d31[0]}, [r0]!
1353            vext.u8     d31, d31, d31, #2
13541:          tst         r3, #1
1355            beq         5f
1356            vst1.u8     {d31[0]}, [r0]!
1357            vext.u8     d31, d31, d31, #1
13585:          nop
1359.endm
1360
1361.irep r, TUNED_LIST1, 25
1362PRIVATE(convolve1_\r)
1363            push        {r12,lr}
1364
1365            sub         r1, r1, r8
1366
1367            prefetch    step=1, max_r=\r
1368
1369            mainloop    core=hconv1_\r, step=1, max_r=\r, labelc=.Lcnv1_\r, labelnc=.Lcnvnc1_\r
1370
1371            pop         {r12,pc}
1372END(convolve1_\r)
1373.endr
1374
1375.irep r, TUNED_LIST4, 25
1376PRIVATE(convolve4_\r)
1377            sub         r12, sp, #0x200
1378            bic         r9, r12, #0x3fc
1379            mov         sp, r9
1380            push        {r12,lr}
1381
1382            /* r9 now points to a buffer on the stack whose address has the low
1383             * 10 bits clear.  This allows easy address calculation in the
1384             * wrap-around cases.
1385             */
1386
1387            sub         r1, r1, r8, LSL #2
1388
1389            prefetch    step=4, max_r=\r
1390
1391            mainloop    core=hconv4_\r, step=4, max_r=\r, labelc=.Lcnv4_\r, labelnc=.Lcnvnc4_\r
1392
1393            pop         {r12,lr}
1394            add         sp, r12, #0x200
1395            bx          lr
1396END(convolve4_\r)
1397.endr
1398
1399/* void rsdIntrinsicBlurU1_K(
1400 *                  void *out,      // r0
1401 *                  void *in,       // r1
1402 *                  size_t w,       // r2
1403 *                  size_t h,       // r3
1404 *                  size_t p,       // [sp]
1405 *                  size_t x,       // [sp,#4]
1406 *                  size_t y,       // [sp,#8]
1407 *                  size_t count,   // [sp,#12]
1408 *                  size_t r,       // [sp,#16]
1409 *                  uint16_t *tab); // [sp,#20]
1410 */
1411ENTRY(rsdIntrinsicBlurU1_K)
1412            push        {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
1413            vpush       {d8-d15}
1414            ldr         r5, [sp,#120]
1415            ldr         r8, [sp,#108]
1416            ldr         r6, [sp,#112]
1417            sub         r9, r2, r8
1418            sub         r7, r3, r6
1419            ldr         r2, [sp,#104]
1420            ldr         r3, [sp,#116]
1421            sub         r9, r9, r3
1422            sub         r7, r7, #1
1423
1424            ldr         r12, [sp,#124]
1425
1426            add         r1, r1, r8
1427
1428            cmp         r6, r5
1429            movhi       r6, r5
1430            cmp         r7, r5
1431            movhi       r7, r5
1432            cmp         r8, r5
1433            movhi       r8, r5
1434            cmp         r9, r5
1435            movhi       r9, r5
1436
1437            add         r4, r8, r9
1438            add         r4, r4, r3
1439
1440            vld1.u16    {d0,d1,d2,d3}, [r12]!
1441            vld1.u16    {d4,d5,d6}, [r12]!
1442
1443            adr         lr, 1f
1444  .irep r, TUNED_LIST1
1445            cmp         r5, #\r
1446            bls         convolve1_\r
1447  .endr
1448            b           convolve1_25
1449
14501:          vpop        {d8-d15}
1451            pop         {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
1452END(rsdIntrinsicBlurU1_K)
1453
1454/* void rsdIntrinsicBlurU4_K(
1455 *                  void *out,      // r0
1456 *                  void *in,       // r1
1457 *                  size_t w,       // r2
1458 *                  size_t h,       // r3
1459 *                  size_t p,       // [sp]
1460 *                  size_t x,       // [sp,#4]
1461 *                  size_t y,       // [sp,#8]
1462 *                  size_t count,   // [sp,#12]
1463 *                  size_t r,       // [sp,#16]
1464 *                  uint16_t *tab); // [sp,#20]
1465 */
1466ENTRY(rsdIntrinsicBlurU4_K)
1467            push        {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
1468            vpush       {d8-d15}
1469            ldr         r5, [sp,#120]
1470            ldr         r8, [sp,#108]
1471            ldr         r6, [sp,#112]
1472            sub         r9, r2, r8
1473            sub         r7, r3, r6
1474            ldr         r2, [sp,#104]
1475            ldr         r3, [sp,#116]
1476            sub         r9, r9, r3
1477            sub         r7, r7, #1
1478
1479            ldr         r12, [sp,#124]
1480
1481            add         r1, r1, r8, LSL #2
1482
1483            cmp         r6, r5
1484            movhi       r6, r5
1485            cmp         r7, r5
1486            movhi       r7, r5
1487            cmp         r8, r5
1488            movhi       r8, r5
1489            cmp         r9, r5
1490            movhi       r9, r5
1491
1492            mov         r3, r3, LSL #2
1493            add         r4, r8, r9
1494            add         r4, r3, r4, LSL #2
1495
1496            vld1.u16    {d0,d1,d2,d3}, [r12]!
1497            vld1.u16    {d4,d5,d6}, [r12]!
1498
1499            adr         lr, 1f
1500  .irep r, TUNED_LIST4
1501            cmp         r5, #\r
1502            bls         convolve4_\r
1503  .endr
1504            b           convolve4_25
1505
15061:          vpop        {d8-d15}
1507            pop         {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
1508END(rsdIntrinsicBlurU4_K)
1509