@@ -82,6 +82,42 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
8282 this. write_immediate ( * res, & dest) ?;
8383 }
8484 }
85+ // Used to implement the _mm_madd_epi16 function.
86+ // Multiplies packed signed 16-bit integers in `left` and `right`, producing
87+ // intermediate signed 32-bit integers. Horizontally add adjacent pairs of
88+ // intermediate 32-bit integers, and pack the results in `dest`.
89+ "pmadd.wd" => {
90+ let [ left, right] =
91+ this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
92+
93+ let ( left, left_len) = this. operand_to_simd ( left) ?;
94+ let ( right, right_len) = this. operand_to_simd ( right) ?;
95+ let ( dest, dest_len) = this. place_to_simd ( dest) ?;
96+
97+ assert_eq ! ( left_len, right_len) ;
98+ assert_eq ! ( dest_len. checked_mul( 2 ) . unwrap( ) , left_len) ;
99+
100+ for i in 0 ..dest_len {
101+ let j1 = i. checked_mul ( 2 ) . unwrap ( ) ;
102+ let left1 = this. read_scalar ( & this. project_index ( & left, j1) ?) ?. to_i16 ( ) ?;
103+ let right1 = this. read_scalar ( & this. project_index ( & right, j1) ?) ?. to_i16 ( ) ?;
104+
105+ let j2 = j1. checked_add ( 1 ) . unwrap ( ) ;
106+ let left2 = this. read_scalar ( & this. project_index ( & left, j2) ?) ?. to_i16 ( ) ?;
107+ let right2 = this. read_scalar ( & this. project_index ( & right, j2) ?) ?. to_i16 ( ) ?;
108+
109+ let dest = this. project_index ( & dest, i) ?;
110+
111+ // Multiplications are i16*i16->i32, which will not overflow.
112+ let mul1 = i32:: from ( left1) . checked_mul ( right1. into ( ) ) . unwrap ( ) ;
113+ let mul2 = i32:: from ( left2) . checked_mul ( right2. into ( ) ) . unwrap ( ) ;
114+ // However, this addition can overflow in the most extreme case
115+ // (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000
116+ let res = mul1. wrapping_add ( mul2) ;
117+
118+ this. write_scalar ( Scalar :: from_i32 ( res) , & dest) ?;
119+ }
120+ }
85121 // Used to implement the _mm_mulhi_epi16 and _mm_mulhi_epu16 functions.
86122 "pmulh.w" | "pmulhu.w" => {
87123 let [ left, right] =
0 commit comments