Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1 | ; |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 2 | ; Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 3 | ; |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 4 | ; This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | ; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | ; was not distributed with this source code in the LICENSE file, you can |
| 7 | ; obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | ; Media Patent License 1.0 was not distributed with this source code in the |
| 9 | ; PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| 10 | ; |
| 11 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 12 | ; |
| 13 | |
| 14 | |
Tom Finegan | 60e653d | 2018-05-22 11:34:58 -0700 | [diff] [blame] | 15 | %include "config/aom_config.asm" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 16 | |
| 17 | ; 32/64 bit compatibility macros |
| 18 | ; |
| 19 | ; In general, we make the source use 64 bit syntax, then twiddle with it using |
| 20 | ; the preprocessor to get the 32 bit syntax on 32 bit platforms. |
| 21 | ; |
| 22 | %ifidn __OUTPUT_FORMAT__,elf32 |
| 23 | %define ABI_IS_32BIT 1 |
| 24 | %elifidn __OUTPUT_FORMAT__,macho32 |
| 25 | %define ABI_IS_32BIT 1 |
| 26 | %elifidn __OUTPUT_FORMAT__,win32 |
| 27 | %define ABI_IS_32BIT 1 |
| 28 | %elifidn __OUTPUT_FORMAT__,aout |
| 29 | %define ABI_IS_32BIT 1 |
| 30 | %else |
| 31 | %define ABI_IS_32BIT 0 |
| 32 | %endif |
| 33 | |
| 34 | %if ABI_IS_32BIT |
| 35 | %define rax eax |
| 36 | %define rbx ebx |
| 37 | %define rcx ecx |
| 38 | %define rdx edx |
| 39 | %define rsi esi |
| 40 | %define rdi edi |
| 41 | %define rsp esp |
| 42 | %define rbp ebp |
| 43 | %define movsxd mov |
| 44 | %macro movq 2 |
| 45 | %ifidn %1,eax |
| 46 | movd %1,%2 |
| 47 | %elifidn %2,eax |
| 48 | movd %1,%2 |
| 49 | %elifidn %1,ebx |
| 50 | movd %1,%2 |
| 51 | %elifidn %2,ebx |
| 52 | movd %1,%2 |
| 53 | %elifidn %1,ecx |
| 54 | movd %1,%2 |
| 55 | %elifidn %2,ecx |
| 56 | movd %1,%2 |
| 57 | %elifidn %1,edx |
| 58 | movd %1,%2 |
| 59 | %elifidn %2,edx |
| 60 | movd %1,%2 |
| 61 | %elifidn %1,esi |
| 62 | movd %1,%2 |
| 63 | %elifidn %2,esi |
| 64 | movd %1,%2 |
| 65 | %elifidn %1,edi |
| 66 | movd %1,%2 |
| 67 | %elifidn %2,edi |
| 68 | movd %1,%2 |
| 69 | %elifidn %1,esp |
| 70 | movd %1,%2 |
| 71 | %elifidn %2,esp |
| 72 | movd %1,%2 |
| 73 | %elifidn %1,ebp |
| 74 | movd %1,%2 |
| 75 | %elifidn %2,ebp |
| 76 | movd %1,%2 |
| 77 | %else |
| 78 | movq %1,%2 |
| 79 | %endif |
| 80 | %endmacro |
| 81 | %endif |
| 82 | |
| 83 | |
| 84 | ; LIBAOM_YASM_WIN64 |
| 85 | ; Set LIBAOM_YASM_WIN64 if output is Windows 64bit so the code will work if x64 |
| 86 | ; or win64 is defined on the Yasm command line. |
| 87 | %ifidn __OUTPUT_FORMAT__,win64 |
| 88 | %define LIBAOM_YASM_WIN64 1 |
| 89 | %elifidn __OUTPUT_FORMAT__,x64 |
| 90 | %define LIBAOM_YASM_WIN64 1 |
| 91 | %else |
| 92 | %define LIBAOM_YASM_WIN64 0 |
| 93 | %endif |
| 94 | |
| 95 | ; sym() |
| 96 | ; Return the proper symbol name for the target ABI. |
| 97 | ; |
| 98 | ; Certain ABIs, notably MS COFF and Darwin MACH-O, require that symbols |
| 99 | ; with C linkage be prefixed with an underscore. |
| 100 | ; |
| 101 | %ifidn __OUTPUT_FORMAT__,elf32 |
| 102 | %define sym(x) x |
| 103 | %elifidn __OUTPUT_FORMAT__,elf64 |
| 104 | %define sym(x) x |
| 105 | %elifidn __OUTPUT_FORMAT__,elfx32 |
| 106 | %define sym(x) x |
| 107 | %elif LIBAOM_YASM_WIN64 |
| 108 | %define sym(x) x |
| 109 | %else |
| 110 | %define sym(x) _ %+ x |
| 111 | %endif |
| 112 | |
| 113 | ; PRIVATE |
| 114 | ; Macro for the attribute to hide a global symbol for the target ABI. |
| 115 | ; This is only active if CHROMIUM is defined. |
| 116 | ; |
| 117 | ; Chromium doesn't like exported global symbols due to symbol clashing with |
| 118 | ; plugins among other things. |
| 119 | ; |
| 120 | ; Requires Chromium's patched copy of yasm: |
| 121 | ; http://src.chromium.org/viewvc/chrome?view=rev&revision=73761 |
| 122 | ; http://www.tortall.net/projects/yasm/ticket/236 |
| 123 | ; |
| 124 | %ifdef CHROMIUM |
Johann | e963651 | 2020-04-01 08:57:52 +0900 | [diff] [blame^] | 125 | %ifdef __NASM_VER__ |
| 126 | %if __NASM_VERSION_ID__ < 0x020e0000 ; 2.14 |
| 127 | ; nasm < 2.14 does not support :private_extern directive |
| 128 | %fatal Must use nasm 2.14 or newer |
| 129 | %endif |
| 130 | %endif |
| 131 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 132 | %ifidn __OUTPUT_FORMAT__,elf32 |
| 133 | %define PRIVATE :hidden |
| 134 | %elifidn __OUTPUT_FORMAT__,elf64 |
| 135 | %define PRIVATE :hidden |
| 136 | %elifidn __OUTPUT_FORMAT__,elfx32 |
| 137 | %define PRIVATE :hidden |
| 138 | %elif LIBAOM_YASM_WIN64 |
| 139 | %define PRIVATE |
| 140 | %else |
| 141 | %define PRIVATE :private_extern |
| 142 | %endif |
| 143 | %else |
| 144 | %define PRIVATE |
| 145 | %endif |
| 146 | |
| 147 | ; arg() |
| 148 | ; Return the address specification of the given argument |
| 149 | ; |
| 150 | %if ABI_IS_32BIT |
| 151 | %define arg(x) [ebp+8+4*x] |
| 152 | %else |
| 153 | ; 64 bit ABI passes arguments in registers. This is a workaround to get up |
| 154 | ; and running quickly. Relies on SHADOW_ARGS_TO_STACK |
| 155 | %if LIBAOM_YASM_WIN64 |
| 156 | %define arg(x) [rbp+16+8*x] |
| 157 | %else |
| 158 | %define arg(x) [rbp-8-8*x] |
| 159 | %endif |
| 160 | %endif |
| 161 | |
| 162 | ; REG_SZ_BYTES, REG_SZ_BITS |
| 163 | ; Size of a register |
| 164 | %if ABI_IS_32BIT |
| 165 | %define REG_SZ_BYTES 4 |
| 166 | %define REG_SZ_BITS 32 |
| 167 | %else |
| 168 | %define REG_SZ_BYTES 8 |
| 169 | %define REG_SZ_BITS 64 |
| 170 | %endif |
| 171 | |
| 172 | |
| 173 | ; ALIGN_STACK <alignment> <register> |
| 174 | ; This macro aligns the stack to the given alignment (in bytes). The stack |
| 175 | ; is left such that the previous value of the stack pointer is the first |
| 176 | ; argument on the stack (ie, the inverse of this macro is 'pop rsp.') |
| 177 | ; This macro uses one temporary register, which is not preserved, and thus |
| 178 | ; must be specified as an argument. |
| 179 | %macro ALIGN_STACK 2 |
| 180 | mov %2, rsp |
| 181 | and rsp, -%1 |
| 182 | lea rsp, [rsp - (%1 - REG_SZ_BYTES)] |
| 183 | push %2 |
| 184 | %endmacro |
| 185 | |
| 186 | |
| 187 | ; |
| 188 | ; The Microsoft assembler tries to impose a certain amount of type safety in |
| 189 | ; its register usage. YASM doesn't recognize these directives, so we just |
| 190 | ; %define them away to maintain as much compatibility as possible with the |
| 191 | ; original inline assembler we're porting from. |
| 192 | ; |
| 193 | %idefine PTR |
| 194 | %idefine XMMWORD |
| 195 | %idefine MMWORD |
| 196 | |
| 197 | ; PIC macros |
| 198 | ; |
| 199 | %if ABI_IS_32BIT |
| 200 | %if CONFIG_PIC=1 |
| 201 | %ifidn __OUTPUT_FORMAT__,elf32 |
| 202 | %define WRT_PLT wrt ..plt |
| 203 | %macro GET_GOT 1 |
| 204 | extern _GLOBAL_OFFSET_TABLE_ |
| 205 | push %1 |
| 206 | call %%get_got |
| 207 | %%sub_offset: |
| 208 | jmp %%exitGG |
| 209 | %%get_got: |
| 210 | mov %1, [esp] |
| 211 | add %1, _GLOBAL_OFFSET_TABLE_ + $$ - %%sub_offset wrt ..gotpc |
| 212 | ret |
| 213 | %%exitGG: |
| 214 | %undef GLOBAL |
| 215 | %define GLOBAL(x) x + %1 wrt ..gotoff |
| 216 | %undef RESTORE_GOT |
| 217 | %define RESTORE_GOT pop %1 |
| 218 | %endmacro |
| 219 | %elifidn __OUTPUT_FORMAT__,macho32 |
| 220 | %macro GET_GOT 1 |
| 221 | push %1 |
| 222 | call %%get_got |
| 223 | %%get_got: |
| 224 | pop %1 |
| 225 | %undef GLOBAL |
| 226 | %define GLOBAL(x) x + %1 - %%get_got |
| 227 | %undef RESTORE_GOT |
| 228 | %define RESTORE_GOT pop %1 |
| 229 | %endmacro |
| 230 | %endif |
| 231 | %endif |
| 232 | |
| 233 | %ifdef CHROMIUM |
| 234 | %ifidn __OUTPUT_FORMAT__,macho32 |
| 235 | %define HIDDEN_DATA(x) x:private_extern |
| 236 | %else |
| 237 | %define HIDDEN_DATA(x) x |
| 238 | %endif |
| 239 | %else |
| 240 | %define HIDDEN_DATA(x) x |
| 241 | %endif |
| 242 | %else |
| 243 | %macro GET_GOT 1 |
| 244 | %endmacro |
| 245 | %define GLOBAL(x) rel x |
| 246 | %ifidn __OUTPUT_FORMAT__,elf64 |
| 247 | %define WRT_PLT wrt ..plt |
| 248 | %define HIDDEN_DATA(x) x:data hidden |
| 249 | %elifidn __OUTPUT_FORMAT__,elfx32 |
| 250 | %define WRT_PLT wrt ..plt |
| 251 | %define HIDDEN_DATA(x) x:data hidden |
| 252 | %elifidn __OUTPUT_FORMAT__,macho64 |
| 253 | %ifdef CHROMIUM |
| 254 | %define HIDDEN_DATA(x) x:private_extern |
| 255 | %else |
| 256 | %define HIDDEN_DATA(x) x |
| 257 | %endif |
| 258 | %else |
| 259 | %define HIDDEN_DATA(x) x |
| 260 | %endif |
| 261 | %endif |
| 262 | %ifnmacro GET_GOT |
| 263 | %macro GET_GOT 1 |
| 264 | %endmacro |
| 265 | %define GLOBAL(x) x |
| 266 | %endif |
| 267 | %ifndef RESTORE_GOT |
| 268 | %define RESTORE_GOT |
| 269 | %endif |
| 270 | %ifndef WRT_PLT |
| 271 | %define WRT_PLT |
| 272 | %endif |
| 273 | |
| 274 | %if ABI_IS_32BIT |
| 275 | %macro SHADOW_ARGS_TO_STACK 1 |
| 276 | %endm |
| 277 | %define UNSHADOW_ARGS |
| 278 | %else |
| 279 | %if LIBAOM_YASM_WIN64 |
| 280 | %macro SHADOW_ARGS_TO_STACK 1 ; argc |
| 281 | %if %1 > 0 |
| 282 | mov arg(0),rcx |
| 283 | %endif |
| 284 | %if %1 > 1 |
| 285 | mov arg(1),rdx |
| 286 | %endif |
| 287 | %if %1 > 2 |
| 288 | mov arg(2),r8 |
| 289 | %endif |
| 290 | %if %1 > 3 |
| 291 | mov arg(3),r9 |
| 292 | %endif |
| 293 | %endm |
| 294 | %else |
| 295 | %macro SHADOW_ARGS_TO_STACK 1 ; argc |
| 296 | %if %1 > 0 |
| 297 | push rdi |
| 298 | %endif |
| 299 | %if %1 > 1 |
| 300 | push rsi |
| 301 | %endif |
| 302 | %if %1 > 2 |
| 303 | push rdx |
| 304 | %endif |
| 305 | %if %1 > 3 |
| 306 | push rcx |
| 307 | %endif |
| 308 | %if %1 > 4 |
| 309 | push r8 |
| 310 | %endif |
| 311 | %if %1 > 5 |
| 312 | push r9 |
| 313 | %endif |
| 314 | %if %1 > 6 |
| 315 | %assign i %1-6 |
| 316 | %assign off 16 |
| 317 | %rep i |
| 318 | mov rax,[rbp+off] |
| 319 | push rax |
| 320 | %assign off off+8 |
| 321 | %endrep |
| 322 | %endif |
| 323 | %endm |
| 324 | %endif |
| 325 | %define UNSHADOW_ARGS mov rsp, rbp |
| 326 | %endif |
| 327 | |
| 328 | ; Win64 ABI requires that XMM6:XMM15 are callee saved |
| 329 | ; SAVE_XMM n, [u] |
| 330 | ; store registers 6-n on the stack |
| 331 | ; if u is specified, use unaligned movs. |
| 332 | ; Win64 ABI requires 16 byte stack alignment, but then pushes an 8 byte return |
| 333 | ; value. Typically we follow this up with 'push rbp' - re-aligning the stack - |
| 334 | ; but in some cases this is not done and unaligned movs must be used. |
| 335 | %if LIBAOM_YASM_WIN64 |
| 336 | %macro SAVE_XMM 1-2 a |
| 337 | %if %1 < 6 |
| 338 | %error Only xmm registers 6-15 must be preserved |
| 339 | %else |
| 340 | %assign last_xmm %1 |
| 341 | %define movxmm movdq %+ %2 |
| 342 | %assign xmm_stack_space ((last_xmm - 5) * 16) |
| 343 | sub rsp, xmm_stack_space |
| 344 | %assign i 6 |
| 345 | %rep (last_xmm - 5) |
| 346 | movxmm [rsp + ((i - 6) * 16)], xmm %+ i |
| 347 | %assign i i+1 |
| 348 | %endrep |
| 349 | %endif |
| 350 | %endmacro |
| 351 | %macro RESTORE_XMM 0 |
| 352 | %ifndef last_xmm |
| 353 | %error RESTORE_XMM must be paired with SAVE_XMM n |
| 354 | %else |
| 355 | %assign i last_xmm |
| 356 | %rep (last_xmm - 5) |
| 357 | movxmm xmm %+ i, [rsp +((i - 6) * 16)] |
| 358 | %assign i i-1 |
| 359 | %endrep |
| 360 | add rsp, xmm_stack_space |
| 361 | ; there are a couple functions which return from multiple places. |
| 362 | ; otherwise, we could uncomment these: |
| 363 | ; %undef last_xmm |
| 364 | ; %undef xmm_stack_space |
| 365 | ; %undef movxmm |
| 366 | %endif |
| 367 | %endmacro |
| 368 | %else |
| 369 | %macro SAVE_XMM 1-2 |
| 370 | %endmacro |
| 371 | %macro RESTORE_XMM 0 |
| 372 | %endmacro |
| 373 | %endif |
| 374 | |
| 375 | ; Name of the rodata section |
| 376 | ; |
| 377 | ; .rodata seems to be an elf-ism, as it doesn't work on OSX. |
| 378 | ; |
| 379 | %ifidn __OUTPUT_FORMAT__,macho64 |
| 380 | %define SECTION_RODATA section .text |
| 381 | %elifidn __OUTPUT_FORMAT__,macho32 |
| 382 | %macro SECTION_RODATA 0 |
| 383 | section .text |
| 384 | %endmacro |
| 385 | %elifidn __OUTPUT_FORMAT__,aout |
| 386 | %define SECTION_RODATA section .data |
| 387 | %else |
| 388 | %define SECTION_RODATA section .rodata |
| 389 | %endif |
| 390 | |
| 391 | |
| 392 | ; Tell GNU ld that we don't require an executable stack. |
| 393 | %ifidn __OUTPUT_FORMAT__,elf32 |
| 394 | section .note.GNU-stack noalloc noexec nowrite progbits |
| 395 | section .text |
| 396 | %elifidn __OUTPUT_FORMAT__,elf64 |
| 397 | section .note.GNU-stack noalloc noexec nowrite progbits |
| 398 | section .text |
| 399 | %elifidn __OUTPUT_FORMAT__,elfx32 |
| 400 | section .note.GNU-stack noalloc noexec nowrite progbits |
| 401 | section .text |
| 402 | %endif |