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