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