diff --git a/cmov/src/x86.rs b/cmov/src/x86.rs index d067620a..7344f101 100644 --- a/cmov/src/x86.rs +++ b/cmov/src/x86.rs @@ -25,6 +25,24 @@ macro_rules! cmov { }; } +macro_rules! cmov_eq { + ($xor:expr, $instruction:expr, $lhs:expr, $rhs:expr, $condition:expr, $dst:expr) => { + let mut tmp = *$dst as u16; + unsafe { + asm! { + $xor, + $instruction, + inout(reg) *$lhs => _, + in(reg) *$rhs, + inlateout(reg) tmp, + in(reg) $condition as u16, + options(pure, nomem, nostack), + }; + } + *$dst = tmp as u8; + }; +} + impl Cmov for u16 { #[inline] fn cmovnz(&mut self, value: &Self, condition: Condition) { @@ -40,12 +58,26 @@ impl Cmov for u16 { impl CmovEq for u16 { #[inline] fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { - output.cmovz(&input, (self ^ rhs) as u8); + cmov_eq!( + "xor {0:x}, {1:x}", + "cmovz {2:e}, {3:e}", + self, + rhs, + input, + output + ); } #[inline] fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { - output.cmovnz(&input, (self ^ rhs) as u8); + cmov_eq!( + "xor {0:x}, {1:x}", + "cmovnz {2:e}, {3:e}", + self, + rhs, + input, + output + ); } } @@ -64,12 +96,26 @@ impl Cmov for u32 { impl CmovEq for u32 { #[inline] fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { - output.cmovz(&input, (self ^ rhs) as u8); + cmov_eq!( + "xor {0:e}, {1:e}", + "cmovz {2:e}, {3:e}", + self, + rhs, + input, + output + ); } #[inline] fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { - output.cmovnz(&input, (self ^ rhs) as u8); + cmov_eq!( + "xor {0:e}, {1:e}", + "cmovnz {2:e}, {3:e}", + self, + rhs, + input, + output + ); } } @@ -140,11 +186,25 @@ impl Cmov for u64 { impl CmovEq for u64 { #[inline] fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { - output.cmovz(&input, (self ^ rhs) as u8); + cmov_eq!( + "xor {0:r}, {1:r}", + "cmovz {2:r}, {3:r}", + self, + rhs, + input, + output + ); } #[inline] fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { - output.cmovnz(&input, (self ^ rhs) as u8); + cmov_eq!( + "xor {0:r}, {1:r}", + "cmovnz {2:r}, {3:r}", + self, + rhs, + input, + output + ); } }