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