x86_abi_support.asm 8.93 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
;
2
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
John Koleszar's avatar
John Koleszar committed
3
;
4 5 6 7 8 9 10 11
; 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.
;

John Koleszar's avatar
John Koleszar committed
12 13 14
;


15
%include "aom_config.asm"
John Koleszar's avatar
John Koleszar committed
16 17 18 19 20 21 22 23 24 25 26 27

; 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
KO Myung-Hun's avatar
KO Myung-Hun committed
28 29
%elifidn __OUTPUT_FORMAT__,aout
%define ABI_IS_32BIT 1
John Koleszar's avatar
John Koleszar committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43
%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
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
%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
John Koleszar's avatar
John Koleszar committed
81 82 83
%endif


84 85
; LIBAOM_YASM_WIN64
; Set LIBAOM_YASM_WIN64 if output is Windows 64bit so the code will work if x64
86 87
; or win64 is defined on the Yasm command line.
%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 94
%endif

John Koleszar's avatar
John Koleszar committed
95 96 97 98 99 100 101 102 103 104
; 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.
;
%ifidn   __OUTPUT_FORMAT__,elf32
%define sym(x) x
%elifidn __OUTPUT_FORMAT__,elf64
%define sym(x) x
Mike Frysinger's avatar
Mike Frysinger committed
105 106
%elifidn __OUTPUT_FORMAT__,elfx32
%define sym(x) x
107
%elif LIBAOM_YASM_WIN64
John Koleszar's avatar
John Koleszar committed
108 109 110 111 112
%define sym(x) x
%else
%define sym(x) _ %+ x
%endif

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
;  PRIVATE
;  Macro for the attribute to hide a global symbol for the target ABI.
;  This is only active if CHROMIUM is defined.
;
;  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
;
%ifdef CHROMIUM
  %ifidn   __OUTPUT_FORMAT__,elf32
    %define PRIVATE :hidden
  %elifidn __OUTPUT_FORMAT__,elf64
    %define PRIVATE :hidden
Mike Frysinger's avatar
Mike Frysinger committed
129 130
  %elifidn __OUTPUT_FORMAT__,elfx32
    %define PRIVATE :hidden
131
  %elif LIBAOM_YASM_WIN64
132 133 134 135 136 137 138 139
    %define PRIVATE
  %else
    %define PRIVATE :private_extern
  %endif
%else
  %define PRIVATE
%endif

John Koleszar's avatar
John Koleszar committed
140 141 142 143 144 145 146 147
; 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
148
  %if LIBAOM_YASM_WIN64
John Koleszar's avatar
John Koleszar committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
    %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
175
    lea         rsp, [rsp - (%1 - REG_SZ_BYTES)]
John Koleszar's avatar
John Koleszar committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    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
200 201
      %%sub_offset:
      jmp %%exitGG
John Koleszar's avatar
John Koleszar committed
202
      %%get_got:
203 204 205 206
      mov %1, [esp]
      add %1, _GLOBAL_OFFSET_TABLE_ + $$ - %%sub_offset wrt ..gotpc
      ret
      %%exitGG:
John Koleszar's avatar
John Koleszar committed
207
      %undef GLOBAL
208
      %define GLOBAL(x) x + %1 wrt ..gotoff
John Koleszar's avatar
John Koleszar committed
209 210 211 212 213 214 215 216
      %undef RESTORE_GOT
      %define RESTORE_GOT pop %1
    %endmacro
  %elifidn __OUTPUT_FORMAT__,macho32
    %macro GET_GOT 1
      push %1
      call %%get_got
      %%get_got:
217
      pop  %1
John Koleszar's avatar
John Koleszar committed
218
      %undef GLOBAL
219
      %define GLOBAL(x) x + %1 - %%get_got
John Koleszar's avatar
John Koleszar committed
220 221 222 223 224
      %undef RESTORE_GOT
      %define RESTORE_GOT pop %1
    %endmacro
  %endif
  %endif
225 226 227 228 229 230 231 232 233 234

  %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
John Koleszar's avatar
John Koleszar committed
235 236 237
%else
  %macro GET_GOT 1
  %endmacro
238
  %define GLOBAL(x) rel x
John Koleszar's avatar
John Koleszar committed
239 240
  %ifidn __OUTPUT_FORMAT__,elf64
    %define WRT_PLT wrt ..plt
241
    %define HIDDEN_DATA(x) x:data hidden
Mike Frysinger's avatar
Mike Frysinger committed
242 243 244
  %elifidn __OUTPUT_FORMAT__,elfx32
    %define WRT_PLT wrt ..plt
    %define HIDDEN_DATA(x) x:data hidden
245 246 247 248 249 250
  %elifidn __OUTPUT_FORMAT__,macho64
    %ifdef CHROMIUM
      %define HIDDEN_DATA(x) x:private_extern
    %else
      %define HIDDEN_DATA(x) x
    %endif
251
  %else
252
    %define HIDDEN_DATA(x) x
John Koleszar's avatar
John Koleszar committed
253 254 255 256 257
  %endif
%endif
%ifnmacro GET_GOT
    %macro GET_GOT 1
    %endmacro
258
    %define GLOBAL(x) x
John Koleszar's avatar
John Koleszar committed
259 260 261 262 263 264 265 266 267 268 269 270 271
%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
272
%if LIBAOM_YASM_WIN64
John Koleszar's avatar
John Koleszar committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
  %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
308 309 310 311
      %assign i %1-6
      %assign off 16
      %rep i
        mov rax,[rbp+off]
John Koleszar's avatar
John Koleszar committed
312
        push rax
313 314
        %assign off off+8
      %endrep
John Koleszar's avatar
John Koleszar committed
315 316 317 318 319 320
    %endif
  %endm
%endif
  %define UNSHADOW_ARGS mov rsp, rbp
%endif

321 322 323 324 325 326 327
; 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.
328
%if LIBAOM_YASM_WIN64
329 330 331 332 333 334 335 336 337 338 339 340 341 342
%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
343 344
%endmacro
%macro RESTORE_XMM 0
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
  %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
360 361
%endmacro
%else
362
%macro SAVE_XMM 1-2
363 364 365 366
%endmacro
%macro RESTORE_XMM 0
%endmacro
%endif
John Koleszar's avatar
John Koleszar committed
367 368 369 370 371 372 373 374 375 376 377

; 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
KO Myung-Hun's avatar
KO Myung-Hun committed
378 379
%elifidn __OUTPUT_FORMAT__,aout
%define SECTION_RODATA section .data
John Koleszar's avatar
John Koleszar committed
380 381 382
%else
%define SECTION_RODATA section .rodata
%endif
383 384 385 386 387 388 389 390 391


; 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
Mike Frysinger's avatar
Mike Frysinger committed
392 393 394
%elifidn __OUTPUT_FORMAT__,elfx32
section .note.GNU-stack noalloc noexec nowrite progbits
section .text
395
%endif