Skip to content

Commit 8d0e2ef

Browse files
committed
Use Stephen Checkoway solution
1 parent 3123d96 commit 8d0e2ef

File tree

1 file changed

+32
-35
lines changed

1 file changed

+32
-35
lines changed

coresimd/x86/cpuid.rs

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -93,41 +93,38 @@ pub fn has_cpuid() -> bool {
9393
// https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets/
9494
// which detects whether `cpuid` is available by checking whether the 21st bit of the EFLAGS register is modifiable or not.
9595
// If it is, then `cpuid` is available.
96-
let eax: i32;
97-
asm!(r#"
98-
# Save a copy of the original eflags that we will restore later:
99-
pushfd
100-
# Copy eflags to ecx and eax:
101-
pushfd
102-
pop %eax
103-
mov %ecx, %eax
104-
# Flip 21st bit and write back to eflags register:
105-
xor %eax, 0x200000
106-
push %eax
107-
popfd
108-
# Read eflags register again:
109-
pushfd
110-
pop %eax
111-
# If cpuid is available, the bit will still be flipped
112-
# and it will be the only bit modified.
113-
#
114-
# xor with the original eflags should produce a 1 in
115-
# the 21st bit in this case, and zeros for all other bits:
116-
xor %eax, %ecx
117-
# So if the value of the 21st bit is 1, cpuid is available,
118-
# and if it is zero, it isn't because we didn't manage to
119-
# modify it:
120-
shrl %eax, 21
121-
# Restore original eflags
122-
popfd
123-
"#
124-
: "={eax}"(eax) // output operands
125-
: // input operands
126-
: "memory", "ecx" // clobbers all memory and ecx
127-
: "volatile" // has side-effects
128-
);
129-
debug_assert!(eax == 0 || eax == 1);
130-
eax == 1
96+
let result: u32;
97+
let _temp: u32;
98+
unsafe {
99+
asm!(r#"
100+
# Read eflags into $0 and copy into $1:
101+
pushfd
102+
pop $0
103+
mov $1, $0
104+
# Flip 21st bit:
105+
xor $0, 0x200000
106+
# Set eflags:
107+
push $0
108+
popfd
109+
# Read eflags again, if cpuid is available
110+
# the 21st bit will be flipped, otherwise it
111+
# it will have the same value as the original in $1:
112+
pushfd
113+
pop $0
114+
# Xor'ing with the original eflags should have the
115+
# 21st bit set to true if cpuid is available and zero
116+
# otherwise. All other bits have not been modified and
117+
# are zero:
118+
xor $0, $1
119+
# Store in $0 the value of the 21st bit
120+
shr $0, 21
121+
"#
122+
: "=r"(result), "=r"(_temp)
123+
:
124+
: "cc", "memory"
125+
: "intel");
126+
}
127+
result != 0
131128
}
132129
}
133130
}

0 commit comments

Comments
 (0)