Fix rounding for DIV_UNc()
[profile/ivi/pixman.git] / pixman / pixman-arm-simd-asm.S
1 /*
2  * Copyright © 2008 Mozilla Corporation
3  * Copyright © 2010 Nokia Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of Mozilla Corporation not be used in
10  * advertising or publicity pertaining to distribution of the software without
11  * specific, written prior permission.  Mozilla Corporation makes no
12  * representations about the suitability of this software for any purpose.  It
13  * is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
21  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22  * SOFTWARE.
23  *
24  * Author:  Jeff Muizelaar (jeff@infidigm.net)
25  *
26  */
27
28 /* Prevent the stack from becoming executable */
29 #if defined(__linux__) && defined(__ELF__)
30 .section .note.GNU-stack,"",%progbits
31 #endif
32
33         .text
34         .arch armv6
35         .object_arch armv4
36         .arm
37         .altmacro
38         .p2align 2
39
40 /* Supplementary macro for setting function attributes */
41 .macro pixman_asm_function fname
42         .func fname
43         .global fname
44 #ifdef __ELF__
45         .hidden fname
46         .type fname, %function
47 #endif
48 fname:
49 .endm
50
51 /*
52  * The code below was generated by gcc 4.3.4 from the commented out
53  * functions in 'pixman-arm-simd.c' file with the following optimization
54  * options: "-O3 -mcpu=arm1136jf-s -fomit-frame-pointer"
55  *
56  * TODO: replace gcc generated code with hand tuned versions because
57  * the code quality is not very good, introduce symbolic register
58  * aliases for better readability and maintainability.
59  */
60
61 pixman_asm_function pixman_composite_add_8_8_asm_armv6
62         push    {r4, r5, r6, r7, r8, r9, r10, r11}
63         mov     r10, r1
64         sub     sp, sp, #4
65         subs    r10, r10, #1
66         mov     r11, r0
67         mov     r8, r2
68         str     r3, [sp]
69         ldr     r7, [sp, #36]
70         bcc     0f
71 6:      cmp     r11, #0
72         beq     1f
73         orr     r3, r8, r7
74         tst     r3, #3
75         beq     2f
76         mov     r1, r8
77         mov     r0, r7
78         mov     r12, r11
79         b       3f
80 5:      tst     r3, #3
81         beq     4f
82 3:      ldrb    r2, [r0], #1
83         subs    r12, r12, #1
84         ldrb    r3, [r1]
85         uqadd8  r3, r2, r3
86         strb    r3, [r1], #1
87         orr     r3, r1, r0
88         bne     5b
89 1:      ldr     r3, [sp]
90         add     r8, r8, r3
91         ldr     r3, [sp, #40]
92         add     r7, r7, r3
93 10:     subs    r10, r10, #1
94         bcs     6b
95 0:      add     sp, sp, #4
96         pop     {r4, r5, r6, r7, r8, r9, r10, r11}
97         bx      lr
98 2:      mov     r12, r11
99         mov     r1, r8
100         mov     r0, r7
101 4:      cmp     r12, #3
102         subgt   r6, r12, #4
103         movgt   r9, r12
104         lsrgt   r5, r6, #2
105         addgt   r3, r5, #1
106         movgt   r12, #0
107         lslgt   r4, r3, #2
108         ble     7f
109 8:      ldr     r3, [r0, r12]
110         ldr     r2, [r1, r12]
111         uqadd8  r3, r3, r2
112         str     r3, [r1, r12]
113         add     r12, r12, #4
114         cmp     r12, r4
115         bne     8b
116         sub     r3, r9, #4
117         bic     r3, r3, #3
118         add     r3, r3, #4
119         subs    r12, r6, r5, lsl #2
120         add     r1, r1, r3
121         add     r0, r0, r3
122         beq     1b
123 7:      mov     r4, #0
124 9:      ldrb    r3, [r1, r4]
125         ldrb    r2, [r0, r4]
126         uqadd8  r3, r2, r3
127         strb    r3, [r1, r4]
128         add     r4, r4, #1
129         cmp     r4, r12
130         bne     9b
131         ldr     r3, [sp]
132         add     r8, r8, r3
133         ldr     r3, [sp, #40]
134         add     r7, r7, r3
135         b       10b
136 .endfunc
137
138 pixman_asm_function pixman_composite_over_8888_8888_asm_armv6
139         push    {r4, r5, r6, r7, r8, r9, r10, r11}
140         sub     sp, sp, #20
141         cmp     r1, #0
142         mov     r12, r2
143         str     r1, [sp, #12]
144         str     r0, [sp, #16]
145         ldr     r2, [sp, #52]
146         beq     0f
147         lsl     r3, r3, #2
148         str     r3, [sp]
149         ldr     r3, [sp, #56]
150         mov     r10, #0
151         lsl     r3, r3, #2
152         str     r3, [sp, #8]
153         mov     r11, r3
154         b       1f
155 6:      ldr     r11, [sp, #8]
156 1:      ldr     r9, [sp]
157         mov     r0, r12
158         add     r12, r12, r9
159         mov     r1, r2
160         str     r12, [sp, #4]
161         add     r2, r2, r11
162         ldr     r12, [sp, #16]
163         ldr     r3, =0x00800080
164         ldr     r9, =0xff00ff00
165         mov     r11, #255
166         cmp     r12, #0
167         beq     4f
168 5:      ldr     r5, [r1], #4
169         ldr     r4, [r0]
170         sub     r8, r11, r5, lsr #24
171         uxtb16  r6, r4
172         uxtb16  r7, r4, ror #8
173         mla     r6, r6, r8, r3
174         mla     r7, r7, r8, r3
175         uxtab16 r6, r6, r6, ror #8
176         uxtab16 r7, r7, r7, ror #8
177         and     r7, r7, r9
178         uxtab16 r6, r7, r6, ror #8
179         uqadd8  r5, r6, r5
180         str     r5, [r0], #4
181         subs    r12, r12, #1
182         bne     5b
183 4:      ldr     r3, [sp, #12]
184         add     r10, r10, #1
185         cmp     r10, r3
186         ldr     r12, [sp, #4]
187         bne     6b
188 0:      add     sp, sp, #20
189         pop     {r4, r5, r6, r7, r8, r9, r10, r11}
190         bx      lr
191 .endfunc
192
193 pixman_asm_function pixman_composite_over_8888_n_8888_asm_armv6
194         push    {r4, r5, r6, r7, r8, r9, r10, r11}
195         sub     sp, sp, #28
196         cmp     r1, #0
197         str     r1, [sp, #12]
198         ldrb    r1, [sp, #71]
199         mov     r12, r2
200         str     r0, [sp, #16]
201         ldr     r2, [sp, #60]
202         str     r1, [sp, #24]
203         beq     0f
204         lsl     r3, r3, #2
205         str     r3, [sp, #20]
206         ldr     r3, [sp, #64]
207         mov     r10, #0
208         lsl     r3, r3, #2
209         str     r3, [sp, #8]
210         mov     r11, r3
211         b       1f
212 5:      ldr     r11, [sp, #8]
213 1:      ldr     r4, [sp, #20]
214         mov     r0, r12
215         mov     r1, r2
216         add     r12, r12, r4
217         add     r2, r2, r11
218         str     r12, [sp]
219         str     r2, [sp, #4]
220         ldr     r12, [sp, #16]
221         ldr     r2, =0x00800080
222         ldr     r3, [sp, #24]
223         mov     r11, #255
224         cmp     r12, #0
225         beq     3f
226 4:      ldr     r5, [r1], #4
227         ldr     r4, [r0]
228         uxtb16  r6, r5
229         uxtb16  r7, r5, ror #8
230         mla     r6, r6, r3, r2
231         mla     r7, r7, r3, r2
232         uxtab16 r6, r6, r6, ror #8
233         uxtab16 r7, r7, r7, ror #8
234         uxtb16  r6, r6, ror #8
235         uxtb16  r7, r7, ror #8
236         orr     r5, r6, r7, lsl #8
237         uxtb16  r6, r4
238         uxtb16  r7, r4, ror #8
239         sub     r8, r11, r5, lsr #24
240         mla     r6, r6, r8, r2
241         mla     r7, r7, r8, r2
242         uxtab16 r6, r6, r6, ror #8
243         uxtab16 r7, r7, r7, ror #8
244         uxtb16  r6, r6, ror #8
245         uxtb16  r7, r7, ror #8
246         orr     r6, r6, r7, lsl #8
247         uqadd8  r5, r6, r5
248         str     r5, [r0], #4
249         subs    r12, r12, #1
250         bne     4b
251 3:      ldr     r1, [sp, #12]
252         add     r10, r10, #1
253         cmp     r10, r1
254         ldr     r12, [sp]
255         ldr     r2, [sp, #4]
256         bne     5b
257 0:      add     sp, sp, #28
258         pop     {r4, r5, r6, r7, r8, r9, r10, r11}
259         bx      lr
260 .endfunc
261
262 pixman_asm_function pixman_composite_over_n_8_8888_asm_armv6
263         push    {r4, r5, r6, r7, r8, r9, r10, r11}
264         sub     sp, sp, #28
265         cmp     r1, #0
266         ldr     r9, [sp, #60]
267         str     r1, [sp, #12]
268         bic     r1, r9, #-16777216
269         str     r1, [sp, #20]
270         mov     r12, r2
271         lsr     r1, r9, #8
272         ldr     r2, [sp, #20]
273         bic     r1, r1, #-16777216
274         bic     r2, r2, #65280
275         bic     r1, r1, #65280
276         str     r2, [sp, #20]
277         str     r0, [sp, #16]
278         str     r1, [sp, #4]
279         ldr     r2, [sp, #68]
280         beq     0f
281         lsl     r3, r3, #2
282         str     r3, [sp, #24]
283         mov     r0, #0
284         b       1f
285 5:      ldr     r3, [sp, #24]
286 1:      ldr     r4, [sp, #72]
287         mov     r10, r12
288         mov     r1, r2
289         add     r12, r12, r3
290         add     r2, r2, r4
291         str     r12, [sp, #8]
292         str     r2, [sp]
293         ldr     r12, [sp, #16]
294         ldr     r11, =0x00800080
295         ldr     r2, [sp, #4]
296         ldr     r3, [sp, #20]
297         cmp     r12, #0
298         beq     3f
299 4:      ldrb    r5, [r1], #1
300         ldr     r4, [r10]
301         mla     r6, r3, r5, r11
302         mla     r7, r2, r5, r11
303         uxtab16 r6, r6, r6, ror #8
304         uxtab16 r7, r7, r7, ror #8
305         uxtb16  r6, r6, ror #8
306         uxtb16  r7, r7, ror #8
307         orr     r5, r6, r7, lsl #8
308         uxtb16  r6, r4
309         uxtb16  r7, r4, ror #8
310         mvn     r8, r5
311         lsr     r8, r8, #24
312         mla     r6, r6, r8, r11
313         mla     r7, r7, r8, r11
314         uxtab16 r6, r6, r6, ror #8
315         uxtab16 r7, r7, r7, ror #8
316         uxtb16  r6, r6, ror #8
317         uxtb16  r7, r7, ror #8
318         orr     r6, r6, r7, lsl #8
319         uqadd8  r5, r6, r5
320         str     r5, [r10], #4
321         subs    r12, r12, #1
322         bne     4b
323 3:      ldr     r4, [sp, #12]
324         add     r0, r0, #1
325         cmp     r0, r4
326         ldr     r12, [sp, #8]
327         ldr     r2, [sp]
328         bne     5b
329 0:      add     sp, sp, #28
330         pop     {r4, r5, r6, r7, r8, r9, r10, r11}
331         bx      lr
332 .endfunc
333
334 /*
335  * Note: This code is only using armv5te instructions (not even armv6),
336  *       but is scheduled for ARM Cortex-A8 pipeline. So it might need to
337  *       be split into a few variants, tuned for each microarchitecture.
338  *
339  * TODO: In order to get good performance on ARM9/ARM11 cores (which don't
340  * have efficient write combining), it needs to be changed to use 16-byte
341  * aligned writes using STM instruction.
342  *
343  * Nearest scanline scaler macro template uses the following arguments:
344  *  fname                     - name of the function to generate
345  *  bpp_shift                 - (1 << bpp_shift) is the size of pixel in bytes
346  *  t                         - type suffix for LDR/STR instructions
347  *  prefetch_distance         - prefetch in the source image by that many
348  *                              pixels ahead
349  *  prefetch_braking_distance - stop prefetching when that many pixels are
350  *                              remaining before the end of scanline
351  */
352
353 .macro generate_nearest_scanline_func fname, bpp_shift, t,      \
354                                       prefetch_distance,        \
355                                       prefetch_braking_distance
356
357 pixman_asm_function fname
358         W       .req    r0
359         DST     .req    r1
360         SRC     .req    r2
361         VX      .req    r3
362         UNIT_X  .req    ip
363         TMP1    .req    r4
364         TMP2    .req    r5
365         VXMASK  .req    r6
366         PF_OFFS .req    r7
367
368         ldr     UNIT_X, [sp]
369         push    {r4, r5, r6, r7}
370         mvn     VXMASK, #((1 << bpp_shift) - 1)
371
372         /* define helper macro */
373         .macro  scale_2_pixels
374                 ldr&t   TMP1, [SRC, TMP1]
375                 and     TMP2, VXMASK, VX, lsr #(16 - bpp_shift)
376                 add     VX, VX, UNIT_X
377                 str&t   TMP1, [DST], #(1 << bpp_shift)
378
379                 ldr&t   TMP2, [SRC, TMP2]
380                 and     TMP1, VXMASK, VX, lsr #(16 - bpp_shift)
381                 add     VX, VX, UNIT_X
382                 str&t   TMP2, [DST], #(1 << bpp_shift)
383         .endm
384
385         /* now do the scaling */
386         and     TMP1, VXMASK, VX, lsr #(16 - bpp_shift)
387         add     VX, VX, UNIT_X
388         subs    W, W, #(8 + prefetch_braking_distance)
389         blt     2f
390         /* calculate prefetch offset */
391         mov     PF_OFFS, #prefetch_distance
392         mla     PF_OFFS, UNIT_X, PF_OFFS, VX
393 1:      /* main loop, process 8 pixels per iteration with prefetch */
394         subs    W, W, #8
395         add     PF_OFFS, UNIT_X, lsl #3
396         scale_2_pixels
397         scale_2_pixels
398         scale_2_pixels
399         scale_2_pixels
400         pld     [SRC, PF_OFFS, lsr #(16 - bpp_shift)]
401         bge     1b
402 2:
403         subs    W, W, #(4 - 8 - prefetch_braking_distance)
404         blt     2f
405 1:      /* process the remaining pixels */
406         scale_2_pixels
407         scale_2_pixels
408         subs    W, W, #4
409         bge     1b
410 2:
411         tst     W, #2
412         beq     2f
413         scale_2_pixels
414 2:
415         tst     W, #1
416         ldrne&t TMP1, [SRC, TMP1]
417         strne&t TMP1, [DST]
418         /* cleanup helper macro */
419         .purgem scale_2_pixels
420         .unreq  DST
421         .unreq  SRC
422         .unreq  W
423         .unreq  VX
424         .unreq  UNIT_X
425         .unreq  TMP1
426         .unreq  TMP2
427         .unreq  VXMASK
428         .unreq  PF_OFFS
429         /* return */
430         pop     {r4, r5, r6, r7}
431         bx      lr
432 .endfunc
433 .endm
434
435 generate_nearest_scanline_func \
436     pixman_scaled_nearest_scanline_0565_0565_SRC_asm_armv6, 1, h, 80, 32
437
438 generate_nearest_scanline_func \
439     pixman_scaled_nearest_scanline_8888_8888_SRC_asm_armv6, 2,  , 48, 32