~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/mesa/glapi/gl_x86-64_asm.py

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 <idr@us.ibm.com>
27
 
 
28
 
import gl_XML, license
29
 
import sys, getopt, copy
30
 
 
31
 
def should_use_push(registers):
32
 
        for [reg, offset] in registers:
33
 
                if reg[1:4] == "xmm":
34
 
                        return 0
35
 
 
36
 
        N = len(registers)
37
 
        return (N & 1) != 0
38
 
 
39
 
 
40
 
def local_size(registers):
41
 
        # The x86-64 ABI says "the value (%rsp - 8) is always a multiple of
42
 
        # 16 when control is transfered to the function entry point."  This
43
 
        # means that the local stack usage must be (16*N)+8 for some value
44
 
        # of N.  (16*N)+8 = (8*(2N))+8 = 8*(2N+1).  As long as N is odd, we
45
 
        # meet this requirement.
46
 
 
47
 
        N = (len(registers) | 1)
48
 
        return 8*N
49
 
 
50
 
 
51
 
def save_all_regs(registers):
52
 
        adjust_stack = 0
53
 
        if not should_use_push(registers):
54
 
                adjust_stack = local_size(registers)
55
 
                print '\tsubq\t$%u, %%rsp' % (adjust_stack)
56
 
 
57
 
        for [reg, stack_offset] in registers:
58
 
                save_reg( reg, stack_offset, adjust_stack )
59
 
        return
60
 
 
61
 
 
62
 
def restore_all_regs(registers):
63
 
        adjust_stack = 0
64
 
        if not should_use_push(registers):
65
 
                adjust_stack = local_size(registers)
66
 
 
67
 
        temp = copy.deepcopy(registers)
68
 
        while len(temp):
69
 
                [reg, stack_offset] = temp.pop()
70
 
                restore_reg(reg, stack_offset, adjust_stack)
71
 
 
72
 
        if adjust_stack:
73
 
                print '\taddq\t$%u, %%rsp' % (adjust_stack)
74
 
        return
75
 
 
76
 
 
77
 
def save_reg(reg, offset, use_move):
78
 
        if use_move:
79
 
                if offset == 0:
80
 
                        print '\tmovq\t%s, (%%rsp)' % (reg)
81
 
                else:
82
 
                        print '\tmovq\t%s, %u(%%rsp)' % (reg, offset)
83
 
        else:
84
 
                print '\tpushq\t%s' % (reg)
85
 
 
86
 
        return
87
 
 
88
 
 
89
 
def restore_reg(reg, offset, use_move):
90
 
        if use_move:
91
 
                if offset == 0:
92
 
                        print '\tmovq\t(%%rsp), %s' % (reg)
93
 
                else:
94
 
                        print '\tmovq\t%u(%%rsp), %s' % (offset, reg)
95
 
        else:
96
 
                print '\tpopq\t%s' % (reg)
97
 
 
98
 
        return
99
 
 
100
 
 
101
 
class PrintGenericStubs(gl_XML.gl_print_base):
102
 
 
103
 
        def __init__(self):
104
 
                gl_XML.gl_print_base.__init__(self)
105
 
 
106
 
                self.name = "gl_x86-64_asm.py (from Mesa)"
107
 
                self.license = license.bsd_license_template % ("(C) Copyright IBM Corporation 2005", "IBM")
108
 
                return
109
 
 
110
 
 
111
 
        def get_stack_size(self, f):
112
 
                size = 0
113
 
                for p in f.parameterIterator():
114
 
                        size += p.get_stack_size()
115
 
 
116
 
                return size
117
 
 
118
 
 
119
 
        def printRealHeader(self):
120
 
                print "/* If we build with gcc's -fvisibility=hidden flag, we'll need to change"
121
 
                print " * the symbol visibility mode to 'default'."
122
 
                print ' */'
123
 
                print ''
124
 
                print '#include "../x86/assyntax.h"'
125
 
                print ''
126
 
                print '#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303'
127
 
                print '#  pragma GCC visibility push(default)'
128
 
                print '#  define HIDDEN(x) .hidden x'
129
 
                print '#else'
130
 
                print '#  define HIDDEN(x)'
131
 
                print '#endif'
132
 
                print ''
133
 
                print '# if defined(USE_MGL_NAMESPACE)'
134
 
                print '#  define GL_PREFIX(n) GLNAME(CONCAT(mgl,n))'
135
 
                print '# else'
136
 
                print '#  define GL_PREFIX(n) GLNAME(CONCAT(gl,n))'
137
 
                print '# endif'
138
 
                print ''
139
 
                print '#if defined(PTHREADS) || defined(USE_XTHREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS)'
140
 
                print '#  define THREADS'
141
 
                print '#endif'
142
 
                print ''
143
 
                print '\t.text'
144
 
                print ''
145
 
                print '#ifdef GLX_USE_TLS'
146
 
                print ''
147
 
                print '\t.globl _x86_64_get_get_dispatch; HIDDEN(_x86_64_get_get_dispatch)'
148
 
                print '_x86_64_get_get_dispatch:'
149
 
                print '\tlea\t_x86_64_get_dispatch(%rip), %rax'
150
 
                print '\tret'
151
 
                print ''
152
 
                print '\t.p2align\t4,,15'
153
 
                print '_x86_64_get_dispatch:'
154
 
                print '\tmovq\t_glapi_tls_Dispatch@GOTTPOFF(%rip), %rax'
155
 
                print '\tmovq\t%fs:(%rax), %rax'
156
 
                print '\tret'
157
 
                print '\t.size\t_x86_64_get_dispatch, .-_x86_64_get_dispatch'
158
 
                print ''
159
 
                print '#elif defined(PTHREADS)'
160
 
                print ''
161
 
                print '\t.extern\t_glapi_Dispatch'
162
 
                print '\t.extern\t_gl_DispatchTSD'
163
 
                print '\t.extern\tpthread_getspecific'
164
 
                print ''
165
 
                print '\t.p2align\t4,,15'
166
 
                print '_x86_64_get_dispatch:'
167
 
                print '\tmovq\t_gl_DispatchTSD(%rip), %rdi'
168
 
                print '\tjmp\tpthread_getspecific@PLT'
169
 
                print ''
170
 
                print '#elif defined(THREADS)'
171
 
                print ''
172
 
                print '\t.extern\t_glapi_get_dispatch'
173
 
                print ''
174
 
                print '#endif'
175
 
                print ''
176
 
                return
177
 
 
178
 
 
179
 
        def printRealFooter(self):
180
 
                print ''
181
 
                print '#if defined(GLX_USE_TLS) && defined(__linux__)'
182
 
                print ' .section ".note.ABI-tag", "a"'
183
 
                print ' .p2align 2'
184
 
                print ' .long   1f - 0f   /* name length */'
185
 
                print ' .long   3f - 2f   /* data length */'
186
 
                print ' .long   1         /* note length */'
187
 
                print '0:       .asciz "GNU"      /* vendor name */'
188
 
                print '1:       .p2align 2'
189
 
                print '2:       .long   0         /* note data: the ABI tag */'
190
 
                print ' .long   2,4,20    /* Minimum kernel version w/TLS */'
191
 
                print '3:       .p2align 2        /* pad out section */'
192
 
                print '#endif /* GLX_USE_TLS */'
193
 
                print ''
194
 
                print '#if defined (__ELF__) && defined (__linux__)'
195
 
                print ' .section .note.GNU-stack,"",%progbits'
196
 
                print '#endif'
197
 
                return
198
 
 
199
 
 
200
 
        def printFunction(self, f):
201
 
                
202
 
                # The x86-64 ABI divides function parameters into a couple
203
 
                # classes.  For the OpenGL interface, the only ones that are
204
 
                # relevent are INTEGER and SSE.  Basically, the first 8
205
 
                # GLfloat or GLdouble parameters are placed in %xmm0 - %xmm7,
206
 
                # the first 6 non-GLfloat / non-GLdouble parameters are placed
207
 
                # in registers listed in int_parameters.
208
 
                #
209
 
                # If more parameters than that are required, they are passed
210
 
                # on the stack.  Therefore, we just have to make sure that
211
 
                # %esp hasn't changed when we jump to the actual function.
212
 
                # Since we're jumping to the function (and not calling it), we
213
 
                # have to make sure of that anyway!
214
 
 
215
 
                int_parameters = ["%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"]
216
 
 
217
 
                int_class = 0
218
 
                sse_class = 0
219
 
                stack_offset = 0
220
 
                registers = []
221
 
                for p in f.parameterIterator():
222
 
                        type_name = p.get_base_type_string()
223
 
 
224
 
                        if p.is_pointer() or (type_name != "GLfloat" and type_name != "GLdouble"):
225
 
                                if int_class < 6:
226
 
                                        registers.append( [int_parameters[int_class], stack_offset] )
227
 
                                        int_class += 1
228
 
                                        stack_offset += 8
229
 
                        else:
230
 
                                if sse_class < 8:
231
 
                                        registers.append( ["%%xmm%u" % (sse_class), stack_offset] )
232
 
                                        sse_class += 1
233
 
                                        stack_offset += 8
234
 
 
235
 
                if ((int_class & 1) == 0) and (sse_class == 0):
236
 
                        registers.append( ["%rbp", 0] )
237
 
 
238
 
 
239
 
                print '\t.p2align\t4,,15'
240
 
                print '\t.globl\tGL_PREFIX(%s)' % (f.name)
241
 
                print '\t.type\tGL_PREFIX(%s), @function' % (f.name)
242
 
                print 'GL_PREFIX(%s):' % (f.name)
243
 
                print '#if defined(GLX_USE_TLS)'
244
 
                print '\tcall\t_x86_64_get_dispatch@PLT'
245
 
                print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8)
246
 
                print '\tjmp\t*%r11'
247
 
                print '#elif defined(PTHREADS)'
248
 
                
249
 
                save_all_regs(registers)
250
 
                print '\tcall\t_x86_64_get_dispatch@PLT'
251
 
                restore_all_regs(registers)
252
 
 
253
 
                if f.offset == 0:
254
 
                        print '\tmovq\t(%rax), %r11'
255
 
                else:
256
 
                        print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8)
257
 
 
258
 
                print '\tjmp\t*%r11'
259
 
 
260
 
                print '#else'
261
 
                print '\tmovq\t_glapi_Dispatch(%rip), %rax'
262
 
                print '\ttestq\t%rax, %rax'
263
 
                print '\tje\t1f'
264
 
                print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8)
265
 
                print '\tjmp\t*%r11'
266
 
                print '1:'
267
 
 
268
 
                save_all_regs(registers)
269
 
                print '\tcall\t_glapi_get_dispatch'
270
 
                restore_all_regs(registers)
271
 
 
272
 
                print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8)
273
 
                print '\tjmp\t*%r11'
274
 
                print '#endif /* defined(GLX_USE_TLS) */'
275
 
 
276
 
                print '\t.size\tGL_PREFIX(%s), .-GL_PREFIX(%s)' % (f.name, f.name)
277
 
                print ''
278
 
                return
279
 
 
280
 
 
281
 
        def printBody(self, api):
282
 
                for f in api.functionIterateByOffset():
283
 
                        self.printFunction(f)
284
 
 
285
 
 
286
 
                for f in api.functionIterateByOffset():
287
 
                        for n in f.entry_points:
288
 
                                if n != f.name:
289
 
                                        print '\t.globl GL_PREFIX(%s) ; .set GL_PREFIX(%s), GL_PREFIX(%s)' % (n, n, f.name)
290
 
 
291
 
                return
292
 
 
293
 
def show_usage():
294
 
        print "Usage: %s [-f input_file_name] [-m output_mode]" % sys.argv[0]
295
 
        sys.exit(1)
296
 
 
297
 
if __name__ == '__main__':
298
 
        file_name = "gl_API.xml"
299
 
        mode = "generic"
300
 
 
301
 
        try:
302
 
                (args, trail) = getopt.getopt(sys.argv[1:], "m:f:")
303
 
        except Exception,e:
304
 
                show_usage()
305
 
 
306
 
        for (arg,val) in args:
307
 
                if arg == '-m':
308
 
                        mode = val
309
 
                elif arg == "-f":
310
 
                        file_name = val
311
 
 
312
 
        if mode == "generic":
313
 
                printer = PrintGenericStubs()
314
 
        else:
315
 
                print "ERROR: Invalid mode \"%s\" specified." % mode
316
 
                show_usage()
317
 
 
318
 
        api = gl_XML.parse_GL_API( file_name )
319
 
 
320
 
        printer.Print( api )