]> git.sesse.net Git - x264/blob - common/x86/x86inc.asm
Update file headers throughout x264
[x264] / common / x86 / x86inc.asm
1 ;*****************************************************************************
2 ;* x86inc.asm
3 ;*****************************************************************************
4 ;* Copyright (C) 2008 Loren Merritt <lorenm@u.washington.edu>
5 ;*
6 ;* This program is free software; you can redistribute it and/or modify
7 ;* it under the terms of the GNU General Public License as published by
8 ;* the Free Software Foundation; either version 2 of the License, or
9 ;* (at your option) any later version.
10 ;*
11 ;* This program is distributed in the hope that it will be useful,
12 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;* GNU General Public License for more details.
15 ;*
16 ;* You should have received a copy of the GNU General Public License
17 ;* along with this program; if not, write to the Free Software
18 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
19 ;*****************************************************************************
20
21 %ifdef ARCH_X86_64
22 %include "x86inc-64.asm"
23 %else
24 %include "x86inc-32.asm"
25 %endif
26
27 ; Macros to eliminate most code duplication between x86_32 and x86_64:
28 ; Currently this works only for leaf functions which load all their arguments
29 ; into registers at the start, and make no other use of the stack. Luckily that
30 ; covers most of x264's asm.
31
32 ; PROLOGUE:
33 ; %1 = number of arguments. loads them from stack if needed.
34 ; %2 = number of registers used, not including PIC. pushes callee-saved regs if needed.
35 ; %3 = whether global constants are used in this function. inits x86_32 PIC if needed.
36 ; PROLOGUE can also be invoked by adding the same options to cglobal
37
38 ; TODO Some functions can use some args directly from the stack. If they're the
39 ; last args then you can just not declare them, but if they're in the middle
40 ; we need more flexible macro.
41
42 ; RET:
43 ; Pops anything that was pushed by PROLOGUE
44
45 ; REP_RET:
46 ; Same, but if it doesn't pop anything it becomes a 2-byte ret, for athlons
47 ; which are slow when a normal ret follows a branch.
48
49 %macro DECLARE_REG 6
50     %define r%1q %2
51     %define r%1d %3
52     %define r%1w %4
53     %define r%1b %5
54     %define r%1m %6
55     %define r%1  %2
56 %endmacro
57
58 %macro DECLARE_REG_SIZE 2
59     %define r%1q r%1
60     %define e%1q r%1
61     %define r%1d e%1
62     %define e%1d e%1
63     %define r%1w %1
64     %define e%1w %1
65     %define r%1b %2
66     %define e%1b %2
67 %ifndef ARCH_X86_64
68     %define r%1  e%1
69 %endif
70 %endmacro
71
72 DECLARE_REG_SIZE ax, al
73 DECLARE_REG_SIZE bx, bl
74 DECLARE_REG_SIZE cx, cl
75 DECLARE_REG_SIZE dx, dl
76 DECLARE_REG_SIZE si, sil
77 DECLARE_REG_SIZE di, dil
78 DECLARE_REG_SIZE bp, bpl
79
80 %ifdef ARCH_X86_64
81     %define push_size 8
82 %else
83     %define push_size 4
84 %endif
85
86 %macro PUSH 1
87     push %1
88     %assign stack_offset stack_offset+push_size
89 %endmacro
90
91 %macro POP 1
92     pop %1
93     %assign stack_offset stack_offset-push_size
94 %endmacro
95
96 %macro SUB 2
97     sub %1, %2
98     %ifidn %1, rsp
99         %assign stack_offset stack_offset+(%2)
100     %endif
101 %endmacro
102
103 %macro ADD 2
104     add %1, %2
105     %ifidn %1, rsp
106         %assign stack_offset stack_offset-(%2)
107     %endif
108 %endmacro
109
110 %macro movifnidn 2
111     %ifnidn %1, %2
112         mov %1, %2
113     %endif
114 %endmacro
115
116 %macro movsxdifnidn 2
117     %ifnidn %1, %2
118         movsxd %1, %2
119     %endif
120 %endmacro
121
122 %macro ASSERT 1
123     %if (%1) == 0
124         %error assert failed
125     %endif
126 %endmacro
127
128 %ifdef ARCH_X86_64 ;========================================================
129
130 DECLARE_REG 0, rdi, edi, di,  dil, edi
131 DECLARE_REG 1, rsi, esi, si,  sil, esi
132 DECLARE_REG 2, rdx, edx, dx,  dl,  edx
133 DECLARE_REG 3, rcx, ecx, cx,  cl,  ecx
134 DECLARE_REG 4, r8,  r8d, r8w, r8b, r8d
135 DECLARE_REG 5, r9,  r9d, r9w, r9b, r9d
136 DECLARE_REG 6, rax, eax, ax,  al,  [rsp + stack_offset + 8]
137 %define r7m [rsp + stack_offset + 16]
138 %define r8m [rsp + stack_offset + 24]
139
140 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
141     %if %1 < %2
142         mov r%1, [rsp - 40 + %1*8]
143     %endif
144 %endmacro
145
146 %macro PROLOGUE 3
147     ASSERT %2 >= %1
148     ASSERT %2 <= 7
149     %assign stack_offset 0
150     LOAD_IF_USED 6, %1
151 %endmacro
152
153 %macro RET 0
154     ret
155 %endmacro
156
157 %macro REP_RET 0
158     rep ret
159 %endmacro
160
161 %else ; X86_32 ;==============================================================
162
163 DECLARE_REG 0, eax, eax, ax, al,   [esp + stack_offset + 4]
164 DECLARE_REG 1, ecx, ecx, cx, cl,   [esp + stack_offset + 8]
165 DECLARE_REG 2, edx, edx, dx, dl,   [esp + stack_offset + 12]
166 DECLARE_REG 3, ebx, ebx, bx, bl,   [esp + stack_offset + 16]
167 DECLARE_REG 4, esi, esi, si, null, [esp + stack_offset + 20]
168 DECLARE_REG 5, edi, edi, di, null, [esp + stack_offset + 24]
169 DECLARE_REG 6, ebp, ebp, bp, null, [esp + stack_offset + 28]
170 %define r7m [esp + stack_offset + 32]
171 %define r8m [esp + stack_offset + 36]
172 %define rsp esp
173
174 %macro PUSH_IF_USED 1 ; reg_id
175     %if %1 < regs_used
176         push r%1
177         %assign stack_offset stack_offset+4
178     %endif
179 %endmacro
180
181 %macro POP_IF_USED 1 ; reg_id
182     %if %1 < regs_used
183         pop r%1
184     %endif
185 %endmacro
186
187 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
188     %if %1 < %2
189         mov r%1, [esp + stack_offset + 4 + %1*4]
190     %endif
191 %endmacro
192
193 %macro PROLOGUE 3
194     ASSERT %2 >= %1
195     %assign stack_offset 0
196     %assign regs_used %2
197     %ifdef __PIC__
198     %if %3
199         %assign regs_used regs_used+1
200     %endif
201     %endif
202     ASSERT regs_used <= 7
203     PUSH_IF_USED 3
204     PUSH_IF_USED 4
205     PUSH_IF_USED 5
206     PUSH_IF_USED 6
207     LOAD_IF_USED 0, %1
208     LOAD_IF_USED 1, %1
209     LOAD_IF_USED 2, %1
210     LOAD_IF_USED 3, %1
211     LOAD_IF_USED 4, %1
212     LOAD_IF_USED 5, %1
213     LOAD_IF_USED 6, %1
214     %if %3
215         picgetgot r%2
216     %endif
217 %endmacro
218
219 %macro RET 0
220     POP_IF_USED 6
221     POP_IF_USED 5
222     POP_IF_USED 4
223     POP_IF_USED 3
224     ret
225 %endmacro
226
227 %macro REP_RET 0
228     %if regs_used > 3
229         RET
230     %else
231         rep ret
232     %endif
233 %endmacro
234
235 %endif ;======================================================================
236
237
238
239 ;=============================================================================
240 ; arch-independent part
241 ;=============================================================================
242
243 %assign function_align 16
244
245 ; Symbol prefix for C linkage
246 %macro cglobal 1
247     %ifidn __OUTPUT_FORMAT__,elf
248         %ifdef PREFIX
249             global _%1:function hidden
250             %define %1 _%1
251         %else
252             global %1:function hidden
253         %endif
254     %else
255         %ifdef PREFIX
256             global _%1
257             %define %1 _%1
258         %else
259             global %1
260         %endif
261     %endif
262     align function_align
263     %1:
264     RESET_MM_PERMUTATION ; not really needed, but makes disassembly somewhat nicer
265 %endmacro
266
267 %macro cglobal 3
268     cglobal %1
269     PROLOGUE %2, %3, 0
270 %endmacro
271
272 %macro cglobal 4
273     cglobal %1
274     PROLOGUE %2, %3, %4
275 %endmacro
276
277 %macro cextern 1
278     %ifdef PREFIX
279         extern _%1
280         %define %1 _%1
281     %else
282         extern %1
283     %endif
284 %endmacro
285
286 ; This is needed for ELF, otherwise the GNU linker assumes the stack is
287 ; executable by default.
288 %ifidn __OUTPUT_FORMAT__,elf
289 SECTION .note.GNU-stack noalloc noexec nowrite progbits
290 %endif
291
292 %assign FENC_STRIDE 16
293 %assign FDEC_STRIDE 32
294
295 ; merge mmx and sse*
296
297 %macro CAT_DEFINE 3
298     %define %1%2 %3
299 %endmacro
300
301 %macro CAT_XDEFINE 3
302     %xdefine %1%2 %3
303 %endmacro
304
305 %macro CAT_UNDEF 2
306     %undef %1%2
307 %endmacro
308
309 %macro INIT_MMX 0
310     %define RESET_MM_PERMUTATION INIT_MMX
311     %define regsize 8
312     %define num_mmregs 8
313     %define mova movq
314     %define movu movq
315     %define movh movd
316     %define movnt movntq
317     %assign %%i 0
318     %rep 8
319     CAT_DEFINE m, %%i, mm %+ %%i
320     CAT_DEFINE nmm, %%i, %%i
321     %assign %%i %%i+1
322     %endrep
323     %rep 8
324     CAT_UNDEF m, %%i
325     CAT_UNDEF nmm, %%i
326     %assign %%i %%i+1
327     %endrep
328 %endmacro
329
330 %macro INIT_XMM 0
331     %define RESET_MM_PERMUTATION INIT_XMM
332     %define regsize 16
333     %define num_mmregs 8
334     %ifdef ARCH_X86_64
335     %define num_mmregs 16
336     %endif
337     %define mova movdqa
338     %define movu movdqu
339     %define movh movq
340     %define movnt movntdq
341     %assign %%i 0
342     %rep num_mmregs
343     CAT_DEFINE m, %%i, xmm %+ %%i
344     CAT_DEFINE nxmm, %%i, %%i
345     %assign %%i %%i+1
346     %endrep
347 %endmacro
348
349 INIT_MMX
350
351 ; I often want to use macros that permute their arguments. e.g. there's no
352 ; efficient way to implement butterfly or transpose or dct without swapping some
353 ; arguments.
354 ;
355 ; I would like to not have to manually keep track of the permutations:
356 ; If I insert a permutation in the middle of a function, it should automatically
357 ; change everything that follows. For more complex macros I may also have multiple
358 ; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations.
359 ;
360 ; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that
361 ; permutes its arguments. It's equivalent to exchanging the contents of the
362 ; registers, except that this way you exchange the register names instead, so it
363 ; doesn't cost any cycles.
364
365 %macro PERMUTE 2-* ; takes a list of pairs to swap
366 %rep %0/2
367     %xdefine tmp%2 m%2
368     %xdefine ntmp%2 nm%2
369     %rotate 2
370 %endrep
371 %rep %0/2
372     %xdefine m%1 tmp%2
373     %xdefine nm%1 ntmp%2
374     %undef tmp%2
375     %undef ntmp%2
376     %rotate 2
377 %endrep
378 %endmacro
379
380 %macro SWAP 2-* ; swaps a single chain (sometimes more concise than pairs)
381 %rep %0-1
382 %ifdef m%1
383     %xdefine tmp m%1
384     %xdefine m%1 m%2
385     %xdefine m%2 tmp
386     CAT_XDEFINE n, m%1, %1
387     CAT_XDEFINE n, m%2, %2
388 %else
389     ; If we were called as "SWAP m0,m1" rather than "SWAP 0,1" infer the original numbers here.
390     ; Be careful using the mode in nested macros though, as in some cases there may be
391     ; other copies of m# that have already been dereferenced and don't get updated correctly.
392     %xdefine %%n1 n %+ %1
393     %xdefine %%n2 n %+ %2
394     %xdefine tmp m %+ %%n1
395     CAT_XDEFINE m, %%n1, m %+ %%n2
396     CAT_XDEFINE m, %%n2, tmp
397     CAT_XDEFINE n, m %+ %%n1, %%n1
398     CAT_XDEFINE n, m %+ %%n2, %%n2
399 %endif
400     %undef tmp
401     %rotate 1
402 %endrep
403 %endmacro
404
405 %macro SAVE_MM_PERMUTATION 1
406     %assign %%i 0
407     %rep num_mmregs
408     CAT_XDEFINE %1_m, %%i, m %+ %%i
409     %assign %%i %%i+1
410     %endrep
411 %endmacro
412
413 %macro LOAD_MM_PERMUTATION 1
414     %assign %%i 0
415     %rep num_mmregs
416     CAT_XDEFINE m, %%i, %1_m %+ %%i
417     %assign %%i %%i+1
418     %endrep
419 %endmacro
420
421 %macro call 1
422     call %1
423     %ifdef %1_m0
424         LOAD_MM_PERMUTATION %1
425     %endif
426 %endmacro
427
428 ; substitutions which are functionally identical but reduce code size
429 %define movdqa movaps
430 %define movdqu movups
431