@@ -210,9 +210,6 @@ fn detect_features() -> usize {
210
210
if test_bit ( proc_info_ecx, 20 ) {
211
211
value = set_bit ( value, __Feature:: sse4_2 as u32 ) ;
212
212
}
213
- if test_bit ( proc_info_ecx, 21 ) {
214
- value = set_bit ( value, __Feature:: tbm as u32 ) ;
215
- }
216
213
if test_bit ( proc_info_ecx, 23 ) {
217
214
value = set_bit ( value, __Feature:: popcnt as u32 ) ;
218
215
}
@@ -257,9 +254,40 @@ fn detect_features() -> usize {
257
254
}
258
255
}
259
256
257
+ if test_bit ( proc_info_ecx, 21 ) && is_amd ( ) {
258
+ value = set_bit ( value, __Feature:: tbm as u32 ) ;
259
+ }
260
+
260
261
value
261
262
}
262
263
264
+ /// Is this an AMD CPU?
265
+ #[ inline( never) ]
266
+ fn is_amd ( ) -> bool {
267
+ let ebx: u32 ;
268
+ let edx: u32 ;
269
+ let ecx: u32 ;
270
+ // EAX = 0: Basic Information. The vendor ID is stored in 12 u8 ascii
271
+ // chars, returned in EBX, EDX, and ECX (in that order):
272
+ unsafe {
273
+ asm ! ( "cpuid"
274
+ : "={ebx}" ( ebx) , "={ecx}" ( ecx) , "={edx}" ( edx)
275
+ : "{eax}" ( 0x0000_0000_u32 ) , "{ecx}" ( 0 as u32 )
276
+ : : "volatile" ) ;
277
+ }
278
+ let ebx: [ u8 ; 4 ] = unsafe { :: std:: mem:: transmute ( ebx) } ;
279
+ let edx: [ u8 ; 4 ] = unsafe { :: std:: mem:: transmute ( edx) } ;
280
+ let ecx: [ u8 ; 4 ] = unsafe { :: std:: mem:: transmute ( ecx) } ;
281
+ #[ cfg_attr( rustfmt, rustfmt_skip) ]
282
+ let vendor_id = [
283
+ ebx[ 0 ] , ebx[ 1 ] , ebx[ 2 ] , ebx[ 3 ] ,
284
+ ecx[ 0 ] , ecx[ 1 ] , ecx[ 2 ] , ecx[ 3 ] ,
285
+ edx[ 0 ] , edx[ 1 ] , edx[ 2 ] , edx[ 3 ] ,
286
+ ] ;
287
+ let vendor_id_amd = b"AuthenticAMD" ;
288
+ vendor_id == * vendor_id_amd
289
+ }
290
+
263
291
/// This global variable is a bitset used to cache the features supported by
264
292
/// the CPU.
265
293
static FEATURES : AtomicUsize = AtomicUsize :: new ( :: std:: usize:: MAX ) ;
0 commit comments