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