]> git.sesse.net Git - x264/blob - common/x86/x86inc.asm
e52d542f830aa249e02a6ef933f9581818d853f9
[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., 59 Temple Place - Suite 330, 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 INIT_MMX 0
298     %define RESET_MM_PERMUTATION INIT_MMX
299     %define regsize 8
300     %define mova movq
301     %define movu movq
302     %define movh movd
303     %define movnt movntq
304     %define m0 mm0
305     %define m1 mm1
306     %define m2 mm2
307     %define m3 mm3
308     %define m4 mm4
309     %define m5 mm5
310     %define m6 mm6
311     %define m7 mm7
312     %undef  m8
313     %undef  m9
314     %undef  m10
315     %undef  m11
316     %undef  m12
317     %undef  m13
318     %undef  m14
319     %undef  m15
320 %endmacro
321
322 %macro INIT_XMM 0
323     %define RESET_MM_PERMUTATION INIT_XMM
324     %define regsize 16
325     %define mova movdqa
326     %define movu movdqu
327     %define movh movq
328     %define movnt movntdq
329     %define m0 xmm0
330     %define m1 xmm1
331     %define m2 xmm2
332     %define m3 xmm3
333     %define m4 xmm4
334     %define m5 xmm5
335     %define m6 xmm6
336     %define m7 xmm7
337     %ifdef ARCH_X86_64
338     %define m8 xmm8
339     %define m9 xmm9
340     %define m10 xmm10
341     %define m11 xmm11
342     %define m12 xmm12
343     %define m13 xmm13
344     %define m14 xmm14
345     %define m15 xmm15
346     %endif
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     %rotate 2
369 %endrep
370 %rep %0/2
371     %xdefine m%1 tmp%2
372     %undef tmp%2
373     %rotate 2
374 %endrep
375 %endmacro
376
377 %macro SWAP 2-* ; swaps a single chain (sometimes more concise than pairs)
378 %rep %0-1
379     %xdefine tmp m%1
380     %xdefine m%1 m%2
381     %xdefine m%2 tmp
382     %undef tmp
383     %rotate 1
384 %endrep
385 %endmacro
386
387 %macro SAVE_MM_PERMUTATION 1
388     %xdefine %1_m0 m0
389     %xdefine %1_m1 m1
390     %xdefine %1_m2 m2
391     %xdefine %1_m3 m3
392     %xdefine %1_m4 m4
393     %xdefine %1_m5 m5
394     %xdefine %1_m6 m6
395     %xdefine %1_m7 m7
396     %ifdef ARCH_X86_64
397     %xdefine %1_m8 m8
398     %xdefine %1_m9 m9
399     %xdefine %1_m10 m10
400     %xdefine %1_m11 m11
401     %xdefine %1_m12 m12
402     %xdefine %1_m13 m13
403     %xdefine %1_m14 m14
404     %xdefine %1_m15 m15
405     %endif
406 %endmacro
407
408 %macro LOAD_MM_PERMUTATION 1
409     %xdefine m0 %1_m0
410     %xdefine m1 %1_m1
411     %xdefine m2 %1_m2
412     %xdefine m3 %1_m3
413     %xdefine m4 %1_m4
414     %xdefine m5 %1_m5
415     %xdefine m6 %1_m6
416     %xdefine m7 %1_m7
417     %ifdef ARCH_X86_64
418     %xdefine m8 %1_m8
419     %xdefine m9 %1_m9
420     %xdefine m10 %1_m10
421     %xdefine m11 %1_m11
422     %xdefine m12 %1_m12
423     %xdefine m13 %1_m13
424     %xdefine m14 %1_m14
425     %xdefine m15 %1_m15
426     %endif
427 %endmacro
428
429 %macro call 1
430     call %1
431     %ifdef %1_m0
432         LOAD_MM_PERMUTATION %1
433     %endif
434 %endmacro
435
436 ; substitutions which are functionally identical but reduce code size
437 %define movdqa movaps
438 %define movdqu movups
439