282 lines
6.9 KiB
NASM
282 lines
6.9 KiB
NASM
;*****************************************************************************
|
|
;* amd64inc.asm: h264 encoder library
|
|
;*****************************************************************************
|
|
;* Copyright (C) 2005 x264 project
|
|
;*
|
|
;* Authors: Andrew Dunstan
|
|
;*
|
|
;* This program is CC_free software; you can redistribute it and/or modify
|
|
;* it under the terms of the GNU General Public License as published by
|
|
;* the Free Software Foundation; either version 2 of the License, or
|
|
;* (at your option) any later version.
|
|
;*
|
|
;* This program is distributed in the hope that it will be useful,
|
|
;* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;* GNU General Public License for more details.
|
|
;*
|
|
;* You should have received a copy of the GNU General Public License
|
|
;* along with this program; if not, write to the Free Software
|
|
;* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
|
;*****************************************************************************
|
|
|
|
BITS 64
|
|
|
|
; FIXME: All of the 64bit asm functions that take a stride as an argument
|
|
; via register, assume that the high dword of that register is filled with 0.
|
|
; This is true in practice (since we never do any 64bit arithmetic on strides),
|
|
; but is not guaranteed by the ABI.
|
|
|
|
%macro cglobal 1
|
|
%ifdef PREFIX
|
|
global _%1
|
|
%define %1 _%1
|
|
%else
|
|
global %1
|
|
%endif
|
|
%ifdef WIN64
|
|
%define %1 pad %1
|
|
%endif
|
|
%endmacro
|
|
|
|
%macro pad 1
|
|
%undef %1
|
|
%ifdef PREFIX
|
|
%define %1 _%1
|
|
%endif
|
|
%ifdef WIN64
|
|
times 6 nop
|
|
align 16
|
|
%1
|
|
.startfunc
|
|
%assign unwindcount 0
|
|
%assign framereg 0
|
|
%else
|
|
align 16
|
|
%1
|
|
%endif
|
|
%endmacro
|
|
|
|
%ifdef WIN64
|
|
|
|
%define __PIC__
|
|
|
|
%define parm1q rcx
|
|
%define parm2q rdx
|
|
%define parm3q r8
|
|
%define parm4q r9
|
|
%define parm5q [rsp+40]
|
|
%define parm6q [rsp+48]
|
|
%define parm7q [rsp+56]
|
|
%define parm8q [rsp+64]
|
|
%define parm1d ecx
|
|
%define parm2d edx
|
|
%define parm3d r8d
|
|
%define parm4d r9d
|
|
%define parm5d dword parm5q
|
|
%define parm6d dword parm6q
|
|
%define parm7d dword parm7q
|
|
%define parm8d dword parm8q
|
|
|
|
%macro firstpush 1
|
|
db 0x48
|
|
push %1
|
|
%endmacro
|
|
|
|
%define unwindcode(count, code) .unwind %+ count EQU code
|
|
|
|
%define regcoderax 0
|
|
%define regcodercx 1
|
|
%define regcoderdx 2
|
|
%define regcoderbx 3
|
|
%define regcodersp 4
|
|
%define regcoderbp 5
|
|
%define regcodersi 6
|
|
%define regcoderdi 7
|
|
%define regcoder8 8
|
|
%define regcoder9 9
|
|
%define regcoder10 10
|
|
%define regcoder11 11
|
|
%define regcoder12 12
|
|
%define regcoder13 13
|
|
%define regcoder14 14
|
|
%define regcoder15 15
|
|
%define regcodexmm0 0
|
|
%define regcodexmm1 1
|
|
%define regcodexmm2 2
|
|
%define regcodexmm3 3
|
|
%define regcodexmm4 4
|
|
%define regcodexmm5 5
|
|
%define regcodexmm6 6
|
|
%define regcodexmm7 7
|
|
%define regcodexmm8 8
|
|
%define regcodexmm9 9
|
|
%define regcodexmm10 10
|
|
%define regcodexmm11 11
|
|
%define regcodexmm12 12
|
|
%define regcodexmm13 13
|
|
%define regcodexmm14 14
|
|
%define regcodexmm15 15
|
|
|
|
%macro allocstack 1
|
|
%if %1 < 8
|
|
%error Stack Allocation must be at least 8 bytes.
|
|
%elif %1 < 129
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, $-.startfunc + 0x200 + (((%1-8)/8)<<12))
|
|
%elif %1 < 524288
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %1/8)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, $-.startfunc + 0x100)
|
|
%else
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %1>>16)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %1 & 0x0000FFFF)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, $-.startfunc + 0x1100)
|
|
%endif
|
|
%endmacro
|
|
|
|
%macro pushreg 1
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, $-.startfunc + 0 + (regcode%1 << 12))
|
|
%endmacro
|
|
|
|
%macro setframe 2
|
|
%if ((%2 % 16) | (%2 > 240) | (%2 < 0))
|
|
%error Frame offset must be a multiple of 16 between 0 and 240.
|
|
%endif
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, $-.startfunc + (3 << 8 )+ (regcode%1 << 12))
|
|
%assign framereg regcode%1 + %2
|
|
%endmacro
|
|
|
|
%macro savereg 2
|
|
%if ((%2 % 8) | (%2 < 0))
|
|
%error Offset must be a positive multiple of 8.
|
|
%endif
|
|
%if (%2 < 64504)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %2/8)
|
|
%assign unwindcount unwindcount +1
|
|
unwindcode(unwindcount, $-.startfunc + (4 << 8) + (regcode%1 << 12))
|
|
%else
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %2 >> 16)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %2 & 0x0000FFFF)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, $-.startfunc + (5 << 8) + (regcode%1 << 12))
|
|
%endif
|
|
%endmacro
|
|
|
|
%macro savexmm128 2
|
|
%if ((%2 % 16) | (%2 < 0))
|
|
%error Offset must be a positive multiple of 16.
|
|
%endif
|
|
%if (%2 < 64512)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %2/16)
|
|
%assign unwindcount unwindcount +1
|
|
unwindcode(unwindcount, $-.startfunc + (8 << 8) + (regcode%1 << 12))
|
|
%else
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %2 >> 16)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, %2 & 0x0000FFFF)
|
|
%assign unwindcount unwindcount+1
|
|
unwindcode(unwindcount, $-.startfunc + (9 << 8) + (regcode%1 << 12))
|
|
%endif
|
|
%endmacro
|
|
|
|
%macro endprolog 0
|
|
.endprolog
|
|
SECTION .xdata
|
|
.unwindinfo
|
|
db 0x01
|
|
db .endprolog-.startfunc
|
|
db unwindcount
|
|
db framereg
|
|
%rep unwindcount
|
|
dw .unwind %+ unwindcount
|
|
%assign unwindcount unwindcount-1
|
|
%endrep
|
|
align 4,db 0
|
|
SECTION .text
|
|
%endmacro
|
|
|
|
%macro endfunc 0
|
|
.endfunc
|
|
SECTION .pdata
|
|
dd .startfunc
|
|
dd .endfunc
|
|
dd .unwindinfo
|
|
SECTION .text
|
|
%endmacro
|
|
|
|
%else ;linux
|
|
%define parm1q rdi
|
|
%define parm2q rsi
|
|
%define parm3q rdx
|
|
%define parm4q rcx
|
|
%define parm5q r8
|
|
%define parm6q r9
|
|
%define parm7q [rsp+8]
|
|
%define parm8q [rsp+16]
|
|
%define parm1d edi
|
|
%define parm2d esi
|
|
%define parm3d edx
|
|
%define parm4d ecx
|
|
%define parm5d r8d
|
|
%define parm6d r9d
|
|
%define parm7d dword parm7q
|
|
%define parm8d dword parm8q
|
|
|
|
%macro allocstack 1
|
|
%endmacro
|
|
|
|
%macro firstpush 1
|
|
push %1
|
|
%endmacro
|
|
|
|
%macro pushreg 1
|
|
%endmacro
|
|
|
|
%macro setframe 2
|
|
%endmacro
|
|
|
|
%macro savereg 2
|
|
%endmacro
|
|
|
|
%macro savexmm128 2
|
|
%endmacro
|
|
|
|
%define endprolog
|
|
%define endfunc
|
|
|
|
%endif ;linux
|
|
|
|
; PIC support macros. On x86_64 we just use RIP-relative addressing, which is
|
|
; much simpler than the GOT handling we need to perform on x86.
|
|
;
|
|
; - GLOBAL should be used as a suffix for global addressing, eg.
|
|
; mov eax, [foo GLOBAL]
|
|
; instead of
|
|
; mov eax, [foo]
|
|
;
|
|
%ifdef __PIC__
|
|
%define GLOBAL wrt rip
|
|
%else
|
|
%define GLOBAL
|
|
%endif
|
|
|
|
%assign FENC_STRIDE 16
|
|
%assign FDEC_STRIDE 32
|
|
|
|
; This is needed for ELF, otherwise the GNU linker assumes the stack is
|
|
; executable by default.
|
|
%ifidn __YASM_OBJFMT__,elf
|
|
section ".note.GNU-stack" noalloc noexec nowrite progbits
|
|
%endif
|