]> git.sesse.net Git - x264/blob - common/x86/x86inc.asm
fix x86_32 ads which failed to preserve a register
[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 WIN64
22 %define ARCH_X86_64
23 %endif
24
25 %ifdef ARCH_X86_64
26 %include "x86inc-64.asm"
27 %else
28 %include "x86inc-32.asm"
29 %endif
30
31 ; Macros to eliminate most code duplication between x86_32 and x86_64:
32 ; Currently this works only for leaf functions which load all their arguments
33 ; into registers at the start, and make no other use of the stack. Luckily that
34 ; covers most of x264's asm.
35
36 ; PROLOGUE:
37 ; %1 = number of arguments. loads them from stack if needed.
38 ; %2 = number of registers used, not including PIC. pushes callee-saved regs if needed.
39 ; %3 = whether global constants are used in this function. inits x86_32 PIC if needed.
40 ; PROLOGUE can also be invoked by adding the same options to cglobal
41
42 ; TODO Some functions can use some args directly from the stack. If they're the
43 ; last args then you can just not declare them, but if they're in the middle
44 ; we need more flexible macro.
45
46 ; RET:
47 ; Pops anything that was pushed by PROLOGUE
48
49 ; REP_RET:
50 ; Same, but if it doesn't pop anything it becomes a 2-byte ret, for athlons
51 ; which are slow when a normal ret follows a branch.
52
53 %macro DECLARE_REG 5
54     %define r%1q %2
55     %define r%1d %3
56     %define r%1w %4
57     ; no r%1b, because some regs don't have a byte form, and anyway x264 doesn't need it
58     %define r%1m %5
59     %define r%1  r%1q
60 %endmacro
61
62 %macro DECLARE_REG_SIZE 1
63     %define r%1q r%1
64     %define e%1q r%1
65     %define r%1d e%1
66     %define e%1d e%1
67     %define r%1w %1
68     %define e%1w %1
69 %ifndef ARCH_X86_64
70     %define r%1  e%1
71 %endif
72 %endmacro
73
74 DECLARE_REG_SIZE ax
75 DECLARE_REG_SIZE bx
76 DECLARE_REG_SIZE cx
77 DECLARE_REG_SIZE dx
78 DECLARE_REG_SIZE si
79 DECLARE_REG_SIZE di
80 DECLARE_REG_SIZE bp
81
82 %ifdef ARCH_X86_64
83     %define push_size 8
84 %else
85     %define push_size 4
86 %endif
87
88 %macro PUSH 1
89     push %1
90     %assign stack_offset stack_offset+push_size
91 %endmacro
92
93 %macro POP 1
94     pop %1
95     %assign stack_offset stack_offset-push_size
96 %endmacro
97
98 %macro SUB 2
99     sub %1, %2
100     %ifidn %1, rsp
101         %assign stack_offset stack_offset+(%2)
102     %endif
103 %endmacro
104
105 %macro ADD 2
106     add %1, %2
107     %ifidn %1, rsp
108         %assign stack_offset stack_offset-(%2)
109     %endif
110 %endmacro
111
112 %macro movifnidn 2
113     %ifnidn %1, %2
114         mov %1, %2
115     %endif
116 %endmacro
117
118 %macro movsxdifnidn 2
119     %ifnidn %1, %2
120         movsxd %1, %2
121     %endif
122 %endmacro
123
124 %macro ASSERT 1
125     %if (%1) == 0
126         %error assert failed
127     %endif
128 %endmacro
129
130 %ifdef WIN64 ;================================================================
131
132 DECLARE_REG 0, rcx, ecx, cx,  ecx
133 DECLARE_REG 1, rdx, edx, dx,  edx
134 DECLARE_REG 2, r8,  r8d, r8w, r8d
135 DECLARE_REG 3, r9,  r9d, r9w, r9d
136 DECLARE_REG 4, rdi, edi, di,  [rsp + stack_offset + 40]
137 DECLARE_REG 5, rsi, esi, si,  [rsp + stack_offset + 48]
138 DECLARE_REG 6, rax, eax, ax,  [rsp + stack_offset + 56]
139 %define r7m [rsp + stack_offset + 64]
140
141 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
142     %if %1 < %2
143         mov r%1, [rsp + 8 + %1*8]
144     %endif
145 %endmacro
146
147 %macro PROLOGUE 3
148     ASSERT %2 >= %1
149     ASSERT %2 <= 7
150     %assign stack_offset 0
151     LOAD_IF_USED 4, %1
152     LOAD_IF_USED 5, %1
153     LOAD_IF_USED 6, %1
154 %endmacro
155
156 %macro RET 0
157     ret
158 %endmacro
159
160 %macro REP_RET 0
161     rep ret
162 %endmacro
163
164 %elifdef ARCH_X86_64 ;========================================================
165
166 DECLARE_REG 0, rdi, edi, di,  edi
167 DECLARE_REG 1, rsi, esi, si,  esi
168 DECLARE_REG 2, rdx, edx, dx,  edx
169 DECLARE_REG 3, rcx, ecx, cx,  ecx
170 DECLARE_REG 4, r8,  r8d, r8w, r8d
171 DECLARE_REG 5, r9,  r9d, r9w, r9d
172 DECLARE_REG 6, rax, eax, ax,  [rsp + stack_offset + 8]
173 %define r7m [rsp + stack_offset + 16]
174
175 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
176     %if %1 < %2
177         mov r%1, [rsp - 40 + %1*8]
178     %endif
179 %endmacro
180
181 %macro PROLOGUE 3
182     ASSERT %2 >= %1
183     ASSERT %2 <= 7
184     %assign stack_offset 0
185     LOAD_IF_USED 6, %1
186 %endmacro
187
188 %macro RET 0
189     ret
190 %endmacro
191
192 %macro REP_RET 0
193     rep ret
194 %endmacro
195
196 %else ; X86_32 ;==============================================================
197
198 DECLARE_REG 0, eax, eax, ax, [esp + stack_offset + 4]
199 DECLARE_REG 1, ecx, ecx, cx, [esp + stack_offset + 8]
200 DECLARE_REG 2, edx, edx, dx, [esp + stack_offset + 12]
201 DECLARE_REG 3, ebx, ebx, bx, [esp + stack_offset + 16]
202 DECLARE_REG 4, esi, esi, si, [esp + stack_offset + 20]
203 DECLARE_REG 5, edi, edi, di, [esp + stack_offset + 24]
204 DECLARE_REG 6, ebp, ebp, bp, [esp + stack_offset + 28]
205 %define r7m [esp + stack_offset + 32]
206 %define rsp esp
207
208 %macro PUSH_IF_USED 1 ; reg_id
209     %if %1 < regs_used
210         push r%1
211         %assign stack_offset stack_offset+4
212     %endif
213 %endmacro
214
215 %macro POP_IF_USED 1 ; reg_id
216     %if %1 < regs_used
217         pop r%1
218     %endif
219 %endmacro
220
221 %macro LOAD_IF_USED 2 ; reg_id, number_of_args
222     %if %1 < %2
223         mov r%1, [esp + stack_offset + 4 + %1*4]
224     %endif
225 %endmacro
226
227 %macro PROLOGUE 3
228     ASSERT %2 >= %1
229     %assign stack_offset 0
230     %assign regs_used %2
231     %ifdef __PIC__
232     %if %3
233         %assign regs_used regs_used+1
234     %endif
235     %endif
236     ASSERT regs_used <= 7
237     PUSH_IF_USED 3
238     PUSH_IF_USED 4
239     PUSH_IF_USED 5
240     PUSH_IF_USED 6
241     LOAD_IF_USED 0, %1
242     LOAD_IF_USED 1, %1
243     LOAD_IF_USED 2, %1
244     LOAD_IF_USED 3, %1
245     LOAD_IF_USED 4, %1
246     LOAD_IF_USED 5, %1
247     LOAD_IF_USED 6, %1
248     %if %3
249         picgetgot r%2
250     %endif
251 %endmacro
252
253 %macro RET 0
254     POP_IF_USED 6
255     POP_IF_USED 5
256     POP_IF_USED 4
257     POP_IF_USED 3
258     ret
259 %endmacro
260
261 %macro REP_RET 0
262     %if regs_used > 3
263         RET
264     %else
265         rep ret
266     %endif
267 %endmacro
268
269 %endif ;======================================================================
270
271
272
273 ;=============================================================================
274 ; arch-independent part
275 ;=============================================================================
276
277 %assign function_align 16
278
279 ; Symbol prefix for C linkage
280 %macro cglobal 1
281     %ifidn __OUTPUT_FORMAT__,elf
282         %ifdef PREFIX
283             global _%1:function hidden
284             %define %1 _%1
285         %else
286             global %1:function hidden
287         %endif
288     %else
289         %ifdef PREFIX
290             global _%1
291             %define %1 _%1
292         %else
293             global %1
294         %endif
295     %endif
296 %ifdef WIN64
297     %define %1 pad %1
298 %endif
299     align function_align
300     %1:
301 %endmacro
302
303 %macro cglobal 3
304     cglobal %1
305     PROLOGUE %2, %3, 0
306 %endmacro
307
308 %macro cglobal 4
309     cglobal %1
310     PROLOGUE %2, %3, %4
311 %endmacro
312
313 %macro cextern 1
314     %ifdef PREFIX
315         extern _%1
316         %define %1 _%1
317     %else
318         extern %1
319     %endif
320 %endmacro
321
322 ; This is needed for ELF, otherwise the GNU linker assumes the stack is
323 ; executable by default.
324 %ifidn __OUTPUT_FORMAT__,elf
325 SECTION ".note.GNU-stack" noalloc noexec nowrite progbits
326 %endif
327
328 %assign FENC_STRIDE 16
329 %assign FDEC_STRIDE 32
330