asm.S (8439B)
1 /* 2 * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "config.h" 22 23 #ifdef __ELF__ 24 # define ELF 25 #else 26 # define ELF # 27 #endif 28 29 #if HAVE_AS_FUNC 30 # define FUNC 31 #else 32 # define FUNC # 33 #endif 34 35 #ifndef __has_feature 36 # define __has_feature(x) 0 37 #endif 38 39 #if HAVE_AS_ARCH_DIRECTIVE 40 .arch AS_ARCH_LEVEL 41 #endif 42 43 #if HAVE_AS_ARCHEXT_DOTPROD_DIRECTIVE 44 #define ENABLE_DOTPROD .arch_extension dotprod 45 #define DISABLE_DOTPROD .arch_extension nodotprod 46 #else 47 #define ENABLE_DOTPROD 48 #define DISABLE_DOTPROD 49 #endif 50 51 #if HAVE_AS_ARCHEXT_I8MM_DIRECTIVE 52 #define ENABLE_I8MM .arch_extension i8mm 53 #define DISABLE_I8MM .arch_extension noi8mm 54 #else 55 #define ENABLE_I8MM 56 #define DISABLE_I8MM 57 #endif 58 59 #if HAVE_AS_ARCHEXT_SVE_DIRECTIVE 60 #define ENABLE_SVE .arch_extension sve 61 #define DISABLE_SVE .arch_extension nosve 62 #else 63 #define ENABLE_SVE 64 #define DISABLE_SVE 65 #endif 66 67 #if HAVE_AS_ARCHEXT_SVE2_DIRECTIVE 68 #define ENABLE_SVE2 .arch_extension sve2 69 #define DISABLE_SVE2 .arch_extension nosve2 70 #else 71 #define ENABLE_SVE2 72 #define DISABLE_SVE2 73 #endif 74 75 DISABLE_DOTPROD 76 DISABLE_I8MM 77 DISABLE_SVE 78 DISABLE_SVE2 79 80 81 /* Support macros for 82 * - Armv8.3-A Pointer Authentication and 83 * - Armv8.5-A Branch Target Identification 84 * features which require emitting a .note.gnu.property section with the 85 * appropriate architecture-dependent feature bits set. 86 * 87 * |AARCH64_SIGN_LINK_REGISTER| and |AARCH64_VALIDATE_LINK_REGISTER| expand to 88 * PACIxSP and AUTIxSP, respectively. |AARCH64_SIGN_LINK_REGISTER| should be 89 * used immediately before saving the LR register (x30) to the stack. 90 * |AARCH64_VALIDATE_LINK_REGISTER| should be used immediately after restoring 91 * it. Note |AARCH64_SIGN_LINK_REGISTER|'s modifications to LR must be undone 92 * with |AARCH64_VALIDATE_LINK_REGISTER| before RET. The SP register must also 93 * have the same value at the two points. For example: 94 * 95 * .global f 96 * f: 97 * AARCH64_SIGN_LINK_REGISTER 98 * stp x29, x30, [sp, #-96]! 99 * mov x29, sp 100 * ... 101 * ldp x29, x30, [sp], #96 102 * AARCH64_VALIDATE_LINK_REGISTER 103 * ret 104 * 105 * |AARCH64_VALID_CALL_TARGET| expands to BTI 'c'. Either it, or 106 * |AARCH64_SIGN_LINK_REGISTER|, must be used at every point that may be an 107 * indirect call target. In particular, all symbols exported from a file must 108 * begin with one of these macros. For example, a leaf function that does not 109 * save LR can instead use |AARCH64_VALID_CALL_TARGET|: 110 * 111 * .globl return_zero 112 * return_zero: 113 * AARCH64_VALID_CALL_TARGET 114 * mov x0, #0 115 * ret 116 * 117 * A non-leaf function which does not immediately save LR may need both macros 118 * because |AARCH64_SIGN_LINK_REGISTER| appears late. For example, the function 119 * may jump to an alternate implementation before setting up the stack: 120 * 121 * .globl with_early_jump 122 * with_early_jump: 123 * AARCH64_VALID_CALL_TARGET 124 * cmp x0, #128 125 * b.lt .Lwith_early_jump_128 126 * AARCH64_SIGN_LINK_REGISTER 127 * stp x29, x30, [sp, #-96]! 128 * mov x29, sp 129 * ... 130 * ldp x29, x30, [sp], #96 131 * AARCH64_VALIDATE_LINK_REGISTER 132 * ret 133 * 134 * .Lwith_early_jump_128: 135 * ... 136 * ret 137 * 138 * These annotations are only required with indirect calls. Private symbols that 139 * are only the target of direct calls do not require annotations. Also note 140 * that |AARCH64_VALID_CALL_TARGET| is only valid for indirect calls (BLR), not 141 * indirect jumps (BR). Indirect jumps in assembly are supported through 142 * |AARCH64_VALID_JUMP_TARGET|. Landing Pads which shall serve for jumps and 143 * calls can be created using |AARCH64_VALID_JUMP_CALL_TARGET|. 144 * 145 * Although not necessary, it is safe to use these macros in 32-bit ARM 146 * assembly. This may be used to simplify dual 32-bit and 64-bit files. 147 * 148 * References: 149 * - "ELF for the ArmĀ® 64-bit Architecture" 150 * https: *github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst 151 * - "Providing protection for complex software" 152 * https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software 153 */ 154 #if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) 155 # define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has BTI 156 # define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' 157 # define AARCH64_VALID_JUMP_TARGET hint #38 // BTI 'j' 158 #else 159 # define GNU_PROPERTY_AARCH64_BTI 0 // No BTI 160 # define AARCH64_VALID_CALL_TARGET 161 # define AARCH64_VALID_JUMP_TARGET 162 #endif 163 164 #if defined(__ARM_FEATURE_PAC_DEFAULT) 165 # if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 0)) != 0) // authentication using key A 166 # define AARCH64_SIGN_LINK_REGISTER paciasp 167 # define AARCH64_VALIDATE_LINK_REGISTER autiasp 168 # elif ((__ARM_FEATURE_PAC_DEFAULT & (1 << 1)) != 0) // authentication using key B 169 # define AARCH64_SIGN_LINK_REGISTER pacibsp 170 # define AARCH64_VALIDATE_LINK_REGISTER autibsp 171 # else 172 # error Pointer authentication defines no valid key! 173 # endif 174 # if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 2)) != 0) 175 # error Authentication of leaf functions is enabled but not supported in FFmpeg! 176 # endif 177 # define GNU_PROPERTY_AARCH64_PAC (1 << 1) 178 #else 179 # define GNU_PROPERTY_AARCH64_PAC 0 180 # define AARCH64_SIGN_LINK_REGISTER 181 # define AARCH64_VALIDATE_LINK_REGISTER 182 #endif 183 184 185 #if (GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_PAC != 0) && defined(__ELF__) 186 .pushsection .note.gnu.property, "a" 187 .balign 8 188 .long 4 189 .long 0x10 190 .long 0x5 191 .asciz "GNU" 192 .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ 193 .long 4 194 .long (GNU_PROPERTY_AARCH64_BTI | GNU_PROPERTY_AARCH64_PAC) 195 .long 0 196 .popsection 197 #endif 198 199 .macro function name, export=0, align=2 200 .macro endfunc 201 ELF .size \name, . - \name 202 FUNC .endfunc 203 .purgem endfunc 204 .endm 205 .text 206 .align \align 207 .if \export 208 .global EXTERN_ASM\name 209 ELF .type EXTERN_ASM\name, %function 210 FUNC .func EXTERN_ASM\name 211 EXTERN_ASM\name: 212 AARCH64_VALID_CALL_TARGET 213 .else 214 ELF .type \name, %function 215 FUNC .func \name 216 \name: 217 .endif 218 .endm 219 220 .macro const name, align=2, relocate=0 221 .macro endconst 222 ELF .size \name, . - \name 223 .purgem endconst 224 .endm 225 #if HAVE_SECTION_DATA_REL_RO 226 .if \relocate 227 .section .data.rel.ro 228 .else 229 .section .rodata 230 .endif 231 #elif defined(_WIN32) 232 .section .rdata 233 #elif !defined(__MACH__) 234 .section .rodata 235 #else 236 .const_data 237 #endif 238 .align \align 239 \name: 240 .endm 241 242 .macro movrel rd, val, offset=0 243 #if CONFIG_PIC && defined(__APPLE__) 244 .if \offset < 0 245 adrp \rd, \val@PAGE 246 add \rd, \rd, \val@PAGEOFF 247 sub \rd, \rd, -(\offset) 248 .else 249 adrp \rd, \val+(\offset)@PAGE 250 add \rd, \rd, \val+(\offset)@PAGEOFF 251 .endif 252 #elif CONFIG_PIC && defined(_WIN32) 253 .if \offset < 0 254 adrp \rd, \val 255 add \rd, \rd, :lo12:\val 256 sub \rd, \rd, -(\offset) 257 .else 258 adrp \rd, \val+(\offset) 259 add \rd, \rd, :lo12:\val+(\offset) 260 .endif 261 #elif CONFIG_PIC 262 # if __has_feature(hwaddress_sanitizer) 263 adrp \rd, :pg_hi21_nc:\val+(\offset) 264 # else 265 adrp \rd, \val+(\offset) 266 # endif 267 add \rd, \rd, :lo12:\val+(\offset) 268 #else 269 ldr \rd, =\val+\offset 270 #endif 271 .endm 272 273 #define GLUE(a, b) a ## b 274 #define JOIN(a, b) GLUE(a, b) 275 #define X(s) JOIN(EXTERN_ASM, s) 276 277 #define x18 do_not_use_x18 278 #define w18 do_not_use_w18