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