Skip to content

Commit 6c4f4e1

Browse files
committed
Fix asm! in bit-test intrinsics on x32
1 parent 99cd446 commit 6c4f4e1

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

crates/core_arch/src/x86/bt.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
#[cfg(test)]
22
use stdarch_test::assert_instr;
33

4+
// x32 wants to use a 32-bit address size, but asm! defaults to using the full
5+
// register name (e.g. rax). We have to explicitly override the placeholder to
6+
// use the 32-bit register name in that case.
7+
#[cfg(target_pointer_width = "32")]
8+
macro_rules! bt {
9+
($inst:expr) => {
10+
concat!($inst, " {b:e}, ({p:e})")
11+
};
12+
}
13+
#[cfg(target_pointer_width = "64")]
14+
macro_rules! bt {
15+
($inst:expr) => {
16+
concat!($inst, " {b:e}, ({p})")
17+
};
18+
}
19+
420
/// Returns the bit in position `b` of the memory addressed by `p`.
521
#[inline]
622
#[cfg_attr(test, assert_instr(bt))]
723
#[unstable(feature = "simd_x86_bittest", issue = "59414")]
824
pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 {
925
let r: u8;
1026
asm!(
11-
"btl {b:e}, ({p})",
27+
bt!("btl"),
1228
"setc {r}",
1329
p = in(reg) p,
1430
b = in(reg) b,
@@ -25,7 +41,7 @@ pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 {
2541
pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 {
2642
let r: u8;
2743
asm!(
28-
"btsl {b:e}, ({p})",
44+
bt!("btsl"),
2945
"setc {r}",
3046
p = in(reg) p,
3147
b = in(reg) b,
@@ -42,7 +58,7 @@ pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 {
4258
pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 {
4359
let r: u8;
4460
asm!(
45-
"btrl {b:e}, ({p})",
61+
bt!("btrl"),
4662
"setc {r}",
4763
p = in(reg) p,
4864
b = in(reg) b,
@@ -59,7 +75,7 @@ pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 {
5975
pub unsafe fn _bittestandcomplement(p: *mut i32, b: i32) -> u8 {
6076
let r: u8;
6177
asm!(
62-
"btcl {b:e}, ({p})",
78+
bt!("btcl"),
6379
"setc {r}",
6480
p = in(reg) p,
6581
b = in(reg) b,

crates/core_arch/src/x86_64/bt.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
#[cfg(test)]
22
use stdarch_test::assert_instr;
33

4+
// x32 wants to use a 32-bit address size, but asm! defaults to using the full
5+
// register name (e.g. rax). We have to explicitly override the placeholder to
6+
// use the 32-bit register name in that case.
7+
#[cfg(target_pointer_width = "32")]
8+
macro_rules! bt {
9+
($inst:expr) => {
10+
concat!($inst, " {b}, ({p:e})")
11+
};
12+
}
13+
#[cfg(target_pointer_width = "64")]
14+
macro_rules! bt {
15+
($inst:expr) => {
16+
concat!($inst, " {b}, ({p})")
17+
};
18+
}
19+
420
/// Returns the bit in position `b` of the memory addressed by `p`.
521
#[inline]
622
#[cfg_attr(test, assert_instr(bt))]
723
#[unstable(feature = "simd_x86_bittest", issue = "59414")]
824
pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 {
925
let r: u8;
1026
asm!(
11-
"btq {b}, ({p})",
27+
bt!("btq"),
1228
"setc {r}",
1329
p = in(reg) p,
1430
b = in(reg) b,
@@ -25,7 +41,7 @@ pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 {
2541
pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 {
2642
let r: u8;
2743
asm!(
28-
"btsq {b}, ({p})",
44+
bt!("btsq"),
2945
"setc {r}",
3046
p = in(reg) p,
3147
b = in(reg) b,
@@ -42,7 +58,7 @@ pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 {
4258
pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 {
4359
let r: u8;
4460
asm!(
45-
"btrq {b}, ({p})",
61+
bt!("btrq"),
4662
"setc {r}",
4763
p = in(reg) p,
4864
b = in(reg) b,
@@ -59,7 +75,7 @@ pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 {
5975
pub unsafe fn _bittestandcomplement64(p: *mut i64, b: i64) -> u8 {
6076
let r: u8;
6177
asm!(
62-
"btcq {b}, ({p})",
78+
bt!("btcq"),
6379
"setc {r}",
6480
p = in(reg) p,
6581
b = in(reg) b,

0 commit comments

Comments
 (0)