@@ -210,9 +210,6 @@ fn detect_features() -> usize {
210210 if test_bit ( proc_info_ecx, 20 ) {
211211 value = set_bit ( value, __Feature:: sse4_2 as u32 ) ;
212212 }
213- if test_bit ( proc_info_ecx, 21 ) {
214- value = set_bit ( value, __Feature:: tbm as u32 ) ;
215- }
216213 if test_bit ( proc_info_ecx, 23 ) {
217214 value = set_bit ( value, __Feature:: popcnt as u32 ) ;
218215 }
@@ -257,9 +254,40 @@ fn detect_features() -> usize {
257254 }
258255 }
259256
257+ if test_bit ( proc_info_ecx, 21 ) && is_amd ( ) {
258+ value = set_bit ( value, __Feature:: tbm as u32 ) ;
259+ }
260+
260261 value
261262}
262263
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+
263291/// This global variable is a bitset used to cache the features supported by
264292/// the CPU.
265293static FEATURES : AtomicUsize = AtomicUsize :: new ( :: std:: usize:: MAX ) ;
0 commit comments