@@ -417,3 +417,205 @@ TYPED_TEST(execute_floating_point_trunc, trunc)
417417 EXPECT_EQ (result.value .template as <IntT>(), FloatT{-1 });
418418 }
419419}
420+
421+ TEST (execute_floating_point, f32_load)
422+ {
423+ /* wat2wasm
424+ (memory 1 1)
425+ (data (i32.const 0) "\00\00\00\00") ;; 0
426+ (data (i32.const 4) "\b6\f3\9d\3f") ;; 1.234
427+ (data (i32.const 8) "\b6\f3\9d\bf") ;; -1.234
428+ (data (i32.const 12) "\00\00\c0\7f") ;; canonical NaN
429+ (data (i32.const 16) "\01\00\c0\7f") ;; arithmetic NaN
430+ (data (i32.const 20) "\01\00\80\7f") ;; signaling NaN
431+ (func (param i32) (result f32)
432+ (f32.load (local.get 0))
433+ )
434+ */
435+ const auto wasm = from_hex (
436+ " 0061736d0100000001060160017f017d0302010005030100010a0901070020002a02000b0b37060041000b0400"
437+ " 0000000041040b04b6f39d3f0041080b04b6f39dbf00410c0b040000c07f0041100b040100c07f0041140b0401"
438+ " 00807f" );
439+
440+ auto instance = instantiate (parse (wasm));
441+ EXPECT_THAT (execute (*instance, 0 , {0 }), Result (0 .0f ));
442+ EXPECT_THAT (execute (*instance, 0 , {4 }), Result (1 .234f ));
443+ EXPECT_THAT (execute (*instance, 0 , {8 }), Result (-1 .234f ));
444+ EXPECT_THAT (execute (*instance, 0 , {12 }), Result (FP32::nan (FP32::canon)));
445+ EXPECT_THAT (execute (*instance, 0 , {16 }), Result (FP32::nan (FP32::canon + 1 )));
446+ EXPECT_THAT (execute (*instance, 0 , {20 }), Result (FP32::nan (1 )));
447+
448+ EXPECT_THAT (execute (*instance, 0 , {65534 }), Traps ());
449+ EXPECT_THAT (execute (*instance, 0 , {65537 }), Traps ());
450+ }
451+
452+ TEST (execute_floating_point, f32_load_overflow)
453+ {
454+ /* wat2wasm
455+ (memory 1 1)
456+ (func (param i32) (result f32)
457+ get_local 0
458+ f32.load offset=0x7fffffff
459+ )
460+ */
461+ const auto wasm = from_hex (
462+ " 0061736d0100000001060160017f017d0302010005030100010a0d010b0020002a02ffffffff070b" );
463+
464+ auto instance = instantiate (parse (wasm));
465+
466+ // Offset is 0x7fffffff + 0 => 0x7fffffff
467+ EXPECT_THAT (execute (*instance, 0 , {0 }), Traps ());
468+ // Offset is 0x7fffffff + 0x80000000 => 0xffffffff
469+ EXPECT_THAT (execute (*instance, 0 , {0x80000000 }), Traps ());
470+ // Offset is 0x7fffffff + 0x80000001 => 0x100000000
471+ EXPECT_THAT (execute (*instance, 0 , {0x80000001 }), Traps ());
472+ }
473+
474+ TEST (execute_floating_point, f64_load)
475+ {
476+ /* wat2wasm
477+ (memory 1 1)
478+ (data (i32.const 0) "\00\00\00\00\00\00\00\00") ;; 0
479+ (data (i32.const 8) "\58\39\b4\c8\76\be\f3\3f") ;; 1.234
480+ (data (i32.const 16) "\58\39\b4\c8\76\be\f3\bf") ;; -1.234
481+ (data (i32.const 24) "\00\00\00\00\00\00\f8\7f") ;; canonical NaN
482+ (data (i32.const 32) "\01\00\00\00\00\00\f8\7f") ;; arithmetic NaN
483+ (data (i32.const 40) "\01\00\00\00\00\00\f0\7f") ;; signaling NaN
484+ (func (param i32) (result f64)
485+ (f64.load (local.get 0))
486+ )
487+ */
488+ const auto wasm = from_hex (
489+ " 0061736d0100000001060160017f017c0302010005030100010a0901070020002b03000b0b4f060041000b0800"
490+ " 000000000000000041080b085839b4c876bef33f0041100b085839b4c876bef3bf0041180b08000000000000f8"
491+ " 7f0041200b08010000000000f87f0041280b08010000000000f07f" );
492+
493+ auto instance = instantiate (parse (wasm));
494+ EXPECT_THAT (execute (*instance, 0 , {0 }), Result (0.0 ));
495+ EXPECT_THAT (execute (*instance, 0 , {8 }), Result (1.234 ));
496+ EXPECT_THAT (execute (*instance, 0 , {16 }), Result (-1.234 ));
497+ EXPECT_THAT (execute (*instance, 0 , {24 }), Result (FP64::nan (FP64::canon)));
498+ EXPECT_THAT (execute (*instance, 0 , {32 }), Result (FP64::nan (FP64::canon + 1 )));
499+ EXPECT_THAT (execute (*instance, 0 , {40 }), Result (FP64::nan (1 )));
500+
501+ EXPECT_THAT (execute (*instance, 0 , {65534 }), Traps ());
502+ EXPECT_THAT (execute (*instance, 0 , {65537 }), Traps ());
503+ }
504+
505+ TEST (execute_floating_point, f64_load_overflow)
506+ {
507+ /* wat2wasm
508+ (memory 1 1)
509+ (func (param i32) (result f64)
510+ get_local 0
511+ f64.load offset=0x7fffffff
512+ )
513+ */
514+ const auto wasm = from_hex (
515+ " 0061736d0100000001060160017f017c0302010005030100010a0d010b0020002b03ffffffff070b" );
516+
517+ auto instance = instantiate (parse (wasm));
518+
519+ // Offset is 0x7fffffff + 0 => 0x7fffffff
520+ EXPECT_THAT (execute (*instance, 0 , {0 }), Traps ());
521+ // Offset is 0x7fffffff + 0x80000000 => 0xffffffff
522+ EXPECT_THAT (execute (*instance, 0 , {0x80000000 }), Traps ());
523+ // Offset is 0x7fffffff + 0x80000001 => 0x100000000
524+ EXPECT_THAT (execute (*instance, 0 , {0x80000001 }), Traps ());
525+ }
526+
527+ TEST (execute_floating_point, f32_store)
528+ {
529+ /* wat2wasm
530+ (memory 1 1)
531+ (data (i32.const 0) "\cc\cc\cc\cc\cc\cc")
532+ (func (param f32 i32)
533+ get_local 1
534+ get_local 0
535+ f32.store
536+ )
537+ */
538+ const auto wasm = from_hex (
539+ " 0061736d0100000001060160027d7f000302010005030100010a0b010900200120003802000b0b0c010041000b"
540+ " 06cccccccccccc" );
541+
542+ const std::tuple<float , bytes> test_cases[]{
543+ {0 .0f , " cc00000000cc" _bytes},
544+ {1 .234f , " ccb6f39d3fcc" _bytes},
545+ {-1 .234f , " ccb6f39dbfcc" _bytes},
546+ {FP32::nan (FP32::canon), " cc0000c07fcc" _bytes},
547+ {FP32::nan (FP32::canon + 1 ), " cc0100c07fcc" _bytes},
548+ {FP32::nan (1 ), " cc0100807fcc" _bytes},
549+ };
550+
551+ for (const auto & [arg, expected] : test_cases)
552+ {
553+ auto instance = instantiate (parse (wasm));
554+
555+ EXPECT_THAT (execute (*instance, 0 , {arg, 1 }), Result ());
556+ EXPECT_EQ (instance->memory ->substr (0 , 6 ), expected);
557+
558+ EXPECT_THAT (execute (*instance, 0 , {arg, 65534 }), Traps ());
559+ EXPECT_THAT (execute (*instance, 0 , {arg, 65537 }), Traps ());
560+ }
561+ }
562+
563+ TEST (execute_floating_point, f32_store_overflow)
564+ {
565+ /* wat2wasm
566+ (memory 1 1)
567+ (func (param i32)
568+ get_local 0
569+ f32.const 1.234
570+ f32.store offset=0x7fffffff
571+ )
572+ */
573+ const auto wasm = from_hex (
574+ " 0061736d0100000001050160017f00030201000504010101010a12011000200043b6f39d3f3802ffffffff070"
575+ " b" );
576+
577+ auto instance = instantiate (parse (wasm));
578+
579+ // Offset is 0x7fffffff + 0 => 0x7fffffff
580+ EXPECT_THAT (execute (*instance, 0 , {0 }), Traps ());
581+ // Offset is 0x7fffffff + 0x80000000 => 0xffffffff
582+ EXPECT_THAT (execute (*instance, 0 , {0x80000000 }), Traps ());
583+ // Offset is 0x7fffffff + 0x80000001 => 0x100000000
584+ EXPECT_THAT (execute (*instance, 0 , {0x80000001 }), Traps ());
585+ }
586+
587+ TEST (execute_floating_point, f64_store)
588+ {
589+ /* wat2wasm
590+ (memory 1 1)
591+ (data (i32.const 0) "\cc\cc\cc\cc\cc\cc\cc\cc\cc\cc\cc\cc")
592+ (func (param f64 i32)
593+ get_local 1
594+ get_local 0
595+ f64.store
596+ )
597+ */
598+ const auto wasm = from_hex (
599+ " 0061736d0100000001060160027c7f000302010005030100010a0b010900200120003903000b0b12010041000b"
600+ " 0ccccccccccccccccccccccccc" );
601+
602+ const std::tuple<double , bytes> test_cases[]{
603+ {0.0 , " cc0000000000000000cc" _bytes},
604+ {1.234 , " cc5839b4c876bef33fcc" _bytes},
605+ {-1.234 , " cc5839b4c876bef3bfcc" _bytes},
606+ {FP64::nan (FP64::canon), " cc000000000000f87fcc" _bytes},
607+ {FP64::nan (FP64::canon + 1 ), " cc010000000000f87fcc" _bytes},
608+ {FP64::nan (1 ), " cc010000000000f07fcc" _bytes},
609+ };
610+
611+ for (const auto & [arg, expected] : test_cases)
612+ {
613+ auto instance = instantiate (parse (wasm));
614+
615+ EXPECT_THAT (execute (*instance, 0 , {arg, 1 }), Result ());
616+ EXPECT_EQ (instance->memory ->substr (0 , 10 ), expected);
617+
618+ EXPECT_THAT (execute (*instance, 0 , {arg, 65534 }), Traps ());
619+ EXPECT_THAT (execute (*instance, 0 , {arg, 65537 }), Traps ());
620+ }
621+ }
0 commit comments