Merge commit 'a05cc56124b4f1237f6355784de821e3290ddb44'
[ffmpeg.git] / tests / checkasm / arm / checkasm.S
1 /****************************************************************************
2  * Assembly testing and benchmarking tool
3  * Copyright (c) 2015 Martin Storsjo
4  * Copyright (c) 2015 Janne Grunau
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 #include "libavutil/arm/asm.S"
24
25 /* override fpu so that NEON instructions are rejected */
26 #if HAVE_VFP
27 FPU     .fpu            vfp
28 ELF     .eabi_attribute 10, 0           @ suppress Tag_FP_arch
29 #endif
30
31 const register_init, align=3
32     .quad 0x21f86d66c8ca00ce
33     .quad 0x75b6ba21077c48ad
34     .quad 0xed56bb2dcb3c7736
35     .quad 0x8bda43d3fd1a7e06
36     .quad 0xb64a9c9e5d318408
37     .quad 0xdf9a54b303f1d3a3
38     .quad 0x4a75479abd64e097
39     .quad 0x249214109d5d1c88
40 endconst
41
42 const error_message_fpscr
43     .asciz "failed to preserve register FPSCR, changed bits: %x"
44 error_message_gpr:
45     .asciz "failed to preserve register r%d"
46 error_message_vfp:
47     .asciz "failed to preserve register d%d"
48 endconst
49
50 @ max number of args used by any asm function.
51 #define MAX_ARGS 15
52
53 #define ARG_STACK 4*(MAX_ARGS - 4)
54
55 @ align the used stack space to 8 to preserve the stack alignment
56 #define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed)
57
58 .macro clobbercheck variant
59 .equ pushed, 4*9
60 function checkasm_checked_call_\variant, export=1
61     push        {r4-r11, lr}
62 .ifc \variant, vfp
63     vpush       {d8-d15}
64     fmrx        r4,  FPSCR
65     push        {r4}
66 .equ pushed, pushed + 16*4 + 4
67 .endif
68
69     movrel      r12, register_init
70 .ifc \variant, vfp
71     vldm        r12, {d8-d15}
72 .endif
73     ldm         r12, {r4-r11}
74
75     sub         sp,  sp,  #ARG_STACK_A
76 .equ pos, 0
77 .rept MAX_ARGS-4
78     ldr         r12, [sp, #ARG_STACK_A + pushed + 8 + pos]
79     str         r12, [sp, #pos]
80 .equ pos, pos + 4
81 .endr
82
83     mov         r12, r0
84     mov         r0,  r2
85     mov         r1,  r3
86     ldrd        r2,  r3,  [sp, #ARG_STACK_A + pushed]
87     blx         r12
88     add         sp,  sp,  #ARG_STACK_A
89
90     push        {r0, r1}
91     movrel      r12, register_init
92 .ifc \variant, vfp
93 .macro check_reg_vfp, dreg, offset
94     ldrd        r2,  r3,  [r12, #8 * (\offset)]
95     vmov        r0,  lr,  \dreg
96     eor         r2,  r2,  r0
97     eor         r3,  r3,  lr
98     orrs        r2,  r2,  r3
99     bne         4f
100 .endm
101
102 .irp n, 8, 9, 10, 11, 12, 13, 14, 15
103     @ keep track of the checked double/SIMD register
104     mov         r1,  #\n
105     check_reg_vfp d\n, \n-8
106 .endr
107 .purgem check_reg_vfp
108
109     fmrx        r1,  FPSCR
110     ldr         r3,  [sp, #8]
111     eor         r1,  r1,  r3
112     @ Ignore changes in bits 0-4 and 7
113     bic         r1,  r1,  #0x9f
114     @ Ignore changes in the topmost 5 bits
115     bics        r1,  r1,  #0xf8000000
116     bne         3f
117 .endif
118
119     @ keep track of the checked GPR
120     mov         r1,  #4
121 .macro check_reg reg1, reg2=
122     ldrd        r2,  r3,  [r12], #8
123     eors        r2,  r2,  \reg1
124     bne         2f
125     add         r1,  r1,  #1
126 .ifnb \reg2
127     eors        r3,  r3,  \reg2
128     bne         2f
129 .endif
130     add         r1,  r1,  #1
131 .endm
132     check_reg   r4,  r5
133     check_reg   r6,  r7
134 @ r9 is a volatile register in the ios ABI
135 #ifdef __APPLE__
136     check_reg   r8
137 #else
138     check_reg   r8,  r9
139 #endif
140     check_reg   r10, r11
141 .purgem check_reg
142
143     b           0f
144 4:
145     movrel      r0, error_message_vfp
146     b           1f
147 3:
148     movrel      r0, error_message_fpscr
149     b           1f
150 2:
151     movrel      r0, error_message_gpr
152 1:
153     blx         X(checkasm_fail_func)
154 0:
155     pop         {r0, r1}
156 .ifc \variant, vfp
157     pop         {r2}
158     fmxr        FPSCR, r2
159     vpop        {d8-d15}
160 .endif
161     pop         {r4-r11, pc}
162 endfunc
163 .endm
164
165 #if HAVE_VFP || HAVE_NEON
166 clobbercheck vfp
167 #endif
168 clobbercheck novfp