Skip to content

Commit 8d61248

Browse files
committed
Add non inline_asm XCr0 implementation
Signed-off-by: Joe Richey <[email protected]>
1 parent dd0b377 commit 8d61248

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

src/asm/asm.s

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,21 @@ _x86_64_asm_rdgsbase:
280280
_x86_64_asm_wrgsbase:
281281
wrgsbase %rdi
282282
retq
283+
284+
.global _x86_64_asm_xgetbv
285+
.p2align 4
286+
_x86_64_asm_xgetbv:
287+
mov %edi, %ecx # First param is the XCR number
288+
xgetbv
289+
shl $32, %rdx # shift edx to upper 32bit
290+
mov %eax, %eax # clear upper 32bit of rax
291+
or %rdx, %rax # or with rdx
292+
retq
293+
294+
.global _x86_64_asm_xsetbv
295+
.p2align 4
296+
_x86_64_asm_xsetbv:
297+
movl %edi, %ecx # First param is the XCR number
298+
movl %esi, %eax # Second param is the low 32-bits
299+
xsetbv # Third param (high 32-bits) is already in %edx
300+
retq

src/asm/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,4 +251,16 @@ extern "C" {
251251
link_name = "_x86_64_asm_wrgsbase"
252252
)]
253253
pub(crate) fn x86_64_asm_wrgsbase(val: u64);
254+
255+
#[cfg_attr(
256+
any(target_env = "gnu", target_env = "musl"),
257+
link_name = "_x86_64_asm_xgetbv"
258+
)]
259+
pub(crate) fn x86_64_asm_xgetbv(xcr: u32) -> u64;
260+
261+
#[cfg_attr(
262+
any(target_env = "gnu", target_env = "musl"),
263+
link_name = "_x86_64_asm_xsetbv"
264+
)]
265+
pub(crate) fn x86_64_asm_xsetbv(xcr: u32, low: u32, high: u32);
254266
}

src/registers/xcontrol.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ bitflags! {
2424
}
2525
}
2626

27-
#[cfg(all(feature = "instructions", feature = "inline_asm"))]
27+
#[cfg(feature = "instructions")]
2828
mod x86_64 {
2929
use super::*;
3030
impl XCr0 {
@@ -37,16 +37,22 @@ mod x86_64 {
3737
/// Read the current raw XCR0 value.
3838
#[inline]
3939
pub fn read_raw() -> u64 {
40-
let (low, high): (u32, u32);
40+
#[cfg(feature = "inline_asm")]
4141
unsafe {
42+
let (low, high): (u32, u32);
4243
asm!(
4344
"xgetbv",
4445
in("ecx") 0,
4546
out("rax") low, out("rdx") high,
4647
options(nomem, nostack, preserves_flags),
4748
);
49+
(high as u64) << 32 | (low as u64)
50+
}
51+
52+
#[cfg(not(feature = "inline_asm"))]
53+
unsafe {
54+
crate::asm::x86_64_asm_xgetbv(0)
4855
}
49-
(high as u64) << 32 | (low as u64)
5056
}
5157

5258
/// Write XCR0 flags.
@@ -78,12 +84,17 @@ mod x86_64 {
7884
pub unsafe fn write_raw(value: u64) {
7985
let low = value as u32;
8086
let high = (value >> 32) as u32;
87+
88+
#[cfg(feature = "inline_asm")]
8189
asm!(
8290
"xsetbv",
8391
in("ecx") 0,
8492
in("rax") low, in("rdx") high,
8593
options(nomem, nostack, preserves_flags),
8694
);
95+
96+
#[cfg(not(feature = "inline_asm"))]
97+
crate::asm::x86_64_asm_xsetbv(0, low, high);
8798
}
8899
}
89100
}

0 commit comments

Comments
 (0)