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 27FPU .fpu vfp 28ELF .eabi_attribute 10, 0 @ suppress Tag_FP_arch 29#endif 30 31const 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 40endconst 41 42const error_message_fpscr 43 .asciz "failed to preserve register FPSCR, changed bits: %x" 44error_message_gpr: 45 .asciz "failed to preserve register r%d" 46error_message_vfp: 47 .asciz "failed to preserve register d%d" 48error_message_stack: 49 .asciz "failed to preserve stack" 50endconst 51 52@ max number of args used by any asm function. 53#define MAX_ARGS 15 54 55#define ARG_STACK 4*(MAX_ARGS - 4) 56 57@ Align the used stack space to 8 to preserve the stack alignment. 58@ +8 for stack canary reference. 59#define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed + 8) 60 61.macro clobbercheck variant 62.equ pushed, 4*9 63function checkasm_checked_call_\variant, export=1 64 push {r4-r11, lr} 65.ifc \variant, vfp 66 vpush {d8-d15} 67 fmrx r4, FPSCR 68 push {r4} 69.equ pushed, pushed + 16*4 + 4 70.endif 71 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.equ pos, 0 80.rept MAX_ARGS-4 81 ldr r12, [sp, #ARG_STACK_A + pushed + 8 + pos] 82 str r12, [sp, #pos] 83.equ pos, pos + 4 84.endr 85 86 @ For stack overflows, the callee is free to overwrite the parameters 87 @ that were passed on the stack (if any), so we can only check after 88 @ that point. First figure out how many parameters the function 89 @ really took on the stack: 90 ldr r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)] 91 @ Load the first non-parameter value from the stack, that should be 92 @ left untouched by the function. Store a copy of it inverted, so that 93 @ e.g. overwriting everything with zero would be noticed. 94 ldr r12, [sp, r12, lsl #2] 95 mvn r12, r12 96 str r12, [sp, #ARG_STACK_A - 4] 97 98 mov r12, r0 99 mov r0, r2 100 mov r1, r3 101 ldrd r2, r3, [sp, #ARG_STACK_A + pushed] 102 @ Call the target function 103 blx r12 104 105 @ Load the number of stack parameters, stack canary and its reference 106 ldr r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)] 107 ldr r2, [sp, r12, lsl #2] 108 ldr r3, [sp, #ARG_STACK_A - 4] 109 110 add sp, sp, #ARG_STACK_A 111 push {r0, r1} 112 113 mvn r3, r3 114 cmp r2, r3 115 bne 5f 116 117 movrel r12, register_init 118.ifc \variant, vfp 119.macro check_reg_vfp, dreg, offset 120 ldrd r2, r3, [r12, #8 * (\offset)] 121 vmov r0, lr, \dreg 122 eor r2, r2, r0 123 eor r3, r3, lr 124 orrs r2, r2, r3 125 bne 4f 126.endm 127 128.irp n, 8, 9, 10, 11, 12, 13, 14, 15 129 @ keep track of the checked double/SIMD register 130 mov r1, #\n 131 check_reg_vfp d\n, \n-8 132.endr 133.purgem check_reg_vfp 134 135 fmrx r1, FPSCR 136 ldr r3, [sp, #8] 137 eor r1, r1, r3 138 @ Ignore changes in bits 0-4 and 7 139 bic r1, r1, #0x9f 140 @ Ignore changes in the topmost 5 bits 141 bics r1, r1, #0xf8000000 142 bne 3f 143.endif 144 145 @ keep track of the checked GPR 146 mov r1, #4 147.macro check_reg reg1, reg2= 148 ldrd r2, r3, [r12], #8 149 eors r2, r2, \reg1 150 bne 2f 151 add r1, r1, #1 152.ifnb \reg2 153 eors r3, r3, \reg2 154 bne 2f 155.endif 156 add r1, r1, #1 157.endm 158 check_reg r4, r5 159 check_reg r6, r7 160@ r9 is a volatile register in the ios ABI 161#ifdef __APPLE__ 162 check_reg r8 163#else 164 check_reg r8, r9 165#endif 166 check_reg r10, r11 167.purgem check_reg 168 169 b 0f 1705: 171 movrel r0, error_message_stack 172 b 1f 1734: 174 movrel r0, error_message_vfp 175 b 1f 1763: 177 movrel r0, error_message_fpscr 178 b 1f 1792: 180 movrel r0, error_message_gpr 1811: 182 bl X(checkasm_fail_func) 1830: 184 pop {r0, r1} 185.ifc \variant, vfp 186 pop {r2} 187 fmxr FPSCR, r2 188 vpop {d8-d15} 189.endif 190 pop {r4-r11, pc} 191endfunc 192.endm 193 194#if HAVE_VFP || HAVE_NEON 195clobbercheck vfp 196#endif 197clobbercheck novfp 198