@@ -159,31 +159,37 @@ fn test_bit(x: usize, bit: u32) -> bool {
159
159
/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
160
160
/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf
161
161
fn detect_features ( ) -> usize {
162
- let extended_features_ebx;
163
- let proc_info_ecx;
164
- let proc_info_edx;
162
+ use super :: x86:: { cpuid, has_cpuid, CpuidResult } ;
163
+ let mut value: usize = 0 ;
165
164
166
- unsafe {
167
- /// To obtain all feature flags we need two CPUID queries:
165
+ // If the x86 CPU does not support the CPUID instruction then it is too
166
+ // old to support all currently-detectable features.
167
+ if !has_cpuid ( ) {
168
+ return value;
169
+ }
168
170
169
- /// 1. EAX=1, ECX=0: Queries "Processor Info and Feature Bits"
170
- /// This gives us most of the CPU features in ECX and EDX (see
171
- /// below).
172
- asm ! ( "cpuid"
173
- : "={ecx}" ( proc_info_ecx) , "={edx}" ( proc_info_edx)
174
- : "{eax}" ( 0x0000_0001_u32 ) , "{ecx}" ( 0 as u32 )
175
- : : ) ;
171
+ // Calling `cpuid` from here on is safe because the CPU has the `cpuid`
172
+ // instruction.
176
173
177
- /// 2. EAX=7, ECX=0: Queries "Extended Features"
178
- /// This gives us information about bmi,bmi2, and avx2 support
179
- /// (see below); the result in ECX is not currently needed.
180
- asm ! ( "cpuid"
181
- : "={ebx}" ( extended_features_ebx)
182
- : "{eax}" ( 0x0000_0007_u32 ) , "{ecx}" ( 0 as u32 )
183
- : : ) ;
184
- }
174
+ // 1. EAX=1, ECX=0: Queries "Processor Info and Feature Bits";
175
+ // Contains information about most x86 features.
176
+ let CpuidResult {
177
+ ecx : proc_info_ecx,
178
+ edx : proc_info_edx,
179
+ ..
180
+ } = unsafe { cpuid ( 0x0000_0001_u32 , 0 ) } ;
185
181
186
- let mut value: usize = 0 ;
182
+ // 2. EAX=7, ECX=0: Queries "Extended Features";
183
+ // Contains information about bmi,bmi2, and avx2 support.
184
+ let CpuidResult {
185
+ ebx : extended_features_ebx,
186
+ ..
187
+ } = unsafe { cpuid ( 0x0000_0007_u32 , 0 ) } ;
188
+
189
+ let proc_info_ecx = proc_info_ecx as usize ;
190
+ let proc_info_edx = proc_info_edx as usize ;
191
+
192
+ let extended_features_ebx = extended_features_ebx as usize ;
187
193
188
194
if test_bit ( extended_features_ebx, 3 ) {
189
195
value = set_bit ( value, __Feature:: bmi as u32 ) ;
@@ -233,18 +239,7 @@ fn detect_features() -> usize {
233
239
// org/mozilla-central/file/64bab5cbb9b6/mozglue/build/SSE.cpp#l190
234
240
//
235
241
if test_bit ( proc_info_ecx, 26 ) && test_bit ( proc_info_ecx, 27 ) {
236
- /// XGETBV: reads the contents of the extended control
237
- /// register (XCR).
238
- unsafe fn xgetbv ( xcr_no : u32 ) -> u64 {
239
- let eax: u32 ;
240
- let edx: u32 ;
241
- // xgetbv
242
- asm ! ( "xgetbv"
243
- : "={eax}" ( eax) , "={edx}" ( edx)
244
- : "{ecx}" ( xcr_no)
245
- : : ) ;
246
- ( ( edx as u64 ) << 32 ) | ( eax as u64 )
247
- }
242
+ use super :: x86:: xgetbv;
248
243
249
244
// This is safe because on x86 `xgetbv` is always available.
250
245
if unsafe { xgetbv ( 0 ) } & 6 == 6 {
0 commit comments