@@ -8,7 +8,7 @@ use crate::{
88        V128 , 
99    } , 
1010    engine:: { executor:: InstructionPtr ,  utils:: unreachable_unchecked} , 
11-     ir:: { Instruction ,  Reg ,  ShiftAmount } , 
11+     ir:: { AnyConst32 ,   Instruction ,  Reg ,  ShiftAmount } , 
1212} ; 
1313
1414impl  Executor < ' _ >  { 
@@ -29,6 +29,60 @@ impl Executor<'_> {
2929        } 
3030    } 
3131
32+     /// Fetches a [`Reg`] from an [`Instruction::Const32`] instruction parameter. 
33+ fn  fetch_const32_as < T > ( & self )  -> T 
34+     where 
35+         T :  From < AnyConst32 > , 
36+     { 
37+         let  mut  addr:  InstructionPtr  = self . ip ; 
38+         addr. add ( 1 ) ; 
39+         match  * addr. get ( )  { 
40+             Instruction :: Const32  {  value }  => value. into ( ) , 
41+             unexpected => { 
42+                 // Safety: Wasmi translation guarantees that [`Instruction::Const32`] exists. 
43+                 unsafe  { 
44+                     unreachable_unchecked ! ( 
45+                         "expected `Instruction::Const32` but found {unexpected:?}" 
46+                     ) 
47+                 } 
48+             } 
49+         } 
50+     } 
51+ 
52+     /// Fetches a [`Reg`] from an [`Instruction::I64Const32`] instruction parameter. 
53+ fn  fetch_i64const32 ( & self )  -> i64  { 
54+         let  mut  addr:  InstructionPtr  = self . ip ; 
55+         addr. add ( 1 ) ; 
56+         match  * addr. get ( )  { 
57+             Instruction :: I64Const32  {  value }  => value. into ( ) , 
58+             unexpected => { 
59+                 // Safety: Wasmi translation guarantees that [`Instruction::I64Const32`] exists. 
60+                 unsafe  { 
61+                     unreachable_unchecked ! ( 
62+                         "expected `Instruction::I64Const32` but found {unexpected:?}" 
63+                     ) 
64+                 } 
65+             } 
66+         } 
67+     } 
68+ 
69+     /// Fetches a [`Reg`] from an [`Instruction::F64Const32`] instruction parameter. 
70+ fn  fetch_f64const32 ( & self )  -> f64  { 
71+         let  mut  addr:  InstructionPtr  = self . ip ; 
72+         addr. add ( 1 ) ; 
73+         match  * addr. get ( )  { 
74+             Instruction :: F64Const32  {  value }  => value. into ( ) , 
75+             unexpected => { 
76+                 // Safety: Wasmi translation guarantees that [`Instruction::F64Const32`] exists. 
77+                 unsafe  { 
78+                     unreachable_unchecked ! ( 
79+                         "expected `Instruction::F64Const32` but found {unexpected:?}" 
80+                     ) 
81+                 } 
82+             } 
83+         } 
84+     } 
85+ 
3286    /// Executes an [`Instruction::I8x16Shuffle`] instruction. 
3387pub  fn  execute_i8x16_shuffle ( & mut  self ,  result :  Reg ,  lhs :  Reg ,  rhs :  Reg )  { 
3488        let  selector = self . fetch_register ( ) ; 
@@ -60,6 +114,91 @@ impl Executor<'_> {
60114        self . set_register_as :: < V128 > ( result,  simd:: v128_bitselect ( lhs,  rhs,  selector) ) ; 
61115        self . next_instr_at ( 2 ) ; 
62116    } 
117+ } 
118+ 
119+ macro_rules!  impl_replace_lane_ops { 
120+     ( 
121+         $( 
122+             ( $ty: ty,  $lane_ty: ty,  Instruction :: $instr_name: ident,  $exec_name: ident,  $execute: expr) 
123+         ) ,*  $( , ) ?
124+     )  => { 
125+         $( 
126+             #[ doc = concat!( "Executes an [`Instruction::" ,  stringify!( $instr_name) ,  "`]." ) ] 
127+             pub  fn  $exec_name( & mut  self ,  result:  Reg ,  input:  Reg ,  lane:  $lane_ty)  { 
128+                 let  value = self . fetch_register( ) ; 
129+                 let  input = self . get_register_as:: <V128 >( input) ; 
130+                 let  value = self . get_register_as:: <$ty>( value) ; 
131+                 self . set_register_as:: <V128 >( result,  $execute( input,  lane,  value) ) ; 
132+                 self . next_instr_at( 2 ) ; 
133+             } 
134+         ) * 
135+     } ; 
136+ } 
137+ 
138+ impl  Executor < ' _ >  { 
139+     impl_replace_lane_ops !  { 
140+         ( i8 ,  ImmLaneIdx16 ,  Instruction :: I8x16ReplaceLane ,  execute_i8x16_replace_lane,  simd:: i8x16_replace_lane) , 
141+         ( i16 ,  ImmLaneIdx8 ,  Instruction :: I16x8ReplaceLane ,  execute_i16x8_replace_lane,  simd:: i16x8_replace_lane) , 
142+         ( i32 ,  ImmLaneIdx4 ,  Instruction :: I32x4ReplaceLane ,  execute_i32x4_replace_lane,  simd:: i32x4_replace_lane) , 
143+         ( i64 ,  ImmLaneIdx2 ,  Instruction :: I64x2ReplaceLane ,  execute_i64x2_replace_lane,  simd:: i64x2_replace_lane) , 
144+         ( f32 ,  ImmLaneIdx4 ,  Instruction :: F32x4ReplaceLane ,  execute_f32x4_replace_lane,  simd:: f32x4_replace_lane) , 
145+         ( f64 ,  ImmLaneIdx2 ,  Instruction :: F64x2ReplaceLane ,  execute_f64x2_replace_lane,  simd:: f64x2_replace_lane) , 
146+     } 
147+ 
148+     /// Executes an [`Instruction::I8x16ReplaceLaneImm`] instruction. 
149+ pub  fn  execute_i8x16_replace_lane_imm ( 
150+         & mut  self , 
151+         result :  Reg , 
152+         input :  Reg , 
153+         lane :  ImmLaneIdx16 , 
154+         value :  i8 , 
155+     )  { 
156+         self . execute_replace_lane_impl ( result,  input,  lane,  value,  simd:: i8x16_replace_lane) 
157+     } 
158+ 
159+     /// Executes an [`Instruction::I16x8ReplaceLaneImm`] instruction. 
160+ pub  fn  execute_i16x8_replace_lane_imm ( & mut  self ,  result :  Reg ,  input :  Reg ,  lane :  ImmLaneIdx8 )  { 
161+         let  value = self . fetch_const32_as :: < i32 > ( )  as  i16 ; 
162+         self . execute_replace_lane_impl ( result,  input,  lane,  value,  simd:: i16x8_replace_lane) 
163+     } 
164+ 
165+     /// Executes an [`Instruction::I32x4ReplaceLaneImm`] instruction. 
166+ pub  fn  execute_i32x4_replace_lane_imm ( & mut  self ,  result :  Reg ,  input :  Reg ,  lane :  ImmLaneIdx4 )  { 
167+         let  value = self . fetch_const32_as :: < i32 > ( ) ; 
168+         self . execute_replace_lane_impl ( result,  input,  lane,  value,  simd:: i32x4_replace_lane) 
169+     } 
170+ 
171+     /// Executes an [`Instruction::I64x2ReplaceLaneImm32`] instruction. 
172+ pub  fn  execute_i64x2_replace_lane_imm32 ( & mut  self ,  result :  Reg ,  input :  Reg ,  lane :  ImmLaneIdx2 )  { 
173+         let  value = self . fetch_i64const32 ( ) ; 
174+         self . execute_replace_lane_impl ( result,  input,  lane,  value,  simd:: i64x2_replace_lane) 
175+     } 
176+ 
177+     /// Executes an [`Instruction::F32x4ReplaceLaneImm`] instruction. 
178+ pub  fn  execute_f32x4_replace_lane_imm ( & mut  self ,  result :  Reg ,  input :  Reg ,  lane :  ImmLaneIdx4 )  { 
179+         let  value = self . fetch_const32_as :: < f32 > ( ) ; 
180+         self . execute_replace_lane_impl ( result,  input,  lane,  value,  simd:: f32x4_replace_lane) 
181+     } 
182+ 
183+     /// Executes an [`Instruction::F64x2ReplaceLaneImm32`] instruction. 
184+ pub  fn  execute_f64x2_replace_lane_imm32 ( & mut  self ,  result :  Reg ,  input :  Reg ,  lane :  ImmLaneIdx2 )  { 
185+         let  value = self . fetch_f64const32 ( ) ; 
186+         self . execute_replace_lane_impl ( result,  input,  lane,  value,  simd:: f64x2_replace_lane) 
187+     } 
188+ 
189+     /// Generically execute a SIMD replace lane instruction. 
190+ fn  execute_replace_lane_impl < T ,  LaneType > ( 
191+         & mut  self , 
192+         result :  Reg , 
193+         input :  Reg , 
194+         lane :  LaneType , 
195+         value :  T , 
196+         eval :  fn ( V128 ,  LaneType ,  T )  -> V128 , 
197+     )  { 
198+         let  input = self . get_register_as :: < V128 > ( input) ; 
199+         self . set_register_as :: < V128 > ( result,  eval ( input,  lane,  value) ) ; 
200+         self . next_instr_at ( 2 ) ; 
201+     } 
63202
64203    impl_unary_executors !  { 
65204        ( Instruction :: V128AnyTrue ,  execute_v128_any_true,  simd:: v128_any_true) , 
0 commit comments