;
; Copyright (c) 2016, Alliance for Open Media. All rights reserved.
;
; This source code is subject to the terms of the BSD 2 Clause License and
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
; was not distributed with this source code in the LICENSE file, you can
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
; Media Patent License 1.0 was not distributed with this source code in the
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
;
;
%
include "config/aom_config.asm"
; 32/64 bit compatibility macros
;
; In general, we make the source use 64 bit syntax, then twiddle with it using
; the preprocessor to get the 32 bit syntax on 32 bit platforms.
;
%
ifidn __OUTPUT_FORMAT__,elf32
%define ABI_IS_32BIT
1
%elifidn __OUTPUT_FORMAT__,macho32
%define ABI_IS_32BIT
1
%elifidn __OUTPUT_FORMAT__,win32
%define ABI_IS_32BIT
1
%elifidn __OUTPUT_FORMAT__,aout
%define ABI_IS_32BIT
1
%
else
%define ABI_IS_32BIT
0
%endif
%
if ABI_IS_32BIT
%define rax
eax
%define rbx ebx
%define rcx
ecx
%define rdx
edx
%define rsi
esi
%define rdi
edi
%define rsp
esp
%define rbp
ebp
%define movsxd
mov
%
macro movq
2
%
ifidn %
1,
eax
movd %
1,%
2
%elifidn %
2,
eax
movd %
1,%
2
%elifidn %
1,ebx
movd %
1,%
2
%elifidn %
2,ebx
movd %
1,%
2
%elifidn %
1,
ecx
movd %
1,%
2
%elifidn %
2,
ecx
movd %
1,%
2
%elifidn %
1,
edx
movd %
1,%
2
%elifidn %
2,
edx
movd %
1,%
2
%elifidn %
1,
esi
movd %
1,%
2
%elifidn %
2,
esi
movd %
1,%
2
%elifidn %
1,
edi
movd %
1,%
2
%elifidn %
2,
edi
movd %
1,%
2
%elifidn %
1,
esp
movd %
1,%
2
%elifidn %
2,
esp
movd %
1,%
2
%elifidn %
1,
ebp
movd %
1,%
2
%elifidn %
2,
ebp
movd %
1,%
2
%
else
movq %
1,%
2
%endif
%endmacro
%endif
; LIBAOM_YASM_WIN64
; Set LIBAOM_YASM_WIN64 if output is Windows 64bit so the code will work if x64
; or win64 is defined on the Yasm command line.
%
ifidn __OUTPUT_FORMAT__,win64
%define LIBAOM_YASM_WIN64
1
%elifidn __OUTPUT_FORMAT__,x64
%define LIBAOM_YASM_WIN64
1
%
else
%define LIBAOM_YASM_WIN64
0
%endif
; Declare groups of platforms
%
ifidn __OUTPUT_FORMAT__,elf32
%define LIBAOM_ELF
1
%elifidn __OUTPUT_FORMAT__,elfx32
%define LIBAOM_ELF
1
%elifidn __OUTPUT_FORMAT__,elf64
%define LIBAOM_ELF
1
%
else
%define LIBAOM_ELF
0
%endif
%
ifidn __OUTPUT_FORMAT__,macho32
%define LIBAOM_MACHO
1
%elifidn __OUTPUT_FORMAT__,macho64
%define LIBAOM_MACHO
1
%
else
%define LIBAOM_MACHO
0
%endif
; sym()
; Return the proper symbol name for the target ABI.
;
; Certain ABIs, notably MS COFF and Darwin MACH-O, require that symbols
; with C linkage be prefixed with an underscore.
;
%
if LIBAOM_ELF || LIBAOM_YASM_WIN64
%define sym(x) x
%
else
; Mach-O / COFF
%define sym(x) _ %+ x
%endif
; globalsym()
; Return a global declaration with the proper decoration for the target ABI.
;
; When CHROMIUM is defined, include attributes to hide the symbol from the
; global namespace.
;
; Chromium doesn't like exported global symbols due to symbol clashing with
; plugins among other things.
;
; Requires Chromium's patched copy of yasm:
; http://src.chromium.org/viewvc/chrome?view=rev&revision=73761
; http://www.tortall.net/projects/yasm/ticket/236
; or nasm > 2.14.
;
%
ifdef CHROMIUM
%
ifdef __NASM_VER__
%
if __NASM_VERSION_ID__ <
0x020e0000
; 2.14
; nasm < 2.14 does not support :private_extern directive
%fatal Must use nasm
2.
14 or newer
%endif
%endif
%
if LIBAOM_ELF
%define globalsym(x) global sym(x) %+ :function hidden
%elif LIBAOM_MACHO
%define globalsym(x) global sym(x) %+ :private_extern
%
else
; COFF / PE32+
%define globalsym(x) global sym(x)
%endif
%
else
%define globalsym(x) global sym(x)
%endif
; arg()
; Return the address specification of the given argument
;
%
if ABI_IS_32BIT
%define arg(x) [
ebp+
8+
4*x]
%
else
; 64 bit ABI passes arguments in registers. This is a workaround to get up
; and running quickly. Relies on SHADOW_ARGS_TO_STACK
%
if LIBAOM_YASM_WIN64
%define arg(x) [rbp+
16+
8*x]
%
else
%define arg(x) [rbp-
8-
8*x]
%endif
%endif
; REG_SZ_BYTES, REG_SZ_BITS
; Size of a register
%
if ABI_IS_32BIT
%define REG_SZ_BYTES
4
%define REG_SZ_BITS
32
%
else
%define REG_SZ_BYTES
8
%define REG_SZ_BITS
64
%endif
; ALIGN_STACK <alignment> <register>
; This macro aligns the stack to the given alignment (in bytes). The stack
; is left such that the previous value of the stack pointer is the first
; argument on the stack (ie, the inverse of this macro is 'pop rsp.')
; This macro uses one temporary register, which is not preserved, and thus
; must be specified as an argument.
%
macro ALIGN_STACK
2
mov %
2, rsp
and rsp, -%
1
lea rsp, [rsp - (%
1 - REG_SZ_BYTES)]
push %
2
%endmacro
;
; The Microsoft assembler tries to impose a certain amount of type safety in
; its register usage. YASM doesn't recognize these directives, so we just
; %define them away to maintain as much compatibility as possible with the
; original inline assembler we're porting from.
;
%idefine PTR
%idefine
XMMWORD
%idefine
MMWORD
; PIC macros
;
%
if ABI_IS_32BIT
%
if CONFIG_PIC=
1
%
ifidn __OUTPUT_FORMAT__,elf32
%define WRT_PLT wrt ..plt
%
macro GET_GOT
1
extern _GLOBAL_OFFSET_TABLE_
push %
1
call %%get_got
%%sub_offset:
jmp %%exitGG
%%get_got:
mov %
1, [
esp]
add %
1, _GLOBAL_OFFSET_TABLE_ + $$ - %%sub_offset wrt ..gotpc
ret
%%exitGG:
%undef GLOBAL
%define GLOBAL(x) x + %
1 wrt ..gotoff
%undef RESTORE_GOT
%define RESTORE_GOT
pop %
1
%endmacro
%elifidn __OUTPUT_FORMAT__,macho32
%
macro GET_GOT
1
push %
1
call %%get_got
%%get_got:
pop %
1
%undef GLOBAL
%define GLOBAL(x) x + %
1 - %%get_got
%undef RESTORE_GOT
%define RESTORE_GOT
pop %
1
%endmacro
%endif
%endif
%
ifdef CHROMIUM
%
ifidn __OUTPUT_FORMAT__,macho32
%define HIDDEN_DATA(x) x:private_extern
%
else
%define HIDDEN_DATA(x) x
%endif
%
else
%define HIDDEN_DATA(x) x
%endif
%
else
%
macro GET_GOT
1
%endmacro
%define GLOBAL(x) rel x
%
ifidn __OUTPUT_FORMAT__,elf64
%define WRT_PLT wrt ..plt
%define HIDDEN_DATA(x) x:
data hidden
%elifidn __OUTPUT_FORMAT__,elfx32
%define WRT_PLT wrt ..plt
%define HIDDEN_DATA(x) x:
data hidden
%elifidn __OUTPUT_FORMAT__,macho64
%
ifdef CHROMIUM
%define HIDDEN_DATA(x) x:private_extern
%
else
%define HIDDEN_DATA(x) x
%endif
%
else
%define HIDDEN_DATA(x) x
%endif
%endif
%ifnmacro GET_GOT
%
macro GET_GOT
1
%endmacro
%define GLOBAL(x) x
%endif
%
ifndef RESTORE_GOT
%define RESTORE_GOT
%endif
%
ifndef WRT_PLT
%define WRT_PLT
%endif
%
if ABI_IS_32BIT
%
macro SHADOW_ARGS_TO_STACK
1
%
endm
%define UNSHADOW_ARGS
%
else
%
if LIBAOM_YASM_WIN64
%
macro SHADOW_ARGS_TO_STACK
1 ; argc
%
if %
1 >
0
mov arg(
0),rcx
%endif
%
if %
1 >
1
mov arg(
1),rdx
%endif
%
if %
1 >
2
mov arg(
2),r8
%endif
%
if %
1 >
3
mov arg(
3),r9
%endif
%
endm
%
else
%
macro SHADOW_ARGS_TO_STACK
1 ; argc
%
if %
1 >
0
push rdi
%endif
%
if %
1 >
1
push rsi
%endif
%
if %
1 >
2
push rdx
%endif
%
if %
1 >
3
push rcx
%endif
%
if %
1 >
4
push r8
%endif
%
if %
1 >
5
push r9
%endif
%
if %
1 >
6
%assign i %
1-
6
%assign off
16
%
rep i
mov rax,[rbp+off]
push rax
%assign off off+
8
%endrep
%endif
%
endm
%endif
%define UNSHADOW_ARGS
mov rsp, rbp
%endif
; Win64 ABI requires that XMM6:XMM15 are callee saved
; SAVE_XMM n, [u]
; store registers 6-n on the stack
; if u is specified, use unaligned movs.
; Win64 ABI requires 16 byte stack alignment, but then pushes an 8 byte return
; value. Typically we follow this up with 'push rbp' - re-aligning the stack -
; but in some cases this is not done and unaligned movs must be used.
%
if LIBAOM_YASM_WIN64
%
macro SAVE_XMM
1-
2 a
%
if %
1 <
6
%error Only xmm registers
6-
15 must be preserved
%
else
%assign last_xmm %
1
%define movxmm movdq %+ %
2
%assign xmm_stack_space ((last_xmm -
5) *
16)
sub rsp, xmm_stack_space
%assign i
6
%
rep (last_xmm -
5)
movxmm [rsp + ((i -
6) *
16)], xmm %+ i
%assign i i+
1
%endrep
%endif
%endmacro
%
macro RESTORE_XMM
0
%
ifndef last_xmm
%error RESTORE_XMM must be paired with SAVE_XMM n
%
else
%assign i last_xmm
%
rep (last_xmm -
5)
movxmm xmm %+ i, [rsp +((i -
6) *
16)]
%assign i i-
1
%endrep
add rsp, xmm_stack_space
; there are a couple functions which return from multiple places.
; otherwise, we could uncomment these:
; %undef last_xmm
; %undef xmm_stack_space
; %undef movxmm
%endif
%endmacro
%
else
%
macro SAVE_XMM
1-
2
%endmacro
%
macro RESTORE_XMM
0
%endmacro
%endif
; Name of the rodata section
;
; .rodata seems to be an elf-ism, as it doesn't work on OSX.
;
%
ifidn __OUTPUT_FORMAT__,macho64
%define SECTION_RODATA section .text
%elifidn __OUTPUT_FORMAT__,macho32
%
macro SECTION_RODATA
0
section .text
%endmacro
%elifidn __OUTPUT_FORMAT__,aout
%define SECTION_RODATA section .
data
%
else
%define SECTION_RODATA section .rodata
%endif
; Tell GNU ld that we don't require an executable stack.
%
ifidn __OUTPUT_FORMAT__,elf32
section .note.GNU-
stack noalloc noexec nowrite progbits
section .text
%elifidn __OUTPUT_FORMAT__,elf64
section .note.GNU-
stack noalloc noexec nowrite progbits
section .text
%elifidn __OUTPUT_FORMAT__,elfx32
section .note.GNU-
stack noalloc noexec nowrite progbits
section .text
%endif