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