Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit a893618

Browse files
committed
Implement llvm.x86.addcarry.64
1 parent a71a008 commit a893618

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

src/shims/foreign_items.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
671671
}
672672

673673
// Architecture-specific shims
674+
"llvm.x86.addcarry.64" if this.tcx.sess.target.arch == "x86_64" => {
675+
// Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum.
676+
let &[ref c_in, ref a, ref b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
677+
let c_in = this.read_scalar(c_in)?.to_u8()?;
678+
let a = this.read_scalar(a)?.to_u64()?;
679+
let b = this.read_scalar(b)?.to_u64()?;
680+
681+
let wide_sum = c_in as u128 + a as u128 + b as u128;
682+
let (c_out, sum) = ((wide_sum >> 64) as u8, wide_sum as u64);
683+
684+
let c_out_field = this.place_field(dest, 0)?;
685+
this.write_scalar(Scalar::from_u8(c_out), &c_out_field)?;
686+
let sum_field = this.place_field(dest, 1)?;
687+
this.write_scalar(Scalar::from_u64(sum), &sum_field)?;
688+
}
674689
"llvm.x86.sse2.pause" if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => {
675690
let &[] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
676691
this.yield_active_thread();

tests/run-pass/intrinsics-x86.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#[cfg(target_arch = "x86_64")]
2+
mod x86_64 {
3+
use core::arch::x86_64 as arch;
4+
5+
fn adc(c_in: u8, a: u64, b: u64) -> (u8, u64) {
6+
let mut sum = 0;
7+
// SAFETY: There are no safety requirements for calling `_addcarry_u64`.
8+
// It's just unsafe for API consistency with other intrinsics.
9+
let c_out = unsafe { arch::_addcarry_u64(c_in, a, b, &mut sum) };
10+
(c_out, sum)
11+
}
12+
13+
pub fn main() {
14+
assert_eq!(adc(1, 1, 1), (0, 3));
15+
assert_eq!(adc(3, u64::MAX, u64::MAX), (2, 1));
16+
}
17+
}
18+
19+
fn main() {
20+
#[cfg(target_arch = "x86_64")]
21+
x86_64::main();
22+
}

0 commit comments

Comments
 (0)