summaryrefslogtreecommitdiffstats
path: root/third_party/dav1d/tests/checkasm/arm/checkasm_32.S
blob: a186ef8fc25ebedafd8a5326b481fedd37c16e15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/******************************************************************************
 * Copyright © 2018, VideoLAN and dav1d authors
 * Copyright © 2015 Martin Storsjo
 * Copyright © 2015 Janne Grunau
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *****************************************************************************/

#define PRIVATE_PREFIX checkasm_

#include "src/arm/asm.S"
#include "src/arm/32/util.S"

const register_init, align=3
        .quad 0x21f86d66c8ca00ce
        .quad 0x75b6ba21077c48ad
        .quad 0xed56bb2dcb3c7736
        .quad 0x8bda43d3fd1a7e06
        .quad 0xb64a9c9e5d318408
        .quad 0xdf9a54b303f1d3a3
        .quad 0x4a75479abd64e097
        .quad 0x249214109d5d1c88
endconst

const error_message_fpscr
        .asciz "failed to preserve register FPSCR, changed bits: %x"
error_message_gpr:
        .asciz "failed to preserve register r%d"
error_message_vfp:
        .asciz "failed to preserve register d%d"
error_message_stack:
        .asciz "failed to preserve stack"
endconst

@ max number of args used by any asm function.
#define MAX_ARGS 15

#define ARG_STACK 4*(MAX_ARGS - 4)

@ Align the used stack space to 8 to preserve the stack alignment.
@ +8 for stack canary reference.
#define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed + 8)

.macro clobbercheck variant
.equ pushed, 4*9
function checked_call_\variant, export=1
        push            {r4-r11, lr}
.ifc \variant, vfp
        vpush           {d8-d15}
        fmrx            r4,  FPSCR
        push            {r4}
.equ pushed, pushed + 16*4 + 4
.endif

        movrel          r12, register_init
.ifc \variant, vfp
        vldm            r12, {d8-d15}
.endif
        ldm             r12, {r4-r11}

        sub             sp,  sp,  #ARG_STACK_A
.equ pos, 0
.rept MAX_ARGS-4
        ldr             r12, [sp, #ARG_STACK_A + pushed + 8 + pos]
        str             r12, [sp, #pos]
.equ pos, pos + 4
.endr

        @ For stack overflows, the callee is free to overwrite the parameters
        @ that were passed on the stack (if any), so we can only check after
        @ that point. First figure out how many parameters the function
        @ really took on the stack:
        ldr             r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)]
        @ Load the first non-parameter value from the stack, that should be
        @ left untouched by the function. Store a copy of it inverted, so that
        @ e.g. overwriting everything with zero would be noticed.
        ldr             r12, [sp, r12, lsl #2]
        mvn             r12, r12
        str             r12, [sp, #ARG_STACK_A - 4]

        mov             r12, r0
        mov             r0,  r2
        mov             r1,  r3
        ldrd            r2,  r3,  [sp, #ARG_STACK_A + pushed]
        @ Call the target function
        blx             r12

        @ Load the number of stack parameters, stack canary and its reference
        ldr             r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)]
        ldr             r2,  [sp, r12, lsl #2]
        ldr             r3,  [sp, #ARG_STACK_A - 4]

        add             sp,  sp,  #ARG_STACK_A
        push            {r0, r1}

        mvn             r3,  r3
        cmp             r2,  r3
        bne             5f

        movrel          r12, register_init
.ifc \variant, vfp
.macro check_reg_vfp, dreg, offset
        ldrd            r2,  r3,  [r12, #8 * (\offset)]
        vmov            r0,  lr,  \dreg
        eor             r2,  r2,  r0
        eor             r3,  r3,  lr
        orrs            r2,  r2,  r3
        bne             4f
.endm

.irp n, 8, 9, 10, 11, 12, 13, 14, 15
        @ keep track of the checked double/SIMD register
        mov             r1,  #\n
        check_reg_vfp   d\n, \n-8
.endr
.purgem check_reg_vfp

        fmrx            r1,  FPSCR
        ldr             r3,  [sp, #8]
        eor             r1,  r1,  r3
        @ Ignore changes in bits 0-4 and 7
        bic             r1,  r1,  #0x9f
        @ Ignore changes in the topmost 5 bits
        bics            r1,  r1,  #0xf8000000
        bne             3f
.endif

        @ keep track of the checked GPR
        mov             r1,  #4
.macro check_reg reg1, reg2=
        ldrd            r2,  r3,  [r12], #8
        eors            r2,  r2,  \reg1
        bne             2f
        add             r1,  r1,  #1
.ifnb \reg2
        eors            r3,  r3,  \reg2
        bne             2f
.endif
        add             r1,  r1,  #1
.endm
        check_reg       r4,  r5
        check_reg       r6,  r7
@ r9 is a volatile register in the ios ABI
#ifdef __APPLE__
        check_reg       r8
#else
        check_reg       r8,  r9
#endif
        check_reg       r10, r11
.purgem check_reg

        b               0f
5:
        movrel          r0, error_message_stack
        b               1f
4:
        movrel          r0, error_message_vfp
        b               1f
3:
        movrel          r0, error_message_fpscr
        b               1f
2:
        movrel          r0, error_message_gpr
1:
#ifdef PREFIX
        bl              _checkasm_fail_func
#else
        bl              checkasm_fail_func
#endif
0:
        pop             {r0, r1}
.ifc \variant, vfp
        pop             {r2}
        fmxr            FPSCR, r2
        vpop            {d8-d15}
.endif
        pop             {r4-r11, pc}
endfunc
.endm

clobbercheck vfp