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