Skip to content

Commit fc010a5

Browse files
authored
cmov: make Cmov::cmovz a provided method (#871)
This makes it easier to implement the `Cmov` trait for foreign types. It additionally makes the `value` argument an `&Self` reference, which should make it easier to impl the trait for non-`Copy` types where it's desirable to avoid a move. Note: breaking change
1 parent a958f76 commit fc010a5

File tree

7 files changed

+101
-99
lines changed

7 files changed

+101
-99
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmov/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ constant-time and not be rewritten as branches by the compiler.
66
Provides wrappers for the CMOV family of instructions on x86/x86_64
77
and CSEL on AArch64.
88
"""
9-
version = "0.2.0"
9+
version = "0.3.0-pre"
1010
authors = ["RustCrypto Developers"]
1111
license = "Apache-2.0 OR MIT"
1212
repository = "https://github.com/RustCrypto/utils/tree/master/cmov"

cmov/src/aarch64.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,71 +19,71 @@ macro_rules! csel {
1919

2020
impl Cmov for u16 {
2121
#[inline(always)]
22-
fn cmovz(&mut self, value: Self, condition: Condition) {
22+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
2323
csel!(
2424
"cmp {0:w}, 0",
25-
"csel {1:w}, {2:w}, {3:w}, EQ",
25+
"csel {1:w}, {2:w}, {3:w}, NE",
2626
self,
27-
value,
27+
*value,
2828
condition
2929
);
3030
}
3131

3232
#[inline(always)]
33-
fn cmovnz(&mut self, value: Self, condition: Condition) {
33+
fn cmovz(&mut self, value: &Self, condition: Condition) {
3434
csel!(
3535
"cmp {0:w}, 0",
36-
"csel {1:w}, {2:w}, {3:w}, NE",
36+
"csel {1:w}, {2:w}, {3:w}, EQ",
3737
self,
38-
value,
38+
*value,
3939
condition
4040
);
4141
}
4242
}
4343

4444
impl Cmov for u32 {
4545
#[inline(always)]
46-
fn cmovz(&mut self, value: Self, condition: Condition) {
46+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
4747
csel!(
4848
"cmp {0:w}, 0",
49-
"csel {1:w}, {2:w}, {3:w}, EQ",
49+
"csel {1:w}, {2:w}, {3:w}, NE",
5050
self,
51-
value,
51+
*value,
5252
condition
5353
);
5454
}
5555

5656
#[inline(always)]
57-
fn cmovnz(&mut self, value: Self, condition: Condition) {
57+
fn cmovz(&mut self, value: &Self, condition: Condition) {
5858
csel!(
5959
"cmp {0:w}, 0",
60-
"csel {1:w}, {2:w}, {3:w}, NE",
60+
"csel {1:w}, {2:w}, {3:w}, EQ",
6161
self,
62-
value,
62+
*value,
6363
condition
6464
);
6565
}
6666
}
6767

6868
impl Cmov for u64 {
6969
#[inline(always)]
70-
fn cmovz(&mut self, value: Self, condition: Condition) {
70+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
7171
csel!(
7272
"cmp {0:x}, 0",
73-
"csel {1:x}, {2:x}, {3:x}, EQ",
73+
"csel {1:x}, {2:x}, {3:x}, NE",
7474
self,
75-
value,
75+
*value,
7676
condition
7777
);
7878
}
7979

8080
#[inline(always)]
81-
fn cmovnz(&mut self, value: Self, condition: Condition) {
81+
fn cmovz(&mut self, value: &Self, condition: Condition) {
8282
csel!(
8383
"cmp {0:x}, 0",
84-
"csel {1:x}, {2:x}, {3:x}, NE",
84+
"csel {1:x}, {2:x}, {3:x}, EQ",
8585
self,
86-
value,
86+
*value,
8787
condition
8888
);
8989
}

cmov/src/lib.rs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,56 +24,58 @@ pub type Condition = u8;
2424
/// Conditional move
2525
// TODO(tarcieri): make one of `cmovz`/`cmovnz` a provided method which calls the other?
2626
pub trait Cmov {
27-
/// Move if zero.
28-
///
29-
/// Uses a `cmp` instruction to check if the given `condition` value is
30-
/// equal to zero, and if so, conditionally moves `value` to `self`
31-
/// when `condition` is equal to zero.
32-
fn cmovz(&mut self, value: Self, condition: Condition);
33-
3427
/// Move if non-zero.
3528
///
3629
/// Uses a `test` instruction to check if the given `condition` value is
3730
/// equal to zero, conditionally moves `value` to `self` when `condition` is
3831
/// equal to zero.
39-
fn cmovnz(&mut self, value: Self, condition: Condition);
32+
fn cmovnz(&mut self, value: &Self, condition: Condition);
33+
34+
/// Move if zero.
35+
///
36+
/// Uses a `cmp` instruction to check if the given `condition` value is
37+
/// equal to zero, and if so, conditionally moves `value` to `self`
38+
/// when `condition` is equal to zero.
39+
fn cmovz(&mut self, value: &Self, condition: Condition) {
40+
self.cmovnz(value, !condition)
41+
}
4042
}
4143

4244
impl Cmov for u8 {
4345
#[inline(always)]
44-
fn cmovz(&mut self, value: Self, condition: Condition) {
46+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
4547
let mut tmp = *self as u16;
46-
tmp.cmovz(value as u16, condition);
48+
tmp.cmovnz(&(*value as u16), condition);
4749
*self = tmp as u8;
4850
}
4951

5052
#[inline(always)]
51-
fn cmovnz(&mut self, value: Self, condition: Condition) {
53+
fn cmovz(&mut self, value: &Self, condition: Condition) {
5254
let mut tmp = *self as u16;
53-
tmp.cmovnz(value as u16, condition);
55+
tmp.cmovz(&(*value as u16), condition);
5456
*self = tmp as u8;
5557
}
5658
}
5759

5860
impl Cmov for u128 {
5961
#[inline(always)]
60-
fn cmovz(&mut self, value: Self, condition: Condition) {
62+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
6163
let mut lo = (*self & u64::MAX as u128) as u64;
6264
let mut hi = (*self >> 64) as u64;
6365

64-
lo.cmovz((value & u64::MAX as u128) as u64, condition);
65-
hi.cmovz((value >> 64) as u64, condition);
66+
lo.cmovnz(&((*value & u64::MAX as u128) as u64), condition);
67+
hi.cmovnz(&((*value >> 64) as u64), condition);
6668

6769
*self = (lo as u128) | (hi as u128) << 64;
6870
}
6971

7072
#[inline(always)]
71-
fn cmovnz(&mut self, value: Self, condition: Condition) {
73+
fn cmovz(&mut self, value: &Self, condition: Condition) {
7274
let mut lo = (*self & u64::MAX as u128) as u64;
7375
let mut hi = (*self >> 64) as u64;
7476

75-
lo.cmovnz((value & u64::MAX as u128) as u64, condition);
76-
hi.cmovnz((value >> 64) as u64, condition);
77+
lo.cmovz(&((*value & u64::MAX as u128) as u64), condition);
78+
hi.cmovz(&((*value >> 64) as u64), condition);
7779

7880
*self = (lo as u128) | (hi as u128) << 64;
7981
}

cmov/src/portable.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,47 +10,47 @@ use crate::{Cmov, Condition};
1010

1111
impl Cmov for u16 {
1212
#[inline(always)]
13-
fn cmovz(&mut self, value: Self, condition: Condition) {
13+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
1414
let mut tmp = *self as u64;
15-
tmp.cmovz(value as u64, condition);
15+
tmp.cmovnz(&(*value as u64), condition);
1616
*self = tmp as u16;
1717
}
1818

1919
#[inline(always)]
20-
fn cmovnz(&mut self, value: Self, condition: Condition) {
20+
fn cmovz(&mut self, value: &Self, condition: Condition) {
2121
let mut tmp = *self as u64;
22-
tmp.cmovnz(value as u64, condition);
22+
tmp.cmovz(&(*value as u64), condition);
2323
*self = tmp as u16;
2424
}
2525
}
2626

2727
impl Cmov for u32 {
2828
#[inline(always)]
29-
fn cmovz(&mut self, value: Self, condition: Condition) {
29+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
3030
let mut tmp = *self as u64;
31-
tmp.cmovz(value as u64, condition);
31+
tmp.cmovnz(&(*value as u64), condition);
3232
*self = tmp as u32;
3333
}
3434

3535
#[inline(always)]
36-
fn cmovnz(&mut self, value: Self, condition: Condition) {
36+
fn cmovz(&mut self, value: &Self, condition: Condition) {
3737
let mut tmp = *self as u64;
38-
tmp.cmovnz(value as u64, condition);
38+
tmp.cmovz(&(*value as u64), condition);
3939
*self = tmp as u32;
4040
}
4141
}
4242

4343
impl Cmov for u64 {
4444
#[inline(always)]
45-
fn cmovz(&mut self, value: Self, condition: Condition) {
46-
let mask = (1 ^ is_non_zero(condition)).wrapping_sub(1);
47-
*self = (*self & mask) | (value & !mask);
45+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
46+
let mask = is_non_zero(condition).wrapping_sub(1);
47+
*self = (*self & mask) | (*value & !mask);
4848
}
4949

5050
#[inline(always)]
51-
fn cmovnz(&mut self, value: Self, condition: Condition) {
52-
let mask = is_non_zero(condition).wrapping_sub(1);
53-
*self = (*self & mask) | (value & !mask);
51+
fn cmovz(&mut self, value: &Self, condition: Condition) {
52+
let mask = (1 ^ is_non_zero(condition)).wrapping_sub(1);
53+
*self = (*self & mask) | (*value & !mask);
5454
}
5555
}
5656

cmov/src/x86.rs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,62 +27,62 @@ macro_rules! cmov {
2727

2828
impl Cmov for u16 {
2929
#[inline(always)]
30-
fn cmovz(&mut self, value: Self, condition: Condition) {
31-
cmov!("cmovz {1:e}, {2:e}", self, value, condition);
30+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
31+
cmov!("cmovnz {1:e}, {2:e}", self, *value, condition);
3232
}
3333

3434
#[inline(always)]
35-
fn cmovnz(&mut self, value: Self, condition: Condition) {
36-
cmov!("cmovnz {1:e}, {2:e}", self, value, condition);
35+
fn cmovz(&mut self, value: &Self, condition: Condition) {
36+
cmov!("cmovz {1:e}, {2:e}", self, *value, condition);
3737
}
3838
}
3939

4040
impl Cmov for u32 {
4141
#[inline(always)]
42-
fn cmovz(&mut self, value: Self, condition: Condition) {
43-
cmov!("cmovz {1:e}, {2:e}", self, value, condition);
42+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
43+
cmov!("cmovnz {1:e}, {2:e}", self, *value, condition);
4444
}
4545

4646
#[inline(always)]
47-
fn cmovnz(&mut self, value: Self, condition: Condition) {
48-
cmov!("cmovnz {1:e}, {2:e}", self, value, condition);
49-
}
50-
}
51-
52-
#[cfg(target_arch = "x86_64")]
53-
impl Cmov for u64 {
54-
#[inline(always)]
55-
fn cmovz(&mut self, value: Self, condition: Condition) {
56-
cmov!("cmovz {1:r}, {2:r}", self, value, condition);
57-
}
58-
59-
#[inline(always)]
60-
fn cmovnz(&mut self, value: Self, condition: Condition) {
61-
cmov!("cmovnz {1:r}, {2:r}", self, value, condition);
47+
fn cmovz(&mut self, value: &Self, condition: Condition) {
48+
cmov!("cmovz {1:e}, {2:e}", self, *value, condition);
6249
}
6350
}
6451

6552
#[cfg(target_arch = "x86")]
6653
impl Cmov for u64 {
6754
#[inline(always)]
68-
fn cmovz(&mut self, value: Self, condition: Condition) {
55+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
6956
let mut lo = (*self & u32::MAX as u64) as u32;
7057
let mut hi = (*self >> 32) as u32;
7158

72-
lo.cmovz((value & u32::MAX as u64) as u32, condition);
73-
hi.cmovz((value >> 32) as u32, condition);
59+
lo.cmovnz(&((*value & u32::MAX as u64) as u32), condition);
60+
hi.cmovnz(&((*value >> 32) as u32), condition);
7461

7562
*self = (lo as u64) | (hi as u64) << 32;
7663
}
7764

7865
#[inline(always)]
79-
fn cmovnz(&mut self, value: Self, condition: Condition) {
66+
fn cmovz(&mut self, value: &Self, condition: Condition) {
8067
let mut lo = (*self & u32::MAX as u64) as u32;
8168
let mut hi = (*self >> 32) as u32;
8269

83-
lo.cmovnz((value & u32::MAX as u64) as u32, condition);
84-
hi.cmovnz((value >> 32) as u32, condition);
70+
lo.cmovz(&((*value & u32::MAX as u64) as u32), condition);
71+
hi.cmovz(&((*value >> 32) as u32), condition);
8572

8673
*self = (lo as u64) | (hi as u64) << 32;
8774
}
8875
}
76+
77+
#[cfg(target_arch = "x86_64")]
78+
impl Cmov for u64 {
79+
#[inline(always)]
80+
fn cmovnz(&mut self, value: &Self, condition: Condition) {
81+
cmov!("cmovnz {1:r}, {2:r}", self, *value, condition);
82+
}
83+
84+
#[inline(always)]
85+
fn cmovz(&mut self, value: &Self, condition: Condition) {
86+
cmov!("cmovz {1:r}, {2:r}", self, *value, condition);
87+
}
88+
}

0 commit comments

Comments
 (0)