33use super :: no_std_floats:: NoStdFloatExt ;
44
55use alloc:: { format, rc:: Rc , string:: ToString } ;
6- use core:: ops:: ControlFlow ;
7- use core:: simd:: cmp:: { SimdPartialEq , SimdPartialOrd } ;
8- use core:: simd:: num:: SimdUint ;
6+ use core:: ops:: { ControlFlow , IndexMut , Shl , Shr } ;
7+
98use interpreter:: stack:: CallFrame ;
109use tinywasm_types:: * ;
1110
1211#[ cfg( feature = "simd" ) ]
13- use super :: simd:: * ;
12+ mod simd {
13+ #[ cfg( feature = "std" ) ]
14+ pub ( super ) use crate :: std:: simd:: StdFloat ;
15+ pub ( super ) use core:: simd:: cmp:: { SimdOrd , SimdPartialEq , SimdPartialOrd } ;
16+ pub ( super ) use core:: simd:: num:: { SimdFloat , SimdInt , SimdUint } ;
17+ pub ( super ) use core:: simd:: * ;
18+ }
19+ #[ cfg( feature = "simd" ) ]
20+ use simd:: * ;
1421
1522use super :: num_helpers:: * ;
1623use super :: stack:: { BlockFrame , BlockType , Stack } ;
@@ -315,8 +322,16 @@ impl<'store, 'stack> Executor<'store, 'stack> {
315322 V128Or => self . stack . values . calculate_same :: < Value128 > ( |a, b| Ok ( a | b) ) . to_cf ( ) ?,
316323 V128Xor => self . stack . values . calculate_same :: < Value128 > ( |a, b| Ok ( a ^ b) ) . to_cf ( ) ?,
317324 V128Bitselect => self . stack . values . calculate_same_3 :: < Value128 > ( |v1, v2, c| Ok ( ( v1 & c) | ( v2 & !c) ) ) . to_cf ( ) ?,
318- V128AnyTrue => self . stack . values . replace_top :: < Value128 , i32 > ( |v| Ok ( ( v. reduce_sum ( ) != 0 ) as i32 ) ) . to_cf ( ) ?,
325+ V128AnyTrue => self . stack . values . replace_top :: < Value128 , i32 > ( |v| Ok ( ( v. reduce_or ( ) != 0 ) as i32 ) ) . to_cf ( ) ?,
319326 I8x16Swizzle => self . stack . values . calculate_same :: < Value128 > ( |a, s| Ok ( a. swizzle_dyn ( s) ) ) . to_cf ( ) ?,
327+ V128Load ( arg) => self . exec_mem_load :: < Value128 , 16 , _ > ( arg. mem_addr ( ) , arg. offset ( ) , |v| v) ?,
328+ V128Store ( arg) => self . exec_mem_store :: < Value128 , Value128 , 16 > ( arg. mem_addr ( ) , arg. offset ( ) , |v| v) ?,
329+ V128Const ( arg) => self . exec_const :: < Value128 > ( self . cf . data ( ) . v128_constants [ * arg as usize ] . to_le_bytes ( ) . into ( ) ) ,
330+
331+ V128Load8Lane ( arg, lane) => self . exec_mem_load_lane :: < i8 , i8x16 , 1 > ( arg. mem_addr ( ) , arg. offset ( ) , * lane) ?,
332+ V128Load16Lane ( arg, lane) => self . exec_mem_load_lane :: < i16 , i16x8 , 2 > ( arg. mem_addr ( ) , arg. offset ( ) , * lane) ?,
333+ V128Load32Lane ( arg, lane) => self . exec_mem_load_lane :: < i32 , i32x4 , 4 > ( arg. mem_addr ( ) , arg. offset ( ) , * lane) ?,
334+ V128Load64Lane ( arg, lane) => self . exec_mem_load_lane :: < i64 , i64x2 , 8 > ( arg. mem_addr ( ) , arg. offset ( ) , * lane) ?,
320335
321336 I8x16Splat => self . stack . values . replace_top :: < i32 , i8x16 > ( |v| Ok ( Simd :: < i8 , 16 > :: splat ( v as i8 ) ) ) . to_cf ( ) ?,
322337 I16x8Splat => self . stack . values . replace_top :: < i32 , i16x8 > ( |v| Ok ( Simd :: < i16 , 8 > :: splat ( v as i16 ) ) ) . to_cf ( ) ?,
@@ -373,6 +388,10 @@ impl<'store, 'stack> Executor<'store, 'stack> {
373388 I16x8LeU => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. simd_le ( b) . to_int ( ) ) ) . to_cf ( ) ?,
374389 I32x4LeU => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. simd_le ( b) . to_int ( ) ) ) . to_cf ( ) ?,
375390
391+ I8x16GeS => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
392+ I16x8GeS => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
393+ I32x4GeS => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
394+
376395 I8x16GeU => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
377396 I16x8GeU => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
378397 I32x4GeU => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
@@ -382,6 +401,98 @@ impl<'store, 'stack> Executor<'store, 'stack> {
382401 I32x4Abs => self . stack . values . replace_top_same :: < i32x4 > ( |a| Ok ( a. abs ( ) ) ) . to_cf ( ) ?,
383402 I64x2Abs => self . stack . values . replace_top_same :: < i64x2 > ( |a| Ok ( a. abs ( ) ) ) . to_cf ( ) ?,
384403
404+ I8x16Neg => self . stack . values . replace_top_same :: < i8x16 > ( |a| Ok ( -a) ) . to_cf ( ) ?,
405+ I16x8Neg => self . stack . values . replace_top_same :: < i16x8 > ( |a| Ok ( -a) ) . to_cf ( ) ?,
406+ I32x4Neg => self . stack . values . replace_top_same :: < i32x4 > ( |a| Ok ( -a) ) . to_cf ( ) ?,
407+ I64x2Neg => self . stack . values . replace_top_same :: < i64x2 > ( |a| Ok ( -a) ) . to_cf ( ) ?,
408+
409+ I8x16AllTrue => self . stack . values . replace_top :: < i8x16 , i32 > ( |v| Ok ( ( v != Simd :: splat ( 0 ) ) as i32 ) ) . to_cf ( ) ?,
410+ I16x8AllTrue => self . stack . values . replace_top :: < i16x8 , i32 > ( |v| Ok ( ( v != Simd :: splat ( 0 ) ) as i32 ) ) . to_cf ( ) ?,
411+ I32x4AllTrue => self . stack . values . replace_top :: < i32x4 , i32 > ( |v| Ok ( ( v != Simd :: splat ( 0 ) ) as i32 ) ) . to_cf ( ) ?,
412+ I64x2AllTrue => self . stack . values . replace_top :: < i64x2 , i32 > ( |v| Ok ( ( v != Simd :: splat ( 0 ) ) as i32 ) ) . to_cf ( ) ?,
413+
414+ I8x16Bitmask => self . stack . values . replace_top :: < i8x16 , i32 > ( |v| Ok ( v. simd_lt ( Simd :: splat ( 0 ) ) . to_bitmask ( ) as i32 ) ) . to_cf ( ) ?,
415+ I16x8Bitmask => self . stack . values . replace_top :: < i16x8 , i32 > ( |v| Ok ( v. simd_lt ( Simd :: splat ( 0 ) ) . to_bitmask ( ) as i32 ) ) . to_cf ( ) ?,
416+ I32x4Bitmask => self . stack . values . replace_top :: < i32x4 , i32 > ( |v| Ok ( v. simd_lt ( Simd :: splat ( 0 ) ) . to_bitmask ( ) as i32 ) ) . to_cf ( ) ?,
417+ I64x2Bitmask => self . stack . values . replace_top :: < i64x2 , i32 > ( |v| Ok ( v. simd_lt ( Simd :: splat ( 0 ) ) . to_bitmask ( ) as i32 ) ) . to_cf ( ) ?,
418+
419+ I8x16Shl => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. shl ( b) ) ) . to_cf ( ) ?,
420+ I16x8Shl => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. shl ( b) ) ) . to_cf ( ) ?,
421+ I32x4Shl => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. shl ( b) ) ) . to_cf ( ) ?,
422+ I64x2Shl => self . stack . values . calculate_same :: < i64x2 > ( |a, b| Ok ( a. shl ( b) ) ) . to_cf ( ) ?,
423+
424+ I8x16ShrS => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
425+ I16x8ShrS => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
426+ I32x4ShrS => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
427+ I64x2ShrS => self . stack . values . calculate_same :: < i64x2 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
428+
429+ I8x16ShrU => self . stack . values . calculate_same :: < u8x16 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
430+ I16x8ShrU => self . stack . values . calculate_same :: < u16x8 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
431+ I32x4ShrU => self . stack . values . calculate_same :: < u32x4 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
432+ I64x2ShrU => self . stack . values . calculate_same :: < u64x2 > ( |a, b| Ok ( a. shr ( b) ) ) . to_cf ( ) ?,
433+
434+ I8x16Add => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a + b) ) . to_cf ( ) ?,
435+ I16x8Add => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a + b) ) . to_cf ( ) ?,
436+ I32x4Add => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a + b) ) . to_cf ( ) ?,
437+ I64x2Add => self . stack . values . calculate_same :: < i64x2 > ( |a, b| Ok ( a + b) ) . to_cf ( ) ?,
438+
439+ I8x16Sub => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a - b) ) . to_cf ( ) ?,
440+ I16x8Sub => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a - b) ) . to_cf ( ) ?,
441+ I32x4Sub => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a - b) ) . to_cf ( ) ?,
442+ I64x2Sub => self . stack . values . calculate_same :: < i64x2 > ( |a, b| Ok ( a - b) ) . to_cf ( ) ?,
443+
444+ I8x16MinS => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
445+ I16x8MinS => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
446+ I32x4MinS => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
447+
448+ I8x16MinU => self . stack . values . calculate_same :: < u8x16 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
449+ I16x8MinU => self . stack . values . calculate_same :: < u16x8 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
450+ I32x4MinU => self . stack . values . calculate_same :: < u32x4 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
451+
452+ I8x16MaxS => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
453+ I16x8MaxS => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
454+ I32x4MaxS => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
455+
456+ I8x16MaxU => self . stack . values . calculate_same :: < u8x16 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
457+ I16x8MaxU => self . stack . values . calculate_same :: < u16x8 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
458+ I32x4MaxU => self . stack . values . calculate_same :: < u32x4 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
459+
460+ I64x2Mul => self . stack . values . calculate_same :: < i64x2 > ( |a, b| Ok ( a * b) ) . to_cf ( ) ?,
461+
462+ I8x16AddSatS => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. saturating_add ( b) ) ) . to_cf ( ) ?,
463+ I16x8AddSatS => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. saturating_add ( b) ) ) . to_cf ( ) ?,
464+ I8x16AddSatU => self . stack . values . calculate_same :: < u8x16 > ( |a, b| Ok ( a. saturating_add ( b) ) ) . to_cf ( ) ?,
465+ I16x8AddSatU => self . stack . values . calculate_same :: < u16x8 > ( |a, b| Ok ( a. saturating_add ( b) ) ) . to_cf ( ) ?,
466+ I8x16SubSatS => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. saturating_sub ( b) ) ) . to_cf ( ) ?,
467+ I16x8SubSatS => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. saturating_sub ( b) ) ) . to_cf ( ) ?,
468+ I8x16SubSatU => self . stack . values . calculate_same :: < u8x16 > ( |a, b| Ok ( a. saturating_sub ( b) ) ) . to_cf ( ) ?,
469+ I16x8SubSatU => self . stack . values . calculate_same :: < u16x8 > ( |a, b| Ok ( a. saturating_sub ( b) ) ) . to_cf ( ) ?,
470+
471+ F32x4Ceil => self . stack . values . replace_top_same :: < f32x4 > ( |v| Ok ( v. ceil ( ) ) ) . to_cf ( ) ?,
472+ F64x2Ceil => self . stack . values . replace_top_same :: < f64x2 > ( |v| Ok ( v. ceil ( ) ) ) . to_cf ( ) ?,
473+ F32x4Floor => self . stack . values . replace_top_same :: < f32x4 > ( |v| Ok ( v. floor ( ) ) ) . to_cf ( ) ?,
474+ F64x2Floor => self . stack . values . replace_top_same :: < f64x2 > ( |v| Ok ( v. floor ( ) ) ) . to_cf ( ) ?,
475+ F32x4Trunc => self . stack . values . replace_top_same :: < f32x4 > ( |v| Ok ( v. trunc ( ) ) ) . to_cf ( ) ?,
476+ F64x2Trunc => self . stack . values . replace_top_same :: < f64x2 > ( |v| Ok ( v. trunc ( ) ) ) . to_cf ( ) ?,
477+ F32x4Abs => self . stack . values . replace_top_same :: < f32x4 > ( |v| Ok ( v. abs ( ) ) ) . to_cf ( ) ?,
478+ F64x2Abs => self . stack . values . replace_top_same :: < f64x2 > ( |v| Ok ( v. abs ( ) ) ) . to_cf ( ) ?,
479+ F32x4Neg => self . stack . values . replace_top_same :: < f32x4 > ( |v| Ok ( -v) ) . to_cf ( ) ?,
480+ F64x2Neg => self . stack . values . replace_top_same :: < f64x2 > ( |v| Ok ( -v) ) . to_cf ( ) ?,
481+ F32x4Sqrt => self . stack . values . replace_top_same :: < f32x4 > ( |v| Ok ( v. sqrt ( ) ) ) . to_cf ( ) ?,
482+ F64x2Sqrt => self . stack . values . replace_top_same :: < f64x2 > ( |v| Ok ( v. sqrt ( ) ) ) . to_cf ( ) ?,
483+ F32x4Add => self . stack . values . calculate_same :: < f32x4 > ( |a, b| Ok ( a + b) ) . to_cf ( ) ?,
484+ F64x2Add => self . stack . values . calculate_same :: < f64x2 > ( |a, b| Ok ( a + b) ) . to_cf ( ) ?,
485+ F32x4Sub => self . stack . values . calculate_same :: < f32x4 > ( |a, b| Ok ( a - b) ) . to_cf ( ) ?,
486+ F64x2Sub => self . stack . values . calculate_same :: < f64x2 > ( |a, b| Ok ( a - b) ) . to_cf ( ) ?,
487+ F32x4Mul => self . stack . values . calculate_same :: < f32x4 > ( |a, b| Ok ( a * b) ) . to_cf ( ) ?,
488+ F64x2Mul => self . stack . values . calculate_same :: < f64x2 > ( |a, b| Ok ( a * b) ) . to_cf ( ) ?,
489+ F32x4Div => self . stack . values . calculate_same :: < f32x4 > ( |a, b| Ok ( a / b) ) . to_cf ( ) ?,
490+ F64x2Div => self . stack . values . calculate_same :: < f64x2 > ( |a, b| Ok ( a / b) ) . to_cf ( ) ?,
491+ F32x4Min => self . stack . values . calculate_same :: < f32x4 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
492+ F64x2Min => self . stack . values . calculate_same :: < f64x2 > ( |a, b| Ok ( a. simd_min ( b) ) ) . to_cf ( ) ?,
493+ F32x4Max => self . stack . values . calculate_same :: < f32x4 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
494+ F64x2Max => self . stack . values . calculate_same :: < f64x2 > ( |a, b| Ok ( a. simd_max ( b) ) ) . to_cf ( ) ?,
495+
385496 i => return ControlFlow :: Break ( Some ( Error :: UnsupportedFeature ( format ! ( "unimplemented opcode: {i:?}" ) ) ) ) ,
386497 } ;
387498
@@ -689,6 +800,47 @@ impl<'store, 'stack> Executor<'store, 'stack> {
689800 Ok ( ( ) )
690801 }
691802
803+ fn exec_mem_load_lane <
804+ LOAD : MemLoadable < LOAD_SIZE > ,
805+ INTO : InternalValue + IndexMut < usize , Output = LOAD > ,
806+ const LOAD_SIZE : usize ,
807+ > (
808+ & mut self ,
809+ mem_addr : tinywasm_types:: MemAddr ,
810+ offset : u64 ,
811+ lanes : u8 ,
812+ ) -> ControlFlow < Option < Error > > {
813+ let mem = self . store . get_mem ( self . module . resolve_mem_addr ( mem_addr) ) ;
814+ let mut imm = self . stack . values . pop :: < INTO > ( ) ;
815+ let val = self . stack . values . pop :: < i32 > ( ) as u64 ;
816+ let Some ( Ok ( addr) ) = offset. checked_add ( val) . map ( TryInto :: try_into) else {
817+ cold ( ) ;
818+ return ControlFlow :: Break ( Some ( Error :: Trap ( Trap :: MemoryOutOfBounds {
819+ offset : val as usize ,
820+ len : LOAD_SIZE ,
821+ max : 0 ,
822+ } ) ) ) ;
823+ } ;
824+ let val = mem. load_as :: < LOAD_SIZE , LOAD > ( addr) . to_cf ( ) ?;
825+ imm[ lanes as usize ] = val;
826+ self . stack . values . push ( imm) ;
827+ ControlFlow :: Continue ( ( ) )
828+ }
829+
830+ // fn mem_load<LOAD: MemLoadable<LOAD_SIZE>, const LOAD_SIZE: usize, TARGET: InternalValue>(
831+ // &mut self,
832+ // mem_addr: tinywasm_types::MemAddr,
833+ // offset: u64,
834+ // ) -> Result<LOAD, Error> {
835+ // let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr));
836+ // let val = self.stack.values.pop::<i32>() as u64;
837+ // let Some(Ok(addr)) = offset.checked_add(val).map(TryInto::try_into) else {
838+ // cold();
839+ // return Err(Error::Trap(Trap::MemoryOutOfBounds { offset: val as usize, len: LOAD_SIZE, max: 0 }));
840+ // };
841+ // mem.load_as::<LOAD_SIZE, LOAD>(addr)
842+ // }
843+
692844 fn exec_mem_load < LOAD : MemLoadable < LOAD_SIZE > , const LOAD_SIZE : usize , TARGET : InternalValue > (
693845 & mut self ,
694846 mem_addr : tinywasm_types:: MemAddr ,
0 commit comments