Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | #!/usr/bin/env python |
2 | |||
3 | # (C) Copyright IBM Corporation 2005 |
||
4 | # All Rights Reserved. |
||
5 | # |
||
6 | # Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | # copy of this software and associated documentation files (the "Software"), |
||
8 | # to deal in the Software without restriction, including without limitation |
||
9 | # on the rights to use, copy, modify, merge, publish, distribute, sub |
||
10 | # license, and/or sell copies of the Software, and to permit persons to whom |
||
11 | # the Software is furnished to do so, subject to the following conditions: |
||
12 | # |
||
13 | # The above copyright notice and this permission notice (including the next |
||
14 | # paragraph) shall be included in all copies or substantial portions of the |
||
15 | # Software. |
||
16 | # |
||
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
20 | # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||
23 | # IN THE SOFTWARE. |
||
24 | # |
||
25 | # Authors: |
||
26 | # Ian Romanick |
||
27 | |||
28 | import license |
||
29 | import gl_XML, glX_XML |
||
30 | import sys, getopt, copy |
||
31 | |||
32 | def should_use_push(registers): |
||
33 | for [reg, offset] in registers: |
||
34 | if reg[1:4] == "xmm": |
||
35 | return 0 |
||
36 | |||
37 | N = len(registers) |
||
38 | return (N & 1) != 0 |
||
39 | |||
40 | |||
41 | def local_size(registers): |
||
42 | # The x86-64 ABI says "the value (%rsp - 8) is always a multiple of |
||
43 | # 16 when control is transfered to the function entry point." This |
||
44 | # means that the local stack usage must be (16*N)+8 for some value |
||
45 | # of N. (16*N)+8 = (8*(2N))+8 = 8*(2N+1). As long as N is odd, we |
||
46 | # meet this requirement. |
||
47 | |||
48 | N = (len(registers) | 1) |
||
49 | return 8*N |
||
50 | |||
51 | |||
52 | def save_all_regs(registers): |
||
53 | adjust_stack = 0 |
||
54 | if not should_use_push(registers): |
||
55 | adjust_stack = local_size(registers) |
||
56 | print '\tsubq\t$%u, %%rsp' % (adjust_stack) |
||
57 | |||
58 | for [reg, stack_offset] in registers: |
||
59 | save_reg( reg, stack_offset, adjust_stack ) |
||
60 | return |
||
61 | |||
62 | |||
63 | def restore_all_regs(registers): |
||
64 | adjust_stack = 0 |
||
65 | if not should_use_push(registers): |
||
66 | adjust_stack = local_size(registers) |
||
67 | |||
68 | temp = copy.deepcopy(registers) |
||
69 | while len(temp): |
||
70 | [reg, stack_offset] = temp.pop() |
||
71 | restore_reg(reg, stack_offset, adjust_stack) |
||
72 | |||
73 | if adjust_stack: |
||
74 | print '\taddq\t$%u, %%rsp' % (adjust_stack) |
||
75 | return |
||
76 | |||
77 | |||
78 | def save_reg(reg, offset, use_move): |
||
79 | if use_move: |
||
80 | if offset == 0: |
||
81 | print '\tmovq\t%s, (%%rsp)' % (reg) |
||
82 | else: |
||
83 | print '\tmovq\t%s, %u(%%rsp)' % (reg, offset) |
||
84 | else: |
||
85 | print '\tpushq\t%s' % (reg) |
||
86 | |||
87 | return |
||
88 | |||
89 | |||
90 | def restore_reg(reg, offset, use_move): |
||
91 | if use_move: |
||
92 | if offset == 0: |
||
93 | print '\tmovq\t(%%rsp), %s' % (reg) |
||
94 | else: |
||
95 | print '\tmovq\t%u(%%rsp), %s' % (offset, reg) |
||
96 | else: |
||
97 | print '\tpopq\t%s' % (reg) |
||
98 | |||
99 | return |
||
100 | |||
101 | |||
102 | class PrintGenericStubs(gl_XML.gl_print_base): |
||
103 | |||
104 | def __init__(self): |
||
105 | gl_XML.gl_print_base.__init__(self) |
||
106 | |||
107 | self.name = "gl_x86-64_asm.py (from Mesa)" |
||
108 | self.license = license.bsd_license_template % ("(C) Copyright IBM Corporation 2005", "IBM") |
||
109 | return |
||
110 | |||
111 | |||
112 | def get_stack_size(self, f): |
||
113 | size = 0 |
||
114 | for p in f.parameterIterator(): |
||
115 | size += p.get_stack_size() |
||
116 | |||
117 | return size |
||
118 | |||
119 | |||
120 | def printRealHeader(self): |
||
121 | print "/* If we build with gcc's -fvisibility=hidden flag, we'll need to change" |
||
122 | print " * the symbol visibility mode to 'default'." |
||
123 | print ' */' |
||
124 | print '' |
||
125 | print '#include "x86/assyntax.h"' |
||
126 | print '' |
||
127 | print '#ifdef __GNUC__' |
||
128 | print '# pragma GCC visibility push(default)' |
||
129 | print '# define HIDDEN(x) .hidden x' |
||
130 | print '#else' |
||
131 | print '# define HIDDEN(x)' |
||
132 | print '#endif' |
||
133 | print '' |
||
134 | print '# if defined(USE_MGL_NAMESPACE)' |
||
135 | print '# define GL_PREFIX(n) GLNAME(CONCAT(mgl,n))' |
||
136 | print '# define _glapi_Dispatch _mglapi_Dispatch' |
||
137 | print '# else' |
||
138 | print '# define GL_PREFIX(n) GLNAME(CONCAT(gl,n))' |
||
139 | print '# endif' |
||
140 | print '' |
||
141 | print '#if defined(HAVE_PTHREAD) || defined(_WIN32)' |
||
142 | print '# define THREADS' |
||
143 | print '#endif' |
||
144 | print '' |
||
145 | print '\t.text' |
||
146 | print '' |
||
147 | print '#ifdef GLX_USE_TLS' |
||
148 | print '' |
||
149 | print '\t.globl _x86_64_get_get_dispatch; HIDDEN(_x86_64_get_get_dispatch)' |
||
150 | print '_x86_64_get_get_dispatch:' |
||
151 | print '\tlea\t_x86_64_get_dispatch(%rip), %rax' |
||
152 | print '\tret' |
||
153 | print '' |
||
154 | print '\t.p2align\t4,,15' |
||
155 | print '_x86_64_get_dispatch:' |
||
156 | print '\tmovq\t_glapi_tls_Dispatch@GOTTPOFF(%rip), %rax' |
||
157 | print '\tmovq\t%fs:(%rax), %rax' |
||
158 | print '\tret' |
||
159 | print '\t.size\t_x86_64_get_dispatch, .-_x86_64_get_dispatch' |
||
160 | print '' |
||
161 | print '#elif defined(HAVE_PTHREAD)' |
||
162 | print '' |
||
163 | print '\t.extern\t_glapi_Dispatch' |
||
164 | print '\t.extern\t_gl_DispatchTSD' |
||
165 | print '\t.extern\tpthread_getspecific' |
||
166 | print '' |
||
167 | print '\t.p2align\t4,,15' |
||
168 | print '_x86_64_get_dispatch:' |
||
169 | print '\tmovq\t_gl_DispatchTSD@GOTPCREL(%rip), %rax' |
||
170 | print '\tmovl\t(%rax), %edi' |
||
171 | print '\tjmp\tpthread_getspecific@PLT' |
||
172 | print '' |
||
173 | print '#elif defined(THREADS)' |
||
174 | print '' |
||
175 | print '\t.extern\t_glapi_get_dispatch' |
||
176 | print '' |
||
177 | print '#endif' |
||
178 | print '' |
||
179 | return |
||
180 | |||
181 | |||
182 | def printRealFooter(self): |
||
183 | print '' |
||
184 | print '#if defined (__ELF__) && defined (__linux__)' |
||
185 | print ' .section .note.GNU-stack,"",%progbits' |
||
186 | print '#endif' |
||
187 | return |
||
188 | |||
189 | |||
190 | def printFunction(self, f): |
||
191 | |||
192 | # The x86-64 ABI divides function parameters into a couple |
||
193 | # classes. For the OpenGL interface, the only ones that are |
||
194 | # relevent are INTEGER and SSE. Basically, the first 8 |
||
195 | # GLfloat or GLdouble parameters are placed in %xmm0 - %xmm7, |
||
196 | # the first 6 non-GLfloat / non-GLdouble parameters are placed |
||
197 | # in registers listed in int_parameters. |
||
198 | # |
||
199 | # If more parameters than that are required, they are passed |
||
200 | # on the stack. Therefore, we just have to make sure that |
||
201 | # %esp hasn't changed when we jump to the actual function. |
||
202 | # Since we're jumping to the function (and not calling it), we |
||
203 | # have to make sure of that anyway! |
||
204 | |||
205 | int_parameters = ["%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"] |
||
206 | |||
207 | int_class = 0 |
||
208 | sse_class = 0 |
||
209 | stack_offset = 0 |
||
210 | registers = [] |
||
211 | for p in f.parameterIterator(): |
||
212 | type_name = p.get_base_type_string() |
||
213 | |||
214 | if p.is_pointer() or (type_name != "GLfloat" and type_name != "GLdouble"): |
||
215 | if int_class < 6: |
||
216 | registers.append( [int_parameters[int_class], stack_offset] ) |
||
217 | int_class += 1 |
||
218 | stack_offset += 8 |
||
219 | else: |
||
220 | if sse_class < 8: |
||
221 | registers.append( ["%%xmm%u" % (sse_class), stack_offset] ) |
||
222 | sse_class += 1 |
||
223 | stack_offset += 8 |
||
224 | |||
225 | if ((int_class & 1) == 0) and (sse_class == 0): |
||
226 | registers.append( ["%rbp", 0] ) |
||
227 | |||
228 | |||
229 | name = f.dispatch_name() |
||
230 | |||
231 | print '\t.p2align\t4,,15' |
||
232 | print '\t.globl\tGL_PREFIX(%s)' % (name) |
||
233 | print '\t.type\tGL_PREFIX(%s), @function' % (name) |
||
234 | if not f.is_static_entry_point(f.name): |
||
235 | print '\tHIDDEN(GL_PREFIX(%s))' % (name) |
||
236 | print 'GL_PREFIX(%s):' % (name) |
||
237 | print '#if defined(GLX_USE_TLS)' |
||
238 | print '\tcall\t_x86_64_get_dispatch@PLT' |
||
239 | print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8) |
||
240 | print '\tjmp\t*%r11' |
||
241 | print '#elif defined(HAVE_PTHREAD)' |
||
242 | |||
243 | save_all_regs(registers) |
||
244 | print '\tcall\t_x86_64_get_dispatch@PLT' |
||
245 | restore_all_regs(registers) |
||
246 | |||
247 | if f.offset == 0: |
||
248 | print '\tmovq\t(%rax), %r11' |
||
249 | else: |
||
250 | print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8) |
||
251 | |||
252 | print '\tjmp\t*%r11' |
||
253 | |||
254 | print '#else' |
||
255 | print '\tmovq\t_glapi_Dispatch(%rip), %rax' |
||
256 | print '\ttestq\t%rax, %rax' |
||
257 | print '\tje\t1f' |
||
258 | print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8) |
||
259 | print '\tjmp\t*%r11' |
||
260 | print '1:' |
||
261 | |||
262 | save_all_regs(registers) |
||
263 | print '\tcall\t_glapi_get_dispatch' |
||
264 | restore_all_regs(registers) |
||
265 | |||
266 | print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8) |
||
267 | print '\tjmp\t*%r11' |
||
268 | print '#endif /* defined(GLX_USE_TLS) */' |
||
269 | |||
270 | print '\t.size\tGL_PREFIX(%s), .-GL_PREFIX(%s)' % (name, name) |
||
271 | print '' |
||
272 | return |
||
273 | |||
274 | |||
275 | def printBody(self, api): |
||
276 | for f in api.functionIterateByOffset(): |
||
277 | self.printFunction(f) |
||
278 | |||
279 | |||
280 | for f in api.functionIterateByOffset(): |
||
281 | dispatch = f.dispatch_name() |
||
282 | for n in f.entry_points: |
||
283 | if n != f.name: |
||
284 | if f.is_static_entry_point(n): |
||
285 | text = '\t.globl GL_PREFIX(%s) ; .set GL_PREFIX(%s), GL_PREFIX(%s)' % (n, n, dispatch) |
||
286 | |||
287 | if f.has_different_protocol(n): |
||
288 | print '#ifndef GLX_INDIRECT_RENDERING' |
||
289 | print text |
||
290 | print '#endif' |
||
291 | else: |
||
292 | print text |
||
293 | |||
294 | return |
||
295 | |||
296 | def show_usage(): |
||
297 | print "Usage: %s [-f input_file_name] [-m output_mode]" % sys.argv[0] |
||
298 | sys.exit(1) |
||
299 | |||
300 | if __name__ == '__main__': |
||
301 | file_name = "gl_API.xml" |
||
302 | mode = "generic" |
||
303 | |||
304 | try: |
||
305 | (args, trail) = getopt.getopt(sys.argv[1:], "m:f:") |
||
306 | except Exception,e: |
||
307 | show_usage() |
||
308 | |||
309 | for (arg,val) in args: |
||
310 | if arg == '-m': |
||
311 | mode = val |
||
312 | elif arg == "-f": |
||
313 | file_name = val |
||
314 | |||
315 | if mode == "generic": |
||
316 | printer = PrintGenericStubs() |
||
317 | else: |
||
318 | print "ERROR: Invalid mode \"%s\" specified." % mode |
||
319 | show_usage() |
||
320 | |||
321 | api = gl_XML.parse_GL_API(file_name, glX_XML.glx_item_factory()) |
||
322 | printer.Print(api)>> |