mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Implement llvm.x86.subborrow.32
and llvm.x86.subborrow.64
This commit is contained in:
parent
6ec63ed251
commit
a617b89996
@ -51,6 +51,32 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
this.write_scalar(Scalar::from_u8(c_out.into()), &this.project_field(dest, 0)?)?;
|
||||
this.write_immediate(*sum, &this.project_field(dest, 1)?)?;
|
||||
}
|
||||
// Used to implement the `_subborrow_u32` and `_subborrow_u64` functions.
|
||||
// Computes a - b with input and output borrow. The input borrow is an 8-bit
|
||||
// value, which is interpreted as 1 if it is non-zero. The output borrow is
|
||||
// an 8-bit value that will be 0 or 1.
|
||||
// https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html
|
||||
"subborrow.32" | "subborrow.64" => {
|
||||
if unprefixed_name == "subborrow.64" && this.tcx.sess.target.arch != "x86_64" {
|
||||
return Ok(EmulateByNameResult::NotSupported);
|
||||
}
|
||||
|
||||
let [b_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
|
||||
let b_in = this.read_scalar(b_in)?.to_u8()? != 0;
|
||||
let a = this.read_immediate(a)?;
|
||||
let b = this.read_immediate(b)?;
|
||||
|
||||
let (sub, overflow1) = this.overflowing_binary_op(mir::BinOp::Sub, &a, &b)?;
|
||||
let (sub, overflow2) = this.overflowing_binary_op(
|
||||
mir::BinOp::Sub,
|
||||
&sub,
|
||||
&ImmTy::from_uint(b_in, a.layout),
|
||||
)?;
|
||||
let b_out = overflow1 | overflow2;
|
||||
|
||||
this.write_scalar(Scalar::from_u8(b_out.into()), &this.project_field(dest, 0)?)?;
|
||||
this.write_immediate(*sub, &this.project_field(dest, 1)?)?;
|
||||
}
|
||||
|
||||
name if name.starts_with("sse.") => {
|
||||
return sse::EvalContextExt::emulate_x86_sse_intrinsic(
|
||||
|
@ -13,6 +13,14 @@ mod x86 {
|
||||
(c_out, sum)
|
||||
}
|
||||
|
||||
fn sbb(b_in: u8, a: u32, b: u32) -> (u8, u32) {
|
||||
let mut sum = 0;
|
||||
// SAFETY: There are no safety requirements for calling `_subborrow_u32`.
|
||||
// It's just unsafe for API consistency with other intrinsics.
|
||||
let b_out = unsafe { arch::_subborrow_u32(b_in, a, b, &mut sum) };
|
||||
(b_out, sum)
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(adc(0, 1, 1), (0, 2));
|
||||
assert_eq!(adc(1, 1, 1), (0, 3));
|
||||
@ -22,6 +30,19 @@ mod x86 {
|
||||
assert_eq!(adc(1, u32::MAX, u32::MAX), (1, u32::MAX));
|
||||
assert_eq!(adc(2, u32::MAX, u32::MAX), (1, u32::MAX));
|
||||
assert_eq!(adc(u8::MAX, u32::MAX, u32::MAX), (1, u32::MAX));
|
||||
|
||||
assert_eq!(sbb(0, 1, 1), (0, 0));
|
||||
assert_eq!(sbb(1, 1, 1), (1, u32::MAX));
|
||||
assert_eq!(sbb(2, 1, 1), (1, u32::MAX)); // any non-zero borrow acts as 1!
|
||||
assert_eq!(sbb(u8::MAX, 1, 1), (1, u32::MAX));
|
||||
assert_eq!(sbb(0, 2, 1), (0, 1));
|
||||
assert_eq!(sbb(1, 2, 1), (0, 0));
|
||||
assert_eq!(sbb(2, 2, 1), (0, 0));
|
||||
assert_eq!(sbb(u8::MAX, 2, 1), (0, 0));
|
||||
assert_eq!(sbb(0, 1, 2), (1, u32::MAX));
|
||||
assert_eq!(sbb(1, 1, 2), (1, u32::MAX - 1));
|
||||
assert_eq!(sbb(2, 1, 2), (1, u32::MAX - 1));
|
||||
assert_eq!(sbb(u8::MAX, 1, 2), (1, u32::MAX - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +58,14 @@ mod x86_64 {
|
||||
(c_out, sum)
|
||||
}
|
||||
|
||||
fn sbb(b_in: u8, a: u64, b: u64) -> (u8, u64) {
|
||||
let mut sum = 0;
|
||||
// SAFETY: There are no safety requirements for calling `_subborrow_u64`.
|
||||
// It's just unsafe for API consistency with other intrinsics.
|
||||
let b_out = unsafe { arch::_subborrow_u64(b_in, a, b, &mut sum) };
|
||||
(b_out, sum)
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(adc(0, 1, 1), (0, 2));
|
||||
assert_eq!(adc(1, 1, 1), (0, 3));
|
||||
@ -46,6 +75,19 @@ mod x86_64 {
|
||||
assert_eq!(adc(1, u64::MAX, u64::MAX), (1, u64::MAX));
|
||||
assert_eq!(adc(2, u64::MAX, u64::MAX), (1, u64::MAX));
|
||||
assert_eq!(adc(u8::MAX, u64::MAX, u64::MAX), (1, u64::MAX));
|
||||
|
||||
assert_eq!(sbb(0, 1, 1), (0, 0));
|
||||
assert_eq!(sbb(1, 1, 1), (1, u64::MAX));
|
||||
assert_eq!(sbb(2, 1, 1), (1, u64::MAX)); // any non-zero borrow acts as 1!
|
||||
assert_eq!(sbb(u8::MAX, 1, 1), (1, u64::MAX));
|
||||
assert_eq!(sbb(0, 2, 1), (0, 1));
|
||||
assert_eq!(sbb(1, 2, 1), (0, 0));
|
||||
assert_eq!(sbb(2, 2, 1), (0, 0));
|
||||
assert_eq!(sbb(u8::MAX, 2, 1), (0, 0));
|
||||
assert_eq!(sbb(0, 1, 2), (1, u64::MAX));
|
||||
assert_eq!(sbb(1, 1, 2), (1, u64::MAX - 1));
|
||||
assert_eq!(sbb(2, 1, 2), (1, u64::MAX - 1));
|
||||
assert_eq!(sbb(u8::MAX, 1, 2), (1, u64::MAX - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user