]> git.sesse.net Git - x264/blob - common/x86/x86inc.asm
Slightly faster ssse3 width4 chroma MC
[x264] / common / x86 / x86inc.asm
1 ;*****************************************************************************
2 ;* x86inc.asm
3 ;*****************************************************************************
4 ;* Copyright (C) 2005-2008 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Anton Mitrofanov <BugMaster@narod.ru>
8 ;*
9 ;* Permission to use, copy, modify, and/or distribute this software for any
10 ;* purpose with or without fee is hereby granted, provided that the above
11 ;* copyright notice and this permission notice appear in all copies.
12 ;*
13 ;* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 ;* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 ;* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 ;* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 ;* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 ;* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 ;*****************************************************************************
21
22 ; This is a header file for the x264ASM assembly language, which uses
23 ; NASM/YASM syntax combined with a large number of macros to provide easy
24 ; abstraction between different calling conventions (x86_32, win64, linux64).
25 ; It also has various other useful features to simplify writing the kind of
26 ; DSP functions that are most often used in x264.
27
28 ; Unlike the rest of x264, this file is available under an ISC license, as it
29 ; has significant usefulness outside of x264 and we want it to be available
30 ; to the largest audience possible.  Of course, if you modify it for your own
31 ; purposes to add a new feature, we strongly encourage contributing a patch
32 ; as this feature might be useful for others as well.  Send patches or ideas
33 ; to x264-devel@videolan.org .
34
35 %ifdef ARCH_X86_64
36     %ifidn __OUTPUT_FORMAT__,win32
37         %define WIN64
38     %else
39         %define UNIX64
40     %endif
41 %endif
42
43 ; FIXME: All of the 64bit asm functions that take a stride as an argument
44 ; via register, assume that the high dword of that register is filled with 0.
45 ; This is true in practice (since we never do any 64bit arithmetic on strides,
46 ; and x264's strides are all positive), but is not guaranteed by the ABI.
47
48 ; Name of the .rodata section.
49 ; Kludge: Something on OS X fails to align .rodata even given an align attribute,
50 ; so use a different read-only section.
51 %macro SECTION_RODATA 0-1 16
52     %ifidn __OUTPUT_FORMAT__,macho64
53         SECTION .text align=%1
54     %elifidn __OUTPUT_FORMAT__,macho
55         SECTION .text align=%1
56         fakegot:
57     %else
58         SECTION .rodata align=%1
59     %endif
60 %endmacro
61
62 ; PIC support macros.
63 ; x86_64 can't fit 64bit address literals in most instruction types,
64 ; so shared objects (under the assumption that they might be anywhere
65 ; in memory) must use an address mode that does fit.
66 ; So all accesses to global variables must use this macro, e.g.
67 ;     mov eax, [foo GLOBAL]
68 ; instead of
69 ;     mov eax, [foo]
70 ;
71 ; x86_32 doesn't require PIC.
72 ; Some distros prefer shared objects to be PIC, but nothing breaks if
73 ; the code contains a few textrels, so we'll skip that complexity.
74
75 %ifdef WIN64
76     %define PIC
77 %elifndef ARCH_X86_64
78     %undef PIC
79 %endif
80 %ifdef PIC
81     %define GLOBAL wrt rip
82 %else
83     %define GLOBAL
84 %endif
85
86 ; Macros to eliminate most code duplication between x86_32 and x86_64:
87 ; Currently this works only for leaf functions which load all their arguments
88 ; into registers at the start, and make no other use of the stack. Luckily that
89 ; covers most of x264's asm.
90
91 ; PROLOGUE:
92 ; %1 = number of arguments. loads them from stack if needed.
93 ; %2 = number of registers used. pushes callee-saved regs if needed.
94 ; %3 = number of xmm registers used. pushes callee-saved xmm regs if needed.
95 ; %4 = list of names to define to registers
96 ; PROLOGUE can also be invoked by adding the same options to cglobal
97
98 ; e.g.
99 ; cglobal foo, 2,3,0, dst, src, tmp
100 ; declares a function (foo), taking two args (dst and src) and one local variable (tmp)
101
102 ; TODO Some functions can use some args directly from the stack. If they're the
103 ; last args then you can just not declare them, but if they're in the middle
104 ; we need more flexible macro.
105
106 ; RET:
107 ; Pops anything that was pushed by PROLOGUE
108
109 ; REP_RET:
110 ; Same, but if it doesn't pop anything it becomes a 2-byte ret, for athlons
111 ; which are slow when a normal ret follows a branch.
112
113 ; registers:
114 ; rN and rNq are the native-size register holding function argument N
115 ; rNd, rNw, rNb are dword, word, and byte size
116 ; rNm is the original location of arg N (a register or on the stack), dword
117 ; rNmp is native size
118
119 %macro DECLARE_REG 6
120     %define r%1q %2
121     %define r%1d %3
122     %define r%1w %4
123     %define r%1b %5
124     %define r%1m %6
125     %ifid %6 ; i.e. it's a register
126         %define r%1mp %2
127     %elifdef ARCH_X86_64 ; memory
128         %define r%1mp qword %6
129     %else
130         %define r%1mp dword %6
131     %endif
132     %define r%1  %2
133 %endmacro
134
135 %macro DECLARE_REG_SIZE 2
136     %define r%1q r%1
137     %define e%1q r%1
138     %define r%1d e%1
139     %define e%1d e%1
140     %define r%1w %1
141     %define e%1w %1
142     %define r%1b %2
143     %define e%1b %2
144 %ifndef ARCH_X86_64
145     %define r%1  e%1
146 %endif
147 %endmacro
148
149 DECLARE_REG_SIZE ax, al
150 DECLARE_REG_SIZE bx, bl
151 DECLARE_REG_SIZE cx, cl
152 DECLARE_REG_SIZE dx, dl
153 DECLARE_REG_SIZE si, sil
154 DECLARE_REG_SIZE di, dil
155 DECLARE_REG_SIZE bp, bpl
156
157 ; t# defines for when per-arch register allocation is more complex than just function arguments
158
159 %macro DECLARE_REG_TMP 1-*
160     %assign %%i 0
161     %rep %0
162         CAT_XDEFINE t, %%i, r%1
163         %assign %%i %%i+1
164         %rotate 1
165     %endrep
166 %endmacro
167
168 %macro DECLARE_REG_TMP_SIZE 0-*
169     %rep %0
170         %define t%1q t%1 %+ q
171         %define t%1d t%1 %+ d
172         %define t%1w t%1 %+ w
173         %define t%1b t%1 %+ b
174         %rotate 1
175     %endrep
176 %endmacro
177
178 DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7
179
180 %ifdef ARCH_X86_64
181     %define gprsize 8
182 %else
183     %define gprsize 4
184 %endif
185
186 %macro PUSH 1
187     push %1
188     %assign stack_offset stack_offset+gprsize
189 %endmacro
190
191 %macro POP 1
192     pop %1
193     %assign stack_offset stack_offset-gprsize
194 %endmacro
195
196 %macro SUB 2
197     sub %1, %2
198     %ifidn %1, rsp
199         %assign stack_offset stack_offset+(%2)
200     %endif
201 %endmacro
202
203 %macro ADD 2
204     add %1, %2
205     %ifidn %1, rsp
206         %assign stack_offset stack_offset-(%2)
207     %endif
208 %endmacro
209
210 %macro movifnidn 2
211     %ifnidn %1, %2
212         mov %1, %2
213     %endif
214 %endmacro
215
216 %macro movsxdifnidn 2
217     %ifnidn %1, %2
218         movsxd %1, %2
219     %endif
220 %endmacro
221
222 %macro ASSERT 1
223     %if (%1) == 0
224         %error assert failed
225     %endif
226 %endmacro
227
228 %macro DEFINE_ARGS 0-*
229     %ifdef n_arg_names
230         %assign %%i 0
231         %rep n_arg_names
232             CAT_UNDEF arg_name %+ %%i, q
233             CAT_UNDEF arg_name %+ %%i, d
234             CAT_UNDEF arg_name %+ %%i, w
235             CAT_UNDEF arg_name %+ %%i, b
236             CAT_UNDEF arg_name %+ %%i, m
237             CAT_UNDEF arg_name, %%i
238             %assign %%i %%i+1
239         %endrep
240     %endif
241
242     %assign %%i 0
243     %rep %0
244         %xdefine %1q r %+ %%i %+ q
245         %xdefine %1d r %+ %%i %+ d
246         %xdefine %1w r %+ %%i %+ w
247         %xdefine %1b r %+ %%i %+ b
248         %xdefine %1m r %+ %%i %+ m
249         CAT_XDEFINE arg_name, %%i, %1
250         %assign %%i %%i+1
251         %rotate 1
252     %endrep
253     %assign n_arg_names %%i
254 %endmacro
255
256 %ifdef WIN64 ; Windows x64 ;=================================================
257
258 DECLARE_REG 0, rcx, ecx, cx,  cl,  ecx
259 DECLARE_REG 1, rdx, edx, dx,  dl,  edx
260 DECLARE_REG 2, r8,  r8d, r8w, r8b, r8d
261 DECLARE_REG 3, r9,  r9d, r9w, r9b, r9d
262 DECLARE_REG 4, rdi, edi, di,  dil, [rsp + stack_offset + 40]
263 DECLARE_REG 5, rsi, esi, si,  sil, [rsp + stack_offset + 48]
264 DECLARE_REG 6, rax, eax, ax,  al,  [rsp + stack_offset + 56]
265 %define r7m [rsp + stack_offset + 64]
266 %define r8m [rsp + stack_offset + 72]
267
268 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
269     %if %1 < %2
270         mov r%1, [rsp + stack_offset + 8 + %1*8]
271     %endif
272 %endmacro
273
274 %macro PROLOGUE 2-4+ ; #args, #regs, #xmm_regs, arg_names...
275     ASSERT %2 >= %1
276     %assign regs_used %2
277     ASSERT regs_used <= 7
278     %if %0 > 2
279         %assign xmm_regs_used %3
280     %else
281         %assign xmm_regs_used 0
282     %endif
283     ASSERT xmm_regs_used <= 16
284     %if regs_used > 4
285         push r4
286         push r5
287         %assign stack_offset stack_offset+16
288     %endif
289     %if xmm_regs_used > 6
290         sub rsp, (xmm_regs_used-6)*16+16
291         %assign stack_offset stack_offset+(xmm_regs_used-6)*16+16
292         %assign %%i xmm_regs_used
293         %rep (xmm_regs_used-6)
294             %assign %%i %%i-1
295             movdqa [rsp + (%%i-6)*16+8], xmm %+ %%i
296         %endrep
297     %endif
298     LOAD_IF_USED 4, %1
299     LOAD_IF_USED 5, %1
300     LOAD_IF_USED 6, %1
301     DEFINE_ARGS %4
302 %endmacro
303
304 %macro RESTORE_XMM_INTERNAL 1
305     %if xmm_regs_used > 6
306         %assign %%i xmm_regs_used
307         %rep (xmm_regs_used-6)
308             %assign %%i %%i-1
309             movdqa xmm %+ %%i, [%1 + (%%i-6)*16+8]
310         %endrep
311         add %1, (xmm_regs_used-6)*16+16
312     %endif
313 %endmacro
314
315 %macro RESTORE_XMM 1
316     RESTORE_XMM_INTERNAL %1
317     %assign stack_offset stack_offset-(xmm_regs_used-6)*16+16
318     %assign xmm_regs_used 0
319 %endmacro
320
321 %macro RET 0
322     RESTORE_XMM_INTERNAL rsp
323     %if regs_used > 4
324         pop r5
325         pop r4
326     %endif
327     ret
328 %endmacro
329
330 %macro REP_RET 0
331     %if regs_used > 4 || xmm_regs_used > 6
332         RET
333     %else
334         rep ret
335     %endif
336 %endmacro
337
338 %elifdef ARCH_X86_64 ; *nix x64 ;=============================================
339
340 DECLARE_REG 0, rdi, edi, di,  dil, edi
341 DECLARE_REG 1, rsi, esi, si,  sil, esi
342 DECLARE_REG 2, rdx, edx, dx,  dl,  edx
343 DECLARE_REG 3, rcx, ecx, cx,  cl,  ecx
344 DECLARE_REG 4, r8,  r8d, r8w, r8b, r8d
345 DECLARE_REG 5, r9,  r9d, r9w, r9b, r9d
346 DECLARE_REG 6, rax, eax, ax,  al,  [rsp + stack_offset + 8]
347 %define r7m [rsp + stack_offset + 16]
348 %define r8m [rsp + stack_offset + 24]
349
350 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
351     %if %1 < %2
352         mov r%1, [rsp - 40 + %1*8]
353     %endif
354 %endmacro
355
356 %macro PROLOGUE 2-4+ ; #args, #regs, #xmm_regs, arg_names...
357     ASSERT %2 >= %1
358     ASSERT %2 <= 7
359     LOAD_IF_USED 6, %1
360     DEFINE_ARGS %4
361 %endmacro
362
363 %macro RET 0
364     ret
365 %endmacro
366
367 %macro REP_RET 0
368     rep ret
369 %endmacro
370
371 %else ; X86_32 ;==============================================================
372
373 DECLARE_REG 0, eax, eax, ax, al,   [esp + stack_offset + 4]
374 DECLARE_REG 1, ecx, ecx, cx, cl,   [esp + stack_offset + 8]
375 DECLARE_REG 2, edx, edx, dx, dl,   [esp + stack_offset + 12]
376 DECLARE_REG 3, ebx, ebx, bx, bl,   [esp + stack_offset + 16]
377 DECLARE_REG 4, esi, esi, si, null, [esp + stack_offset + 20]
378 DECLARE_REG 5, edi, edi, di, null, [esp + stack_offset + 24]
379 DECLARE_REG 6, ebp, ebp, bp, null, [esp + stack_offset + 28]
380 %define r7m [esp + stack_offset + 32]
381 %define r8m [esp + stack_offset + 36]
382 %define rsp esp
383
384 %macro PUSH_IF_USED 1 ; reg_id
385     %if %1 < regs_used
386         push r%1
387         %assign stack_offset stack_offset+4
388     %endif
389 %endmacro
390
391 %macro POP_IF_USED 1 ; reg_id
392     %if %1 < regs_used
393         pop r%1
394     %endif
395 %endmacro
396
397 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
398     %if %1 < %2
399         mov r%1, [esp + stack_offset + 4 + %1*4]
400     %endif
401 %endmacro
402
403 %macro PROLOGUE 2-4+ ; #args, #regs, #xmm_regs, arg_names...
404     ASSERT %2 >= %1
405     %assign regs_used %2
406     ASSERT regs_used <= 7
407     PUSH_IF_USED 3
408     PUSH_IF_USED 4
409     PUSH_IF_USED 5
410     PUSH_IF_USED 6
411     LOAD_IF_USED 0, %1
412     LOAD_IF_USED 1, %1
413     LOAD_IF_USED 2, %1
414     LOAD_IF_USED 3, %1
415     LOAD_IF_USED 4, %1
416     LOAD_IF_USED 5, %1
417     LOAD_IF_USED 6, %1
418     DEFINE_ARGS %4
419 %endmacro
420
421 %macro RET 0
422     POP_IF_USED 6
423     POP_IF_USED 5
424     POP_IF_USED 4
425     POP_IF_USED 3
426     ret
427 %endmacro
428
429 %macro REP_RET 0
430     %if regs_used > 3
431         RET
432     %else
433         rep ret
434     %endif
435 %endmacro
436
437 %endif ;======================================================================
438
439
440
441 ;=============================================================================
442 ; arch-independent part
443 ;=============================================================================
444
445 %assign function_align 16
446
447 ; Symbol prefix for C linkage
448 %macro cglobal 1-2+
449     %ifdef PREFIX
450         %xdefine %1 _ %+ %1
451     %endif
452     %xdefine %1.skip_prologue %1 %+ .skip_prologue
453     %ifidn __OUTPUT_FORMAT__,elf
454         global %1:function hidden
455     %else
456         global %1
457     %endif
458     align function_align
459     %1:
460     RESET_MM_PERMUTATION ; not really needed, but makes disassembly somewhat nicer
461     %assign stack_offset 0
462     %if %0 > 1
463         PROLOGUE %2
464     %endif
465 %endmacro
466
467 %macro cextern 1
468     %ifdef PREFIX
469         %xdefine %1 _%1
470     %endif
471     extern %1
472 %endmacro
473
474 ; This is needed for ELF, otherwise the GNU linker assumes the stack is
475 ; executable by default.
476 %ifidn __OUTPUT_FORMAT__,elf
477 SECTION .note.GNU-stack noalloc noexec nowrite progbits
478 %endif
479
480 ; merge mmx and sse*
481
482 %macro CAT_XDEFINE 3
483     %xdefine %1%2 %3
484 %endmacro
485
486 %macro CAT_UNDEF 2
487     %undef %1%2
488 %endmacro
489
490 %macro INIT_MMX 0
491     %define RESET_MM_PERMUTATION INIT_MMX
492     %define mmsize 8
493     %define num_mmregs 8
494     %define mova movq
495     %define movu movq
496     %define movh movd
497     %define movnt movntq
498     %assign %%i 0
499     %rep 8
500     CAT_XDEFINE m, %%i, mm %+ %%i
501     CAT_XDEFINE nmm, %%i, %%i
502     %assign %%i %%i+1
503     %endrep
504     %rep 8
505     CAT_UNDEF m, %%i
506     CAT_UNDEF nmm, %%i
507     %assign %%i %%i+1
508     %endrep
509 %endmacro
510
511 %macro INIT_XMM 0
512     %define RESET_MM_PERMUTATION INIT_XMM
513     %define mmsize 16
514     %define num_mmregs 8
515     %ifdef ARCH_X86_64
516     %define num_mmregs 16
517     %endif
518     %define mova movdqa
519     %define movu movdqu
520     %define movh movq
521     %define movnt movntdq
522     %assign %%i 0
523     %rep num_mmregs
524     CAT_XDEFINE m, %%i, xmm %+ %%i
525     CAT_XDEFINE nxmm, %%i, %%i
526     %assign %%i %%i+1
527     %endrep
528 %endmacro
529
530 INIT_MMX
531
532 ; I often want to use macros that permute their arguments. e.g. there's no
533 ; efficient way to implement butterfly or transpose or dct without swapping some
534 ; arguments.
535 ;
536 ; I would like to not have to manually keep track of the permutations:
537 ; If I insert a permutation in the middle of a function, it should automatically
538 ; change everything that follows. For more complex macros I may also have multiple
539 ; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations.
540 ;
541 ; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that
542 ; permutes its arguments. It's equivalent to exchanging the contents of the
543 ; registers, except that this way you exchange the register names instead, so it
544 ; doesn't cost any cycles.
545
546 %macro PERMUTE 2-* ; takes a list of pairs to swap
547 %rep %0/2
548     %xdefine tmp%2 m%2
549     %xdefine ntmp%2 nm%2
550     %rotate 2
551 %endrep
552 %rep %0/2
553     %xdefine m%1 tmp%2
554     %xdefine nm%1 ntmp%2
555     %undef tmp%2
556     %undef ntmp%2
557     %rotate 2
558 %endrep
559 %endmacro
560
561 %macro SWAP 2-* ; swaps a single chain (sometimes more concise than pairs)
562 %rep %0-1
563 %ifdef m%1
564     %xdefine tmp m%1
565     %xdefine m%1 m%2
566     %xdefine m%2 tmp
567     CAT_XDEFINE n, m%1, %1
568     CAT_XDEFINE n, m%2, %2
569 %else
570     ; If we were called as "SWAP m0,m1" rather than "SWAP 0,1" infer the original numbers here.
571     ; Be careful using this mode in nested macros though, as in some cases there may be
572     ; other copies of m# that have already been dereferenced and don't get updated correctly.
573     %xdefine %%n1 n %+ %1
574     %xdefine %%n2 n %+ %2
575     %xdefine tmp m %+ %%n1
576     CAT_XDEFINE m, %%n1, m %+ %%n2
577     CAT_XDEFINE m, %%n2, tmp
578     CAT_XDEFINE n, m %+ %%n1, %%n1
579     CAT_XDEFINE n, m %+ %%n2, %%n2
580 %endif
581     %undef tmp
582     %rotate 1
583 %endrep
584 %endmacro
585
586 ; If SAVE_MM_PERMUTATION is placed at the end of a function and given the
587 ; function name, then any later calls to that function will automatically
588 ; load the permutation, so values can be returned in mmregs.
589 %macro SAVE_MM_PERMUTATION 1 ; name to save as
590     %assign %%i 0
591     %rep num_mmregs
592     CAT_XDEFINE %1_m, %%i, m %+ %%i
593     %assign %%i %%i+1
594     %endrep
595 %endmacro
596
597 %macro LOAD_MM_PERMUTATION 1 ; name to load from
598     %assign %%i 0
599     %rep num_mmregs
600     CAT_XDEFINE m, %%i, %1_m %+ %%i
601     CAT_XDEFINE n, m %+ %%i, %%i
602     %assign %%i %%i+1
603     %endrep
604 %endmacro
605
606 %macro call 1
607     call %1
608     %ifdef %1_m0
609         LOAD_MM_PERMUTATION %1
610     %endif
611 %endmacro
612
613 ; Substitutions that reduce instruction size but are functionally equivalent
614 %macro add 2
615     %ifnum %2
616         %if %2==128
617             sub %1, -128
618         %else
619             add %1, %2
620         %endif
621     %else
622         add %1, %2
623     %endif
624 %endmacro
625
626 %macro sub 2
627     %ifnum %2
628         %if %2==128
629             add %1, -128
630         %else
631             sub %1, %2
632         %endif
633     %else
634         sub %1, %2
635     %endif
636 %endmacro