tests: add armv7 debug test and a register dumper
[pandora-misc.git] / tests / fbturbo_asm.S
1 /*
2  * Copyright © 2006-2008, 2013 Siarhei Siamashka <siarhei.siamashka@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23
24 /* Prevent the stack from becoming executable */
25 #if defined(__linux__) && defined(__ELF__)
26 .section .note.GNU-stack,"",%progbits
27 #endif
28
29 #ifdef __arm__
30
31 .text
32 .syntax unified
33 .fpu neon
34 .arch armv7a
35 .object_arch armv4
36 .arm
37 .altmacro
38 .p2align 2
39
40 /******************************************************************************/
41
42 .macro asm_function function_name
43     .global \function_name
44 #ifdef __ELF__
45     .hidden \function_name
46     .type \function_name, %function
47 #endif
48 .func \function_name
49 \function_name:
50 .endm
51
52 /******************************************************************************/
53
54 /*
55  * writeback_scratch_to_mem_neon(int numbytes, void *dst, void *src)
56  *
57  * Copy a chunk of data from a cached scratch buffer (so prefetch is not
58  * really needed), to a memory buffer in forward direction. Generated from
59  * pixman macro templates.
60  */
61
62 asm_function writeback_scratch_to_mem_neon
63         mov     ip, r1
64         cmp     r0, #32
65         blt     0f
66         tst     ip, #15
67         beq     1f
68         tst     ip, #1
69         beq     2f
70         vld1.8  {d0[1]}, [r2]!
71         add     ip, ip, #1
72         sub     r0, r0, #1
73 2:      tst     ip, #2
74         beq     3f
75         vld1.8  {d0[2]}, [r2]!
76         vld1.8  {d0[3]}, [r2]!
77         add     ip, ip, #2
78         sub     r0, r0, #2
79 3:      tst     ip, #4
80         beq     4f
81         vld1.8  {d0[4]}, [r2]!
82         vld1.8  {d0[5]}, [r2]!
83         vld1.8  {d0[6]}, [r2]!
84         vld1.8  {d0[7]}, [r2]!
85         add     ip, ip, #4
86         sub     r0, r0, #4
87 4:      tst     ip, #8
88         beq     5f
89         vld1.8  {d1}, [r2]!
90         add     ip, ip, #8
91         sub     r0, r0, #8
92 5:      vld1.8  {d2-d3}, [r2]!
93         add     ip, ip, #16
94         sub     r0, r0, #16
95         tst     r1, #1
96         beq     6f
97         vst1.8  {d0[1]}, [r1]!
98 6:      tst     r1, #2
99         beq     7f
100         vst1.8  {d0[2]}, [r1]!
101         vst1.8  {d0[3]}, [r1]!
102 7:      tst     r1, #4
103         beq     8f
104         vst1.8  {d0[4]}, [r1]!
105         vst1.8  {d0[5]}, [r1]!
106         vst1.8  {d0[6]}, [r1]!
107         vst1.8  {d0[7]}, [r1]!
108 8:      tst     r1, #8
109         beq     9f
110         vst1.8  {d1}, [r1, :64]!
111 9:      vst1.8  {d2-d3}, [r1, :128]!
112 1:      subs    r0, r0, #32
113         blt     10f
114         vld1.8  {d0-d3}, [r2]!
115         subs    r0, r0, #32
116         blt     11f
117 12:     vst1.8  {d0-d3}, [r1, :128]!
118         vld1.8  {d0-d3}, [r2]!
119         subs    r0, r0, #32
120         bge     12b
121 11:     vst1.8  {d0-d3}, [r1, :128]!
122 10:     tst     r0, #31
123         beq     13f
124         tst     r0, #16
125         beq     14f
126         vld1.8  {d2-d3}, [r2]!
127 14:     tst     r0, #8
128         beq     15f
129         vld1.8  {d1}, [r2]!
130 15:     tst     r0, #4
131         beq     16f
132         vld1.8  {d0[4]}, [r2]!
133         vld1.8  {d0[5]}, [r2]!
134         vld1.8  {d0[6]}, [r2]!
135         vld1.8  {d0[7]}, [r2]!
136 16:     tst     r0, #2
137         beq     17f
138         vld1.8  {d0[2]}, [r2]!
139         vld1.8  {d0[3]}, [r2]!
140 17:     tst     r0, #1
141         beq     18f
142         vld1.8  {d0[1]}, [r2]!
143 18:     tst     r0, #16
144         beq     19f
145         vst1.8  {d2-d3}, [r1, :128]!
146 19:     tst     r0, #8
147         beq     20f
148         vst1.8  {d1}, [r1, :64]!
149 20:     tst     r0, #4
150         beq     21f
151         vst1.8  {d0[4]}, [r1]!
152         vst1.8  {d0[5]}, [r1]!
153         vst1.8  {d0[6]}, [r1]!
154         vst1.8  {d0[7]}, [r1]!
155 21:     tst     r0, #2
156         beq     22f
157         vst1.8  {d0[2]}, [r1]!
158         vst1.8  {d0[3]}, [r1]!
159 22:     tst     r0, #1
160         beq     13f
161         vst1.8  {d0[1]}, [r1]!
162 13:     bx      lr
163 0:      tst     r0, #31
164         beq     23f
165         tst     r0, #16
166         beq     24f
167         vld1.8  {d2-d3}, [r2]!
168 24:     tst     r0, #8
169         beq     25f
170         vld1.8  {d1}, [r2]!
171 25:     tst     r0, #4
172         beq     26f
173         vld1.8  {d0[4]}, [r2]!
174         vld1.8  {d0[5]}, [r2]!
175         vld1.8  {d0[6]}, [r2]!
176         vld1.8  {d0[7]}, [r2]!
177 26:     tst     r0, #2
178         beq     27f
179         vld1.8  {d0[2]}, [r2]!
180         vld1.8  {d0[3]}, [r2]!
181 27:     tst     r0, #1
182         beq     28f
183         vld1.8  {d0[1]}, [r2]!
184 28:     tst     r0, #16
185         beq     29f
186         vst1.8  {d2-d3}, [r1]!
187 29:     tst     r0, #8
188         beq     30f
189         vst1.8  {d1}, [r1]!
190 30:     tst     r0, #4
191         beq     31f
192         vst1.8  {d0[4]}, [r1]!
193         vst1.8  {d0[5]}, [r1]!
194         vst1.8  {d0[6]}, [r1]!
195         vst1.8  {d0[7]}, [r1]!
196 31:     tst     r0, #2
197         beq     32f
198         vst1.8  {d0[2]}, [r1]!
199         vst1.8  {d0[3]}, [r1]!
200 32:     tst     r0, #1
201         beq     23f
202         vst1.8  {d0[1]}, [r1]!
203 23:     bx      lr
204 .endfunc
205
206 /******************************************************************************/
207
208 /*
209  * Helper macro for memcpy function, it can copy data from source (r1) to 
210  * destination (r0) buffers fixing alignment in the process. Destination
211  * buffer should be aligned already (4 bytes alignment is required.
212  * Size of the block to copy is in r2 register
213  */
214 .macro  UNALIGNED_MEMCPY shift
215     sub     r1, #(\shift)
216     ldr     ip, [r1], #4
217
218     tst     r0, #4
219     movne   r3, ip, lsr #(\shift * 8)
220     ldrne   ip, [r1], #4
221     subne   r2, r2, #4
222     orrne   r3, r3, ip, asl #(32 - \shift * 8)
223     strne   r3, [r0], #4
224
225     tst     r0, #8
226     movne   r3, ip, lsr #(\shift * 8)
227     ldmiane r1!, {r4, ip}
228     subne   r2, r2, #8
229     orrne   r3, r3, r4, asl #(32 - \shift * 8)
230     movne   r4, r4, lsr #(\shift * 8)
231     orrne   r4, r4, ip, asl #(32 - \shift * 8)
232     stmiane r0!, {r3-r4}
233     cmp     r2, #32
234     blt     3f
235     pld     [r1, #48]
236     stmfd   sp!, {r7, r8, r9, r10, r11}
237     add     r3, r1, #128
238     bic     r3, r3, #31
239     sub     r9, r3, r1
240 1:
241     pld     [r1, r9]
242     subs    r2, r2, #32
243     movge   r3, ip, lsr #(\shift * 8)
244     ldmiage r1!, {r4-r6, r7, r8, r10, r11, ip}
245     orrge   r3, r3, r4, asl #(32 - \shift * 8)
246     movge   r4, r4, lsr #(\shift * 8)
247     orrge   r4, r4, r5, asl #(32 - \shift * 8)
248     movge   r5, r5, lsr #(\shift * 8)
249     orrge   r5, r5, r6, asl #(32 - \shift * 8)
250     movge   r6, r6, lsr #(\shift * 8)
251     orrge   r6, r6, r7, asl #(32 - \shift * 8)
252     stmiage r0!, {r3-r6}
253     movge   r7, r7, lsr #(\shift * 8)
254     orrge   r7, r7, r8, asl #(32 - \shift * 8)
255     movge   r8, r8, lsr #(\shift * 8)
256     orrge   r8, r8, r10, asl #(32 - \shift * 8)
257     movge   r10, r10, lsr #(\shift * 8)
258     orrge   r10, r10, r11, asl #(32 - \shift * 8)
259     movge   r11, r11, lsr #(\shift * 8)
260     orrge   r11, r11, ip, asl #(32 - \shift * 8)
261     stmiage r0!, {r7, r8, r10, r11}
262     bgt     1b
263 2:
264     ldmfd   sp!, {r7, r8, r9, r10, r11}
265 3:  /* copy remaining data */
266     tst     r2, #16
267     movne   r3, ip, lsr #(\shift * 8)
268     ldmiane r1!, {r4-r6, ip}
269     orrne   r3, r3, r4, asl #(32 - \shift * 8)
270     movne   r4, r4, lsr #(\shift * 8)
271     orrne   r4, r4, r5, asl #(32 - \shift * 8)
272     movge   r5, r5, lsr #(\shift * 8)
273     orrge   r5, r5, r6, asl #(32 - \shift * 8)
274     movge   r6, r6, lsr #(\shift * 8)
275     orrge   r6, r6, ip, asl #(32 - \shift * 8)
276     stmiane r0!, {r3-r6}
277
278     tst     r2, #8
279     movne   r3, ip, lsr #(\shift * 8)
280     ldmiane r1!, {r4, ip}
281     orrne   r3, r3, r4, asl #(32 - \shift * 8)
282     movne   r4, r4, lsr #(\shift * 8)
283     orrne   r4, r4, ip, asl #(32 - \shift * 8)
284     stmiane r0!, {r3-r4}
285
286     tst     r2, #4
287     movne   r3, ip, lsr #(\shift * 8)
288     ldrne   ip, [r1], #4
289     sub     r1, r1, #(4 - \shift)
290     orrne   r3, r3, ip, asl #(32 - \shift * 8)
291     strne   r3, [r0], #4
292
293     tst     r2, #2
294     ldrbne  r3, [r1], #1
295     ldrbne  r4, [r1], #1
296     ldr     r5, [sp], #4
297     strbne  r3, [r0], #1
298     strbne  r4, [r0], #1
299
300     tst     r2, #1
301     ldrbne  r3, [r1], #1
302     ldr     r6, [sp], #4
303     strbne  r3, [r0], #1
304
305     ldmfd   sp!, {r0, r4}
306
307     bx      lr
308 .endm
309
310 /*
311  * Memcpy function with Raspberry Pi specific aligned prefetch, based on
312  * https://garage.maemo.org/plugins/scmsvn/viewcvs.php/mplayer/trunk/fastmem-arm9/fastmem-arm9.S
313  */
314 asm_function memcpy_armv5te
315     cmp     r2, #20
316     blt     9f
317     /* copy data until destination address is 4 bytes aligned */
318     tst     r0, #1
319     ldrbne  r3, [r1], #1
320     stmfd   sp!, {r0, r4}
321     subne   r2, r2, #1
322     strbne  r3, [r0], #1
323     tst     r0, #2
324     ldrbne  r3, [r1], #1
325     ldrbne  r4, [r1], #1
326     stmfd   sp!, {r5, r6}
327     subne   r2, r2, #2
328     orrne   r3, r3, r4, asl #8
329     strhne  r3, [r0], #2
330     /* destination address is 4 bytes aligned */
331     /* now we should handle 4 cases of source address alignment */
332     tst     r1, #1
333     bne     6f
334     tst     r1, #2
335     bne     7f
336
337     /* both source and destination are 4 bytes aligned */
338     stmfd   sp!, {r7, r8, r9, r10, r11}
339     tst     r0, #4
340     ldrne   r4, [r1], #4
341     subne   r2, r2, #4
342     strne   r4, [r0], #4
343     tst     r0, #8
344     ldmiane r1!, {r3-r4}
345     add     r9, r1, #96
346     subne   r2, r2, #8
347     bic     r9, r9, #31
348     stmiane r0!, {r3-r4}
349     sub     r9, r9, r1
350 1:
351     subs    r2, r2, #32
352     ldmiage r1!, {r3-r6, r7, r8, r10, r11}
353     pld     [r1, r9]
354     stmiage r0!, {r3-r6}
355     stmiage r0!, {r7, r8, r10, r11}
356     bgt     1b
357 2:
358     ldmfd   sp!, {r7, r8, r9, r10, r11}
359     tst     r2, #16
360     ldmiane r1!, {r3-r6}
361     stmiane r0!, {r3-r6}
362     tst     r2, #8
363     ldmiane r1!, {r3-r4}
364     stmiane r0!, {r3-r4}
365     tst     r2, #4
366     ldrne   r3, [r1], #4
367     mov     ip, r0
368     strne   r3, [ip], #4
369     tst     r2, #2
370     ldrhne  r3, [r1], #2
371     ldmfd   sp!, {r5, r6}
372     strhne  r3, [ip], #2
373     tst     r2, #1
374     ldrbne  r3, [r1], #1
375     ldmfd   sp!, {r0, r4}
376     strbne  r3, [ip], #1
377
378     bx      lr
379
380 6:
381     tst    r1, #2
382     bne    8f
383     UNALIGNED_MEMCPY 1
384 7:
385     UNALIGNED_MEMCPY 2
386 8:
387     UNALIGNED_MEMCPY 3
388 9:
389     stmfd  sp!, {r0, r4}
390 1:  subs   r2, r2, #3
391     ldrbge ip, [r0]
392     ldrbge r3, [r1], #1
393     ldrbge r4, [r1], #1
394     ldrbge ip, [r1], #1
395     strbge r3, [r0], #1
396     strbge r4, [r0], #1
397     strbge ip, [r0], #1
398     bge    1b
399     adds   r2, r2, #2
400     ldrbge r3, [r1], #1
401     mov    ip, r0
402     ldr    r0, [sp], #4
403     strbge r3, [ip], #1
404     ldrbgt r3, [r1], #1
405     ldr    r4, [sp], #4
406     strbgt r3, [ip], #1
407     bx     lr
408 .endfunc
409
410 /******************************************************************************/
411
412 /*
413  * aligned_fetch_fbmem_to_scratch_neon(int numbytes, void *scratch, void *fbmem)
414  *
415  * Both 'scratch' and 'fbmem' pointers must be 32 bytes aligned.
416  * The value in 'numbytes' is also rounded up to a multiple of 32 bytes.
417
418  * The only purpose of this code is to attempt minimizing penalty incured
419  * by doing uncached reads from memory (for example framebuffer). We are
420  * trying to do the largest possible perfectly aligned reads to fetch
421  * data into a temporary scratch buffer in L1 cache.
422  */
423
424 asm_function aligned_fetch_fbmem_to_scratch_neon
425     SIZE        .req r0
426     DST         .req r1
427     SRC         .req r2
428
429     subs        SIZE, #128
430     blt         1f
431 0:
432     /* aligned load from the source (framebuffer) */
433     vld1.64     {q0, q1}, [SRC, :256]!
434     vld1.64     {q2, q3}, [SRC, :256]!
435     vld1.64     {q8, q9}, [SRC, :256]!
436     vld1.64     {q10, q11}, [SRC, :256]!
437     /* fetch destination (scratch buffer) into L1 cache */
438     ldr         r3, [DST]
439     ldr         ip, [DST, #64]
440     /* aligned store to the scratch buffer */
441     vst1.64     {q0, q1}, [DST, :256]!
442     vst1.64     {q2, q3}, [DST, :256]!
443     vst1.64     {q8, q9}, [DST, :256]!
444     vst1.64     {q10, q11}, [DST, :256]!
445     subs        SIZE, SIZE, #128
446     bge         0b
447 1:
448     tst         SIZE, #64
449     beq         1f
450     vld1.64     {q0, q1}, [SRC, :256]!
451     vld1.64     {q2, q3}, [SRC, :256]!
452     ldr         r3, [DST]
453     vst1.64     {q0, q1}, [DST, :256]!
454     vst1.64     {q2, q3}, [DST, :256]!
455 1:
456     tst         SIZE, #32
457     beq         1f
458     vld1.64     {q0, q1}, [SRC, :256]!
459     vst1.64     {q0, q1}, [DST, :256]!
460 1:
461     tst         SIZE, #31
462     beq         1f
463     vld1.64     {q0, q1}, [SRC, :256]!
464     vst1.64     {q0, q1}, [DST, :256]!
465 1:
466     bx          lr
467
468     .unreq      SIZE
469     .unreq      DST
470     .unreq      SRC
471 .endfunc
472
473 asm_function aligned_fetch_fbmem_to_scratch_vfp
474     SIZE        .req r0
475     DST         .req r1
476     SRC         .req r2
477
478     vpush       {d8-d15}
479     subs        SIZE, #128
480     blt         1f
481 0:
482     /* aligned load from the source (framebuffer) */
483     vldm        SRC!, {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15}
484     /* aligned store to the scratch buffer */
485     vstm        DST!, {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15}
486     subs        SIZE, SIZE, #128
487     bge         0b
488 1:
489     tst         SIZE, #64
490     beq         1f
491     vldm        SRC!, {d0, d1, d2, d3, d4, d5, d6, d7}
492     vstm        DST!, {d0, d1, d2, d3, d4, d5, d6, d7}
493 1:
494     tst         SIZE, #32
495     beq         1f
496     vldm        SRC!, {d0, d1, d2, d3}
497     vstm        DST!, {d0, d1, d2, d3}
498 1:
499     tst         SIZE, #31
500     beq         1f
501     vldm        SRC!, {d0, d1, d2, d3}
502     vstm        DST!, {d0, d1, d2, d3}
503 1:
504     vpop        {d8-d15}
505     bx          lr
506
507     .unreq      SIZE
508     .unreq      DST
509     .unreq      SRC
510 .endfunc
511
512 asm_function aligned_fetch_fbmem_to_scratch_arm
513     SIZE        .req r0
514     DST         .req r1
515     SRC         .req r2
516
517     push        {r4-r11, lr}
518     subs        SIZE, #128
519     blt         1f
520 0:
521     ldmia       SRC!, {r4-r11}
522     stmia       DST!, {r4-r11}
523     ldmia       SRC!, {r4-r11}
524     stmia       DST!, {r4-r11}
525     ldmia       SRC!, {r4-r11}
526     stmia       DST!, {r4-r11}
527     ldmia       SRC!, {r4-r11}
528     stmia       DST!, {r4-r11}
529     subs        SIZE, SIZE, #128
530     bge         0b
531 1:
532     tst         SIZE, #64
533     beq         1f
534     ldmia       SRC!, {r4-r11}
535     stmia       DST!, {r4-r11}
536     ldmia       SRC!, {r4-r11}
537     stmia       DST!, {r4-r11}
538 1:
539     tst         SIZE, #32
540     beq         1f
541     ldmia       SRC!, {r4-r11}
542     stmia       DST!, {r4-r11}
543 1:
544     tst         SIZE, #31
545     beq         1f
546     ldmia       SRC!, {r4-r11}
547     stmia       DST!, {r4-r11}
548 1:
549     pop         {r4-r11, pc}
550
551     .unreq      SIZE
552     .unreq      DST
553     .unreq      SRC
554 .endfunc
555
556 #endif