checkasm_32.S 5.3 KB
Newer Older
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
/******************************************************************************
 * 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
35 36 37 38 39 40 41 42
        .quad 0x21f86d66c8ca00ce
        .quad 0x75b6ba21077c48ad
        .quad 0xed56bb2dcb3c7736
        .quad 0x8bda43d3fd1a7e06
        .quad 0xb64a9c9e5d318408
        .quad 0xdf9a54b303f1d3a3
        .quad 0x4a75479abd64e097
        .quad 0x249214109d5d1c88
43 44 45
endconst

const error_message_fpscr
46
        .asciz "failed to preserve register FPSCR, changed bits: %x"
47
error_message_gpr:
48
        .asciz "failed to preserve register r%d"
49
error_message_vfp:
50
        .asciz "failed to preserve register d%d"
51 52 53 54 55 56 57 58 59 60 61 62 63
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
#define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed)

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

72
        movrel          r12, register_init
73
.ifc \variant, vfp
74
        vldm            r12, {d8-d15}
75
.endif
76
        ldm             r12, {r4-r11}
77

78
        sub             sp,  sp,  #ARG_STACK_A
79 80
.equ pos, 0
.rept MAX_ARGS-4
81 82
        ldr             r12, [sp, #ARG_STACK_A + pushed + 8 + pos]
        str             r12, [sp, #pos]
83 84 85
.equ pos, pos + 4
.endr

86 87 88 89 90 91
        mov             r12, r0
        mov             r0,  r2
        mov             r1,  r3
        ldrd            r2,  r3,  [sp, #ARG_STACK_A + pushed]
        blx             r12
        add             sp,  sp,  #ARG_STACK_A
92

93 94
        push            {r0, r1}
        movrel          r12, register_init
95 96
.ifc \variant, vfp
.macro check_reg_vfp, dreg, offset
97 98 99 100 101 102
        ldrd            r2,  r3,  [r12, #8 * (\offset)]
        vmov            r0,  lr,  \dreg
        eor             r2,  r2,  r0
        eor             r3,  r3,  lr
        orrs            r2,  r2,  r3
        bne             4f
103 104 105
.endm

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

112 113 114 115 116 117 118 119
        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
120 121
.endif

122 123
        @ keep track of the checked GPR
        mov             r1,  #4
124
.macro check_reg reg1, reg2=
125 126 127 128
        ldrd            r2,  r3,  [r12], #8
        eors            r2,  r2,  \reg1
        bne             2f
        add             r1,  r1,  #1
129
.ifnb \reg2
130 131
        eors            r3,  r3,  \reg2
        bne             2f
132
.endif
133
        add             r1,  r1,  #1
134
.endm
135 136
        check_reg       r4,  r5
        check_reg       r6,  r7
137 138
@ r9 is a volatile register in the ios ABI
#ifdef __APPLE__
139
        check_reg       r8
140
#else
141
        check_reg       r8,  r9
142
#endif
143
        check_reg       r10, r11
144 145
.purgem check_reg

146
        b               0f
147
4:
148 149
        movrel          r0, error_message_vfp
        b               1f
150
3:
151 152
        movrel          r0, error_message_fpscr
        b               1f
153
2:
154
        movrel          r0, error_message_gpr
155 156
1:
#ifdef PREFIX
157
        blx             _checkasm_fail_func
158
#else
159
        blx             checkasm_fail_func
160 161
#endif
0:
162
        pop             {r0, r1}
163
.ifc \variant, vfp
164 165 166
        pop             {r2}
        fmxr            FPSCR, r2
        vpop            {d8-d15}
167
.endif
168
        pop             {r4-r11, pc}
169 170 171 172
endfunc
.endm

clobbercheck vfp