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/aarch64/asm.S" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ciconst register_init, align=4 26cabdff1aSopenharmony_ci .quad 0x21f86d66c8ca00ce 27cabdff1aSopenharmony_ci .quad 0x75b6ba21077c48ad 28cabdff1aSopenharmony_ci .quad 0xed56bb2dcb3c7736 29cabdff1aSopenharmony_ci .quad 0x8bda43d3fd1a7e06 30cabdff1aSopenharmony_ci .quad 0xb64a9c9e5d318408 31cabdff1aSopenharmony_ci .quad 0xdf9a54b303f1d3a3 32cabdff1aSopenharmony_ci .quad 0x4a75479abd64e097 33cabdff1aSopenharmony_ci .quad 0x249214109d5d1c88 34cabdff1aSopenharmony_ci .quad 0x1a1b2550a612b48c 35cabdff1aSopenharmony_ci .quad 0x79445c159ce79064 36cabdff1aSopenharmony_ci .quad 0x2eed899d5a28ddcd 37cabdff1aSopenharmony_ci .quad 0x86b2536fcd8cf636 38cabdff1aSopenharmony_ci .quad 0xb0856806085e7943 39cabdff1aSopenharmony_ci .quad 0x3f2bf84fc0fcca4e 40cabdff1aSopenharmony_ci .quad 0xacbd382dcf5b8de2 41cabdff1aSopenharmony_ci .quad 0xd229e1f5b281303f 42cabdff1aSopenharmony_ci .quad 0x71aeaff20b095fd9 43cabdff1aSopenharmony_ci .quad 0xab63e2e11fa38ed9 44cabdff1aSopenharmony_ciendconst 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ciconst error_message_register 48cabdff1aSopenharmony_ci .asciz "failed to preserve register" 49cabdff1aSopenharmony_cierror_message_stack: 50cabdff1aSopenharmony_ci .asciz "stack clobbered" 51cabdff1aSopenharmony_ciendconst 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci// max number of args used by any asm function. 55cabdff1aSopenharmony_ci#define MAX_ARGS 15 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci#define CLOBBER_STACK ((8*MAX_ARGS + 15) & ~15) 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_cifunction checkasm_stack_clobber, export=1 60cabdff1aSopenharmony_ci mov x3, sp 61cabdff1aSopenharmony_ci mov x2, #CLOBBER_STACK 62cabdff1aSopenharmony_ci1: 63cabdff1aSopenharmony_ci stp x0, x1, [sp, #-16]! 64cabdff1aSopenharmony_ci subs x2, x2, #16 65cabdff1aSopenharmony_ci b.gt 1b 66cabdff1aSopenharmony_ci mov sp, x3 67cabdff1aSopenharmony_ci ret 68cabdff1aSopenharmony_ciendfunc 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci// + 16 for stack canary reference 71cabdff1aSopenharmony_ci#define ARG_STACK ((8*(MAX_ARGS - 8) + 15) & ~15 + 16) 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_cifunction checkasm_checked_call, export=1 74cabdff1aSopenharmony_ci stp x29, x30, [sp, #-16]! 75cabdff1aSopenharmony_ci mov x29, sp 76cabdff1aSopenharmony_ci stp x19, x20, [sp, #-16]! 77cabdff1aSopenharmony_ci stp x21, x22, [sp, #-16]! 78cabdff1aSopenharmony_ci stp x23, x24, [sp, #-16]! 79cabdff1aSopenharmony_ci stp x25, x26, [sp, #-16]! 80cabdff1aSopenharmony_ci stp x27, x28, [sp, #-16]! 81cabdff1aSopenharmony_ci stp d8, d9, [sp, #-16]! 82cabdff1aSopenharmony_ci stp d10, d11, [sp, #-16]! 83cabdff1aSopenharmony_ci stp d12, d13, [sp, #-16]! 84cabdff1aSopenharmony_ci stp d14, d15, [sp, #-16]! 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci movrel x9, register_init 87cabdff1aSopenharmony_ci ldp d8, d9, [x9], #16 88cabdff1aSopenharmony_ci ldp d10, d11, [x9], #16 89cabdff1aSopenharmony_ci ldp d12, d13, [x9], #16 90cabdff1aSopenharmony_ci ldp d14, d15, [x9], #16 91cabdff1aSopenharmony_ci ldp x19, x20, [x9], #16 92cabdff1aSopenharmony_ci ldp x21, x22, [x9], #16 93cabdff1aSopenharmony_ci ldp x23, x24, [x9], #16 94cabdff1aSopenharmony_ci ldp x25, x26, [x9], #16 95cabdff1aSopenharmony_ci ldp x27, x28, [x9], #16 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci sub sp, sp, #ARG_STACK 98cabdff1aSopenharmony_ci.equ pos, 0 99cabdff1aSopenharmony_ci.rept MAX_ARGS-8 100cabdff1aSopenharmony_ci // Skip the first 8 args, that are loaded into registers 101cabdff1aSopenharmony_ci ldr x9, [x29, #16 + 8*8 + pos] 102cabdff1aSopenharmony_ci str x9, [sp, #pos] 103cabdff1aSopenharmony_ci.equ pos, pos + 8 104cabdff1aSopenharmony_ci.endr 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci // Fill x8-x17 with garbage. This doesn't have to be preserved, 107cabdff1aSopenharmony_ci // but avoids relying on them having any particular value. 108cabdff1aSopenharmony_ci movrel x9, register_init 109cabdff1aSopenharmony_ci ldp x10, x11, [x9], #32 110cabdff1aSopenharmony_ci ldp x12, x13, [x9], #32 111cabdff1aSopenharmony_ci ldp x14, x15, [x9], #32 112cabdff1aSopenharmony_ci ldp x16, x17, [x9], #32 113cabdff1aSopenharmony_ci ldp x8, x9, [x9] 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci // For stack overflows, the callee is free to overwrite the parameters 116cabdff1aSopenharmony_ci // that were passed on the stack (if any), so we can only check after 117cabdff1aSopenharmony_ci // that point. First figure out how many parameters the function 118cabdff1aSopenharmony_ci // really took on the stack: 119cabdff1aSopenharmony_ci ldr w2, [x29, #16 + 8*8 + (MAX_ARGS-8)*8] 120cabdff1aSopenharmony_ci // Load the first non-parameter value from the stack, that should be 121cabdff1aSopenharmony_ci // left untouched by the function. Store a copy of it inverted, so that 122cabdff1aSopenharmony_ci // e.g. overwriting everything with zero would be noticed. 123cabdff1aSopenharmony_ci ldr x2, [sp, x2, lsl #3] 124cabdff1aSopenharmony_ci mvn x2, x2 125cabdff1aSopenharmony_ci str x2, [sp, #ARG_STACK-8] 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ci // Load the in-register arguments 128cabdff1aSopenharmony_ci mov x12, x0 129cabdff1aSopenharmony_ci ldp x0, x1, [x29, #16] 130cabdff1aSopenharmony_ci ldp x2, x3, [x29, #32] 131cabdff1aSopenharmony_ci ldp x4, x5, [x29, #48] 132cabdff1aSopenharmony_ci ldp x6, x7, [x29, #64] 133cabdff1aSopenharmony_ci // Call the target function 134cabdff1aSopenharmony_ci blr x12 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci // Load the number of stack parameters, stack canary and its reference 137cabdff1aSopenharmony_ci ldr w2, [x29, #16 + 8*8 + (MAX_ARGS-8)*8] 138cabdff1aSopenharmony_ci ldr x2, [sp, x2, lsl #3] 139cabdff1aSopenharmony_ci ldr x3, [sp, #ARG_STACK-8] 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci add sp, sp, #ARG_STACK 142cabdff1aSopenharmony_ci stp x0, x1, [sp, #-16]! 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci mvn x3, x3 145cabdff1aSopenharmony_ci cmp x2, x3 146cabdff1aSopenharmony_ci b.ne 2f 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci movrel x9, register_init 149cabdff1aSopenharmony_ci movi v3.8h, #0 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci.macro check_reg_neon reg1, reg2 152cabdff1aSopenharmony_ci ldr q1, [x9], #16 153cabdff1aSopenharmony_ci uzp1 v2.2d, v\reg1\().2d, v\reg2\().2d 154cabdff1aSopenharmony_ci eor v1.16b, v1.16b, v2.16b 155cabdff1aSopenharmony_ci orr v3.16b, v3.16b, v1.16b 156cabdff1aSopenharmony_ci.endm 157cabdff1aSopenharmony_ci check_reg_neon 8, 9 158cabdff1aSopenharmony_ci check_reg_neon 10, 11 159cabdff1aSopenharmony_ci check_reg_neon 12, 13 160cabdff1aSopenharmony_ci check_reg_neon 14, 15 161cabdff1aSopenharmony_ci uqxtn v3.8b, v3.8h 162cabdff1aSopenharmony_ci umov x3, v3.d[0] 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci.macro check_reg reg1, reg2 165cabdff1aSopenharmony_ci ldp x0, x1, [x9], #16 166cabdff1aSopenharmony_ci eor x0, x0, \reg1 167cabdff1aSopenharmony_ci eor x1, x1, \reg2 168cabdff1aSopenharmony_ci orr x3, x3, x0 169cabdff1aSopenharmony_ci orr x3, x3, x1 170cabdff1aSopenharmony_ci.endm 171cabdff1aSopenharmony_ci check_reg x19, x20 172cabdff1aSopenharmony_ci check_reg x21, x22 173cabdff1aSopenharmony_ci check_reg x23, x24 174cabdff1aSopenharmony_ci check_reg x25, x26 175cabdff1aSopenharmony_ci check_reg x27, x28 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_ci cbz x3, 0f 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci movrel x0, error_message_register 180cabdff1aSopenharmony_ci b 1f 181cabdff1aSopenharmony_ci2: 182cabdff1aSopenharmony_ci movrel x0, error_message_stack 183cabdff1aSopenharmony_ci1: 184cabdff1aSopenharmony_ci bl X(checkasm_fail_func) 185cabdff1aSopenharmony_ci0: 186cabdff1aSopenharmony_ci ldp x0, x1, [sp], #16 187cabdff1aSopenharmony_ci ldp d14, d15, [sp], #16 188cabdff1aSopenharmony_ci ldp d12, d13, [sp], #16 189cabdff1aSopenharmony_ci ldp d10, d11, [sp], #16 190cabdff1aSopenharmony_ci ldp d8, d9, [sp], #16 191cabdff1aSopenharmony_ci ldp x27, x28, [sp], #16 192cabdff1aSopenharmony_ci ldp x25, x26, [sp], #16 193cabdff1aSopenharmony_ci ldp x23, x24, [sp], #16 194cabdff1aSopenharmony_ci ldp x21, x22, [sp], #16 195cabdff1aSopenharmony_ci ldp x19, x20, [sp], #16 196cabdff1aSopenharmony_ci ldp x29, x30, [sp], #16 197cabdff1aSopenharmony_ci ret 198cabdff1aSopenharmony_ciendfunc 199