core/stdarch/crates/core_arch/src/x86_64/
adx.rs

1#[cfg(test)]
2use stdarch_test::assert_instr;
3
4#[allow(improper_ctypes)]
5unsafe extern "unadjusted" {
6    #[link_name = "llvm.x86.addcarry.64"]
7    fn llvm_addcarry_u64(a: u8, b: u64, c: u64) -> (u8, u64);
8    #[link_name = "llvm.x86.subborrow.64"]
9    fn llvm_subborrow_u64(a: u8, b: u64, c: u64) -> (u8, u64);
10}
11
12/// Adds unsigned 64-bit integers `a` and `b` with unsigned 8-bit carry-in `c_in`
13/// (carry or overflow flag), and store the unsigned 64-bit result in `out`, and the carry-out
14/// is returned (carry or overflow flag).
15///
16/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_addcarry_u64)
17#[inline]
18#[cfg_attr(test, assert_instr(adc))]
19#[stable(feature = "simd_x86_adx", since = "1.33.0")]
20pub fn _addcarry_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 {
21    let (a, b) = unsafe { llvm_addcarry_u64(c_in, a, b) };
22    *out = b;
23    a
24}
25
26/// Adds unsigned 64-bit integers `a` and `b` with unsigned 8-bit carry-in `c_in`
27/// (carry or overflow flag), and store the unsigned 64-bit result in `out`, and
28/// the carry-out is returned (carry or overflow flag).
29///
30/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_addcarryx_u64)
31#[inline]
32#[target_feature(enable = "adx")]
33#[cfg_attr(test, assert_instr(adc))]
34#[stable(feature = "simd_x86_adx", since = "1.33.0")]
35pub fn _addcarryx_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 {
36    _addcarry_u64(c_in, a, b, out)
37}
38
39/// Adds unsigned 64-bit integers `a` and `b` with unsigned 8-bit carry-in `c_in`.
40/// (carry or overflow flag), and store the unsigned 64-bit result in `out`, and
41/// the carry-out is returned (carry or overflow flag).
42///
43/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_subborrow_u64)
44#[inline]
45#[cfg_attr(test, assert_instr(sbb))]
46#[stable(feature = "simd_x86_adx", since = "1.33.0")]
47pub fn _subborrow_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 {
48    let (a, b) = unsafe { llvm_subborrow_u64(c_in, a, b) };
49    *out = b;
50    a
51}
52
53#[cfg(test)]
54mod tests {
55    use stdarch_test::simd_test;
56
57    use crate::core_arch::x86_64::*;
58
59    #[test]
60    fn test_addcarry_u64() {
61        let a = u64::MAX;
62        let mut out = 0;
63
64        let r = _addcarry_u64(0, a, 1, &mut out);
65        assert_eq!(r, 1);
66        assert_eq!(out, 0);
67
68        let r = _addcarry_u64(0, a, 0, &mut out);
69        assert_eq!(r, 0);
70        assert_eq!(out, a);
71
72        let r = _addcarry_u64(1, a, 1, &mut out);
73        assert_eq!(r, 1);
74        assert_eq!(out, 1);
75
76        let r = _addcarry_u64(1, a, 0, &mut out);
77        assert_eq!(r, 1);
78        assert_eq!(out, 0);
79
80        let r = _addcarry_u64(0, 3, 4, &mut out);
81        assert_eq!(r, 0);
82        assert_eq!(out, 7);
83
84        let r = _addcarry_u64(1, 3, 4, &mut out);
85        assert_eq!(r, 0);
86        assert_eq!(out, 8);
87    }
88
89    #[simd_test(enable = "adx")]
90    fn test_addcarryx_u64() {
91        let a = u64::MAX;
92        let mut out = 0;
93
94        let r = _addcarryx_u64(0, a, 1, &mut out);
95        assert_eq!(r, 1);
96        assert_eq!(out, 0);
97
98        let r = _addcarryx_u64(0, a, 0, &mut out);
99        assert_eq!(r, 0);
100        assert_eq!(out, a);
101
102        let r = _addcarryx_u64(1, a, 1, &mut out);
103        assert_eq!(r, 1);
104        assert_eq!(out, 1);
105
106        let r = _addcarryx_u64(1, a, 0, &mut out);
107        assert_eq!(r, 1);
108        assert_eq!(out, 0);
109
110        let r = _addcarryx_u64(0, 3, 4, &mut out);
111        assert_eq!(r, 0);
112        assert_eq!(out, 7);
113
114        let r = _addcarryx_u64(1, 3, 4, &mut out);
115        assert_eq!(r, 0);
116        assert_eq!(out, 8);
117    }
118
119    #[test]
120    fn test_subborrow_u64() {
121        let a = u64::MAX;
122        let mut out = 0;
123
124        let r = _subborrow_u64(0, 0, 1, &mut out);
125        assert_eq!(r, 1);
126        assert_eq!(out, a);
127
128        let r = _subborrow_u64(0, 0, 0, &mut out);
129        assert_eq!(r, 0);
130        assert_eq!(out, 0);
131
132        let r = _subborrow_u64(1, 0, 1, &mut out);
133        assert_eq!(r, 1);
134        assert_eq!(out, a - 1);
135
136        let r = _subborrow_u64(1, 0, 0, &mut out);
137        assert_eq!(r, 1);
138        assert_eq!(out, a);
139
140        let r = _subborrow_u64(0, 7, 3, &mut out);
141        assert_eq!(r, 0);
142        assert_eq!(out, 4);
143
144        let r = _subborrow_u64(1, 7, 3, &mut out);
145        assert_eq!(r, 0);
146        assert_eq!(out, 3);
147    }
148}