1cabdff1aSopenharmony_ci/**************************************************************************** 2cabdff1aSopenharmony_ci * Assembly testing and benchmarking tool 3cabdff1aSopenharmony_ci * Copyright (c) 2015 Martin Storsjo 4cabdff1aSopenharmony_ci * Copyright (c) 2015 Janne Grunau 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or modify 9cabdff1aSopenharmony_ci * it under the terms of the GNU General Public License as published by 10cabdff1aSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 11cabdff1aSopenharmony_ci * (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16cabdff1aSopenharmony_ci * GNU General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU General Public License 19cabdff1aSopenharmony_ci * along with this program; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. 21cabdff1aSopenharmony_ci *****************************************************************************/ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "libavutil/arm/asm.S" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci/* override fpu so that NEON instructions are rejected */ 26cabdff1aSopenharmony_ci#if HAVE_VFP 27cabdff1aSopenharmony_ciFPU .fpu vfp 28cabdff1aSopenharmony_ciELF .eabi_attribute 10, 0 @ suppress Tag_FP_arch 29cabdff1aSopenharmony_ci#endif 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ciconst register_init, align=3 32cabdff1aSopenharmony_ci .quad 0x21f86d66c8ca00ce 33cabdff1aSopenharmony_ci .quad 0x75b6ba21077c48ad 34cabdff1aSopenharmony_ci .quad 0xed56bb2dcb3c7736 35cabdff1aSopenharmony_ci .quad 0x8bda43d3fd1a7e06 36cabdff1aSopenharmony_ci .quad 0xb64a9c9e5d318408 37cabdff1aSopenharmony_ci .quad 0xdf9a54b303f1d3a3 38cabdff1aSopenharmony_ci .quad 0x4a75479abd64e097 39cabdff1aSopenharmony_ci .quad 0x249214109d5d1c88 40cabdff1aSopenharmony_ciendconst 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ciconst error_message_fpscr 43cabdff1aSopenharmony_ci .asciz "failed to preserve register FPSCR, changed bits: %x" 44cabdff1aSopenharmony_cierror_message_gpr: 45cabdff1aSopenharmony_ci .asciz "failed to preserve register r%d" 46cabdff1aSopenharmony_cierror_message_vfp: 47cabdff1aSopenharmony_ci .asciz "failed to preserve register d%d" 48cabdff1aSopenharmony_cierror_message_stack: 49cabdff1aSopenharmony_ci .asciz "failed to preserve stack" 50cabdff1aSopenharmony_ciendconst 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci@ max number of args used by any asm function. 53cabdff1aSopenharmony_ci#define MAX_ARGS 15 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci#define ARG_STACK 4*(MAX_ARGS - 4) 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci@ Align the used stack space to 8 to preserve the stack alignment. 58cabdff1aSopenharmony_ci@ +8 for stack canary reference. 59cabdff1aSopenharmony_ci#define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed + 8) 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci.macro clobbercheck variant 62cabdff1aSopenharmony_ci.equ pushed, 4*9 63cabdff1aSopenharmony_cifunction checkasm_checked_call_\variant, export=1 64cabdff1aSopenharmony_ci push {r4-r11, lr} 65cabdff1aSopenharmony_ci.ifc \variant, vfp 66cabdff1aSopenharmony_ci vpush {d8-d15} 67cabdff1aSopenharmony_ci fmrx r4, FPSCR 68cabdff1aSopenharmony_ci push {r4} 69cabdff1aSopenharmony_ci.equ pushed, pushed + 16*4 + 4 70cabdff1aSopenharmony_ci.endif 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci movrel r12, register_init 73cabdff1aSopenharmony_ci.ifc \variant, vfp 74cabdff1aSopenharmony_ci vldm r12, {d8-d15} 75cabdff1aSopenharmony_ci.endif 76cabdff1aSopenharmony_ci ldm r12, {r4-r11} 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci sub sp, sp, #ARG_STACK_A 79cabdff1aSopenharmony_ci.equ pos, 0 80cabdff1aSopenharmony_ci.rept MAX_ARGS-4 81cabdff1aSopenharmony_ci ldr r12, [sp, #ARG_STACK_A + pushed + 8 + pos] 82cabdff1aSopenharmony_ci str r12, [sp, #pos] 83cabdff1aSopenharmony_ci.equ pos, pos + 4 84cabdff1aSopenharmony_ci.endr 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci @ For stack overflows, the callee is free to overwrite the parameters 87cabdff1aSopenharmony_ci @ that were passed on the stack (if any), so we can only check after 88cabdff1aSopenharmony_ci @ that point. First figure out how many parameters the function 89cabdff1aSopenharmony_ci @ really took on the stack: 90cabdff1aSopenharmony_ci ldr r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)] 91cabdff1aSopenharmony_ci @ Load the first non-parameter value from the stack, that should be 92cabdff1aSopenharmony_ci @ left untouched by the function. Store a copy of it inverted, so that 93cabdff1aSopenharmony_ci @ e.g. overwriting everything with zero would be noticed. 94cabdff1aSopenharmony_ci ldr r12, [sp, r12, lsl #2] 95cabdff1aSopenharmony_ci mvn r12, r12 96cabdff1aSopenharmony_ci str r12, [sp, #ARG_STACK_A - 4] 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci mov r12, r0 99cabdff1aSopenharmony_ci mov r0, r2 100cabdff1aSopenharmony_ci mov r1, r3 101cabdff1aSopenharmony_ci ldrd r2, r3, [sp, #ARG_STACK_A + pushed] 102cabdff1aSopenharmony_ci @ Call the target function 103cabdff1aSopenharmony_ci blx r12 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci @ Load the number of stack parameters, stack canary and its reference 106cabdff1aSopenharmony_ci ldr r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)] 107cabdff1aSopenharmony_ci ldr r2, [sp, r12, lsl #2] 108cabdff1aSopenharmony_ci ldr r3, [sp, #ARG_STACK_A - 4] 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_ci add sp, sp, #ARG_STACK_A 111cabdff1aSopenharmony_ci push {r0, r1} 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci mvn r3, r3 114cabdff1aSopenharmony_ci cmp r2, r3 115cabdff1aSopenharmony_ci bne 5f 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci movrel r12, register_init 118cabdff1aSopenharmony_ci.ifc \variant, vfp 119cabdff1aSopenharmony_ci.macro check_reg_vfp, dreg, offset 120cabdff1aSopenharmony_ci ldrd r2, r3, [r12, #8 * (\offset)] 121cabdff1aSopenharmony_ci vmov r0, lr, \dreg 122cabdff1aSopenharmony_ci eor r2, r2, r0 123cabdff1aSopenharmony_ci eor r3, r3, lr 124cabdff1aSopenharmony_ci orrs r2, r2, r3 125cabdff1aSopenharmony_ci bne 4f 126cabdff1aSopenharmony_ci.endm 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci.irp n, 8, 9, 10, 11, 12, 13, 14, 15 129cabdff1aSopenharmony_ci @ keep track of the checked double/SIMD register 130cabdff1aSopenharmony_ci mov r1, #\n 131cabdff1aSopenharmony_ci check_reg_vfp d\n, \n-8 132cabdff1aSopenharmony_ci.endr 133cabdff1aSopenharmony_ci.purgem check_reg_vfp 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci fmrx r1, FPSCR 136cabdff1aSopenharmony_ci ldr r3, [sp, #8] 137cabdff1aSopenharmony_ci eor r1, r1, r3 138cabdff1aSopenharmony_ci @ Ignore changes in bits 0-4 and 7 139cabdff1aSopenharmony_ci bic r1, r1, #0x9f 140cabdff1aSopenharmony_ci @ Ignore changes in the topmost 5 bits 141cabdff1aSopenharmony_ci bics r1, r1, #0xf8000000 142cabdff1aSopenharmony_ci bne 3f 143cabdff1aSopenharmony_ci.endif 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci @ keep track of the checked GPR 146cabdff1aSopenharmony_ci mov r1, #4 147cabdff1aSopenharmony_ci.macro check_reg reg1, reg2= 148cabdff1aSopenharmony_ci ldrd r2, r3, [r12], #8 149cabdff1aSopenharmony_ci eors r2, r2, \reg1 150cabdff1aSopenharmony_ci bne 2f 151cabdff1aSopenharmony_ci add r1, r1, #1 152cabdff1aSopenharmony_ci.ifnb \reg2 153cabdff1aSopenharmony_ci eors r3, r3, \reg2 154cabdff1aSopenharmony_ci bne 2f 155cabdff1aSopenharmony_ci.endif 156cabdff1aSopenharmony_ci add r1, r1, #1 157cabdff1aSopenharmony_ci.endm 158cabdff1aSopenharmony_ci check_reg r4, r5 159cabdff1aSopenharmony_ci check_reg r6, r7 160cabdff1aSopenharmony_ci@ r9 is a volatile register in the ios ABI 161cabdff1aSopenharmony_ci#ifdef __APPLE__ 162cabdff1aSopenharmony_ci check_reg r8 163cabdff1aSopenharmony_ci#else 164cabdff1aSopenharmony_ci check_reg r8, r9 165cabdff1aSopenharmony_ci#endif 166cabdff1aSopenharmony_ci check_reg r10, r11 167cabdff1aSopenharmony_ci.purgem check_reg 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci b 0f 170cabdff1aSopenharmony_ci5: 171cabdff1aSopenharmony_ci movrel r0, error_message_stack 172cabdff1aSopenharmony_ci b 1f 173cabdff1aSopenharmony_ci4: 174cabdff1aSopenharmony_ci movrel r0, error_message_vfp 175cabdff1aSopenharmony_ci b 1f 176cabdff1aSopenharmony_ci3: 177cabdff1aSopenharmony_ci movrel r0, error_message_fpscr 178cabdff1aSopenharmony_ci b 1f 179cabdff1aSopenharmony_ci2: 180cabdff1aSopenharmony_ci movrel r0, error_message_gpr 181cabdff1aSopenharmony_ci1: 182cabdff1aSopenharmony_ci bl X(checkasm_fail_func) 183cabdff1aSopenharmony_ci0: 184cabdff1aSopenharmony_ci pop {r0, r1} 185cabdff1aSopenharmony_ci.ifc \variant, vfp 186cabdff1aSopenharmony_ci pop {r2} 187cabdff1aSopenharmony_ci fmxr FPSCR, r2 188cabdff1aSopenharmony_ci vpop {d8-d15} 189cabdff1aSopenharmony_ci.endif 190cabdff1aSopenharmony_ci pop {r4-r11, pc} 191cabdff1aSopenharmony_ciendfunc 192cabdff1aSopenharmony_ci.endm 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci#if HAVE_VFP || HAVE_NEON 195cabdff1aSopenharmony_ciclobbercheck vfp 196cabdff1aSopenharmony_ci#endif 197cabdff1aSopenharmony_ciclobbercheck novfp 198