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