1/*
2 * Mesa 3-D graphics library
3 * Version:  6.3
4 *
5 * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/*
26 * Check extended CPU capabilities.  Now justs returns the raw CPUID
27 * feature information, allowing the higher level code to interpret the
28 * results.
29 *
30 * Written by Holger Waechtler <holger@akaflieg.extern.tu-berlin.de>
31 *
32 * Cleaned up and simplified by Gareth Hughes <gareth@valinux.com>
33 *
34 */
35
36/*
37 * NOTE: Avoid using spaces in between '(' ')' and arguments, especially
38 * with macros like CONST, LLBL that expand to CONCAT(...).  Putting spaces
39 * in there will break the build on some platforms.
40 */
41
42#include "matypes.h"
43#include "assyntax.h"
44#include "common_x86_features.h"
45
46	SEG_TEXT
47
48ALIGNTEXT4
49GLOBL GLNAME(_mesa_x86_has_cpuid)
50HIDDEN(_mesa_x86_has_cpuid)
51GLNAME(_mesa_x86_has_cpuid):
52
53	/* Test for the CPUID command.  If the ID Flag bit in EFLAGS
54	 * (bit 21) is writable, the CPUID command is present */
55	PUSHF_L
56	POP_L	(EAX)
57	MOV_L	(EAX, ECX)
58	XOR_L	(CONST(0x00200000), EAX)
59	PUSH_L	(EAX)
60	POPF_L
61	PUSHF_L
62	POP_L	(EAX)
63
64	/* Verify the ID Flag bit has been written. */
65	CMP_L	(ECX, EAX)
66	SETNE	(AL)
67	XOR_L	(CONST(0xff), EAX)
68
69	RET
70
71
72ALIGNTEXT4
73GLOBL GLNAME(_mesa_x86_cpuid)
74HIDDEN(_mesa_x86_cpuid)
75GLNAME(_mesa_x86_cpuid):
76
77	MOV_L	(REGOFF(4, ESP), EAX)		/* cpuid op */
78	PUSH_L	(EDI)
79	PUSH_L	(EBX)
80
81	CPUID
82
83	MOV_L	(REGOFF(16, ESP), EDI)	/* *eax */
84	MOV_L	(EAX, REGIND(EDI))
85	MOV_L	(REGOFF(20, ESP), EDI)	/* *ebx */
86	MOV_L	(EBX, REGIND(EDI))
87	MOV_L	(REGOFF(24, ESP), EDI)	/* *ecx */
88	MOV_L	(ECX, REGIND(EDI))
89	MOV_L	(REGOFF(28, ESP), EDI)	/* *edx */
90	MOV_L	(EDX, REGIND(EDI))
91
92	POP_L	(EBX)
93	POP_L	(EDI)
94	RET
95
96ALIGNTEXT4
97GLOBL GLNAME(_mesa_x86_cpuid_eax)
98HIDDEN(_mesa_x86_cpuid_eax)
99GLNAME(_mesa_x86_cpuid_eax):
100
101	MOV_L	(REGOFF(4, ESP), EAX)		/* cpuid op */
102	PUSH_L	(EBX)
103
104	CPUID
105
106	POP_L	(EBX)
107	RET
108
109ALIGNTEXT4
110GLOBL GLNAME(_mesa_x86_cpuid_ebx)
111HIDDEN(_mesa_x86_cpuid_ebx)
112GLNAME(_mesa_x86_cpuid_ebx):
113
114	MOV_L	(REGOFF(4, ESP), EAX)		/* cpuid op */
115	PUSH_L	(EBX)
116
117	CPUID
118	MOV_L	(EBX, EAX)			/* return EBX */
119
120	POP_L	(EBX)
121	RET
122
123ALIGNTEXT4
124GLOBL GLNAME(_mesa_x86_cpuid_ecx)
125HIDDEN(_mesa_x86_cpuid_ecx)
126GLNAME(_mesa_x86_cpuid_ecx):
127
128	MOV_L	(REGOFF(4, ESP), EAX)		/* cpuid op */
129	PUSH_L	(EBX)
130
131	CPUID
132	MOV_L	(ECX, EAX)			/* return ECX */
133
134	POP_L	(EBX)
135	RET
136
137ALIGNTEXT4
138GLOBL GLNAME(_mesa_x86_cpuid_edx)
139HIDDEN(_mesa_x86_cpuid_edx)
140GLNAME(_mesa_x86_cpuid_edx):
141
142	MOV_L	(REGOFF(4, ESP), EAX)		/* cpuid op */
143	PUSH_L	(EBX)
144
145	CPUID
146	MOV_L	(EDX, EAX)			/* return EDX */
147
148	POP_L	(EBX)
149	RET
150
151#ifdef USE_SSE_ASM
152/* Execute an SSE instruction to see if the operating system correctly
153 * supports SSE.  A signal handler for SIGILL should have been set
154 * before calling this function, otherwise this could kill the client
155 * application.
156 *
157 *        -----> !!!! ATTENTION DEVELOPERS !!!! <-----
158 *
159 * If you're debugging with gdb and you get stopped in this function,
160 * just type 'continue'!  Execution will proceed normally.
161 * See freedesktop.org bug #1709 for more info.
162 */
163ALIGNTEXT4
164GLOBL GLNAME( _mesa_test_os_sse_support )
165HIDDEN(_mesa_test_os_sse_support)
166GLNAME( _mesa_test_os_sse_support ):
167
168	XORPS	( XMM0, XMM0 )
169
170	RET
171
172
173/* Perform an SSE divide-by-zero to see if the operating system
174 * correctly supports unmasked SIMD FPU exceptions.  Signal handlers for
175 * SIGILL and SIGFPE should have been set before calling this function,
176 * otherwise this could kill the client application.
177 */
178ALIGNTEXT4
179GLOBL GLNAME( _mesa_test_os_sse_exception_support )
180HIDDEN(_mesa_test_os_sse_exception_support)
181GLNAME( _mesa_test_os_sse_exception_support ):
182
183	PUSH_L	( EBP )
184	MOV_L	( ESP, EBP )
185	SUB_L	( CONST( 8 ), ESP )
186
187	/* Save the original MXCSR register value.
188	 */
189	STMXCSR	( REGOFF( -4, EBP ) )
190
191	/* Unmask the divide-by-zero exception and perform one.
192	 */
193	STMXCSR	( REGOFF( -8, EBP ) )
194	AND_L	( CONST( 0xfffffdff ), REGOFF( -8, EBP ) )
195	LDMXCSR	( REGOFF( -8, EBP ) )
196
197	XORPS	( XMM0, XMM0 )
198
199	PUSH_L	( CONST( 0x3f800000 ) )
200	PUSH_L	( CONST( 0x3f800000 ) )
201	PUSH_L	( CONST( 0x3f800000 ) )
202	PUSH_L	( CONST( 0x3f800000 ) )
203
204	MOVUPS	( REGIND( ESP ), XMM1 )
205
206	DIVPS	( XMM0, XMM1 )
207
208	/* Restore the original MXCSR register value.
209	 */
210	LDMXCSR	( REGOFF( -4, EBP ) )
211
212	LEAVE
213	RET
214
215#endif
216
217
218#if defined (__ELF__) && defined (__linux__)
219	.section .note.GNU-stack,"",%progbits
220#endif
221