3
3
use super :: no_std_floats:: NoStdFloatExt ;
4
4
5
5
use 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
+
9
8
use interpreter:: stack:: CallFrame ;
10
9
use tinywasm_types:: * ;
11
10
12
11
#[ 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:: * ;
14
21
15
22
use super :: num_helpers:: * ;
16
23
use super :: stack:: { BlockFrame , BlockType , Stack } ;
@@ -315,8 +322,16 @@ impl<'store, 'stack> Executor<'store, 'stack> {
315
322
V128Or => self . stack . values . calculate_same :: < Value128 > ( |a, b| Ok ( a | b) ) . to_cf ( ) ?,
316
323
V128Xor => self . stack . values . calculate_same :: < Value128 > ( |a, b| Ok ( a ^ b) ) . to_cf ( ) ?,
317
324
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 ( ) ?,
319
326
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) ?,
320
335
321
336
I8x16Splat => self . stack . values . replace_top :: < i32 , i8x16 > ( |v| Ok ( Simd :: < i8 , 16 > :: splat ( v as i8 ) ) ) . to_cf ( ) ?,
322
337
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> {
373
388
I16x8LeU => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. simd_le ( b) . to_int ( ) ) ) . to_cf ( ) ?,
374
389
I32x4LeU => self . stack . values . calculate_same :: < i32x4 > ( |a, b| Ok ( a. simd_le ( b) . to_int ( ) ) ) . to_cf ( ) ?,
375
390
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
+
376
395
I8x16GeU => self . stack . values . calculate_same :: < i8x16 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
377
396
I16x8GeU => self . stack . values . calculate_same :: < i16x8 > ( |a, b| Ok ( a. simd_ge ( b) . to_int ( ) ) ) . to_cf ( ) ?,
378
397
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> {
382
401
I32x4Abs => self . stack . values . replace_top_same :: < i32x4 > ( |a| Ok ( a. abs ( ) ) ) . to_cf ( ) ?,
383
402
I64x2Abs => self . stack . values . replace_top_same :: < i64x2 > ( |a| Ok ( a. abs ( ) ) ) . to_cf ( ) ?,
384
403
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
+
385
496
i => return ControlFlow :: Break ( Some ( Error :: UnsupportedFeature ( format ! ( "unimplemented opcode: {i:?}" ) ) ) ) ,
386
497
} ;
387
498
@@ -689,6 +800,47 @@ impl<'store, 'stack> Executor<'store, 'stack> {
689
800
Ok ( ( ) )
690
801
}
691
802
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
+
692
844
fn exec_mem_load < LOAD : MemLoadable < LOAD_SIZE > , const LOAD_SIZE : usize , TARGET : InternalValue > (
693
845
& mut self ,
694
846
mem_addr : tinywasm_types:: MemAddr ,
0 commit comments