use rustc_middle::mir;
use rustc_span::Symbol;
use rustc_target::abi::Align;
use rustc_target::spec::abi::Abi;
use super::horizontal_bin_op;
use crate::*;
use shims::foreign_items::EmulateByNameResult;
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
crate::MiriInterpCxExt<'mir, 'tcx>
{
fn emulate_x86_sse3_intrinsic(
&mut self,
link_name: Symbol,
abi: Abi,
args: &[OpTy<'tcx, Provenance>],
dest: &PlaceTy<'tcx, Provenance>,
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
let this = self.eval_context_mut();
let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap();
match unprefixed_name {
"addsub.ps" | "addsub.pd" => {
let [left, right] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let (left, left_len) = this.operand_to_simd(left)?;
let (right, right_len) = this.operand_to_simd(right)?;
let (dest, dest_len) = this.place_to_simd(dest)?;
assert_eq!(dest_len, left_len);
assert_eq!(dest_len, right_len);
for i in 0..dest_len {
let left = this.read_immediate(&this.project_index(&left, i)?)?;
let right = this.read_immediate(&this.project_index(&right, i)?)?;
let dest = this.project_index(&dest, i)?;
let op = if i % 2 == 0 { mir::BinOp::Sub } else { mir::BinOp::Add };
let res = this.wrapping_binary_op(op, &left, &right)?;
this.write_immediate(*res, &dest)?;
}
}
"hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => {
let [left, right] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let which = match unprefixed_name {
"hadd.ps" | "hadd.pd" => mir::BinOp::Add,
"hsub.ps" | "hsub.pd" => mir::BinOp::Sub,
_ => unreachable!(),
};
horizontal_bin_op(this, which, false, left, right, dest)?;
}
"ldu.dq" => {
let [src_ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let src_ptr = this.read_pointer(src_ptr)?;
let dest = dest.force_mplace(this)?;
this.mem_copy(
src_ptr,
Align::ONE,
dest.ptr(),
Align::ONE,
dest.layout.size,
true,
)?;
}
_ => return Ok(EmulateByNameResult::NotSupported),
}
Ok(EmulateByNameResult::NeedsJumping)
}
}