miri/shims/
aarch64.rs
1use rustc_middle::mir::BinOp;
2use rustc_middle::ty::Ty;
3use rustc_span::Symbol;
4use rustc_target::callconv::{Conv, FnAbi};
5
6use crate::*;
7
8impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
9pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10 fn emulate_aarch64_intrinsic(
11 &mut self,
12 link_name: Symbol,
13 abi: &FnAbi<'tcx, Ty<'tcx>>,
14 args: &[OpTy<'tcx>],
15 dest: &MPlaceTy<'tcx>,
16 ) -> InterpResult<'tcx, EmulateItemResult> {
17 let this = self.eval_context_mut();
18 let unprefixed_name = link_name.as_str().strip_prefix("llvm.aarch64.").unwrap();
20 match unprefixed_name {
21 "isb" => {
22 let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
23 let arg = this.read_scalar(arg)?.to_i32()?;
24 match arg {
25 15 => {
27 this.yield_active_thread();
28 }
29 _ => {
30 throw_unsup_format!("unsupported llvm.aarch64.isb argument {}", arg);
31 }
32 }
33 }
34
35 "neon.umaxp.v16i8" => {
40 let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
41
42 let (left, left_len) = this.project_to_simd(left)?;
43 let (right, right_len) = this.project_to_simd(right)?;
44 let (dest, lane_count) = this.project_to_simd(dest)?;
45 assert_eq!(left_len, right_len);
46 assert_eq!(lane_count, left_len);
47
48 for lane_idx in 0..lane_count {
49 let src = if lane_idx < (lane_count / 2) { &left } else { &right };
50 let src_idx = lane_idx.strict_rem(lane_count / 2);
51
52 let lhs_lane =
53 this.read_immediate(&this.project_index(src, src_idx.strict_mul(2))?)?;
54 let rhs_lane = this.read_immediate(
55 &this.project_index(src, src_idx.strict_mul(2).strict_add(1))?,
56 )?;
57
58 let res_lane = if this
60 .binary_op(BinOp::Gt, &lhs_lane, &rhs_lane)?
61 .to_scalar()
62 .to_bool()?
63 {
64 lhs_lane
65 } else {
66 rhs_lane
67 };
68
69 let dest = this.project_index(&dest, lane_idx)?;
70 this.write_immediate(*res_lane, &dest)?;
71 }
72 }
73
74 _ => return interp_ok(EmulateItemResult::NotSupported),
75 }
76 interp_ok(EmulateItemResult::NeedsReturn)
77 }
78}