diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index ec5accad6..aad434808 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -304,6 +304,22 @@ let simd_prefix s = | 0x50l -> v128_or | 0x51l -> v128_xor | 0x52l -> v128_bitselect + | 0x58l -> + let a, o = memop s in + let lane = u8 s in + v128_load8_lane a o lane + | 0x59l -> + let a, o = memop s in + let lane = u8 s in + v128_load16_lane a o lane + | 0x5al -> + let a, o = memop s in + let lane = u8 s in + v128_load32_lane a o lane + | 0x5bl -> + let a, o = memop s in + let lane = u8 s in + v128_load64_lane a o lane | 0x60l -> i8x16_abs | 0x61l -> i8x16_neg | 0x62l -> v128_any_true diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index c69f2fa32..4e76e91e2 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -225,6 +225,15 @@ let encode m = | SimdLoad ({ty= V128Type; sz = Some (Pack64, PackZero); _} as mo) -> simd_op 0xfdl; memop mo + | SimdLoadLane ({ty = V128Type; sz = Some Pack8; _} as mo, i) -> + simd_op 0x58l; memop mo; u8 i; + | SimdLoadLane ({ty = V128Type; sz = Some Pack16; _} as mo, i) -> + simd_op 0x59l; memop mo; u8 i; + | SimdLoadLane ({ty = V128Type; sz = Some Pack32; _} as mo, i) -> + simd_op 0x5al; memop mo; u8 i; + | SimdLoadLane ({ty = V128Type; sz = Some Pack64; _} as mo, i) -> + simd_op 0x5bl; memop mo; u8 i; + | Store ({ty = I32Type; sz = None; _} as mo) -> op 0x36; memop mo | Store ({ty = I64Type; sz = None; _} as mo) -> op 0x37; memop mo | Store ({ty = F32Type; sz = None; _} as mo) -> op 0x38; memop mo diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 3fdc0b5a8..ff86dbc1a 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -227,7 +227,20 @@ let rec step (c : config) : config = let v = match sz with | None -> Memory.load_value mem addr offset ty - | Some (pack_size, simd_load) -> Memory.load_simd_packed pack_size simd_load mem addr offset ty + | Some (pack_size, simd_load) -> + V128 (Memory.load_simd_packed pack_size simd_load mem addr offset ty) + in v :: vs', [] + with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) + + | SimdLoadLane ({offset; ty; sz; _}, j), V128 v128 :: I32 i :: vs' -> + let mem = memory frame.inst (0l @@ e.at) in + let addr = I64_convert.extend_i32_u i in + (try + let v = + match sz with + | None -> assert false + | Some pack_size -> + V128 (Memory.load_simd_lane v128 pack_size mem addr offset ty j) in v :: vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) diff --git a/interpreter/runtime/memory.ml b/interpreter/runtime/memory.ml index 5d4ccfb49..4a20c5a8b 100644 --- a/interpreter/runtime/memory.ml +++ b/interpreter/runtime/memory.ml @@ -139,20 +139,30 @@ let load_simd_packed pack_size simd_load mem a o t = Bytes.set_int64_le b 0 x; let v = V128.of_bits (Bytes.to_string b) in match pack_size, simd_load with - | Pack64, Pack8x8 SX -> V128 (V128.I16x8_convert.widen_low_s v) - | Pack64, Pack8x8 ZX -> V128 (V128.I16x8_convert.widen_low_u v) - | Pack64, Pack16x4 SX -> V128 (V128.I32x4_convert.widen_low_s v) - | Pack64, Pack16x4 ZX -> V128 (V128.I32x4_convert.widen_low_u v) - | Pack64, Pack32x2 SX -> V128 (V128.I64x2_convert.widen_low_s v) - | Pack64, Pack32x2 ZX -> V128 (V128.I64x2_convert.widen_low_u v) - | Pack8, PackSplat -> V128 (V128.I8x16.splat (I8.of_int_s (Int64.to_int x))) - | Pack16, PackSplat -> V128 (V128.I16x8.splat (I16.of_int_s (Int64.to_int x))) - | Pack32, PackSplat -> V128 (V128.I32x4.splat (I32.of_int_s (Int64.to_int x))) - | Pack64, PackSplat -> V128 (V128.I64x2.splat x) - | Pack32, PackZero -> V128 v - | Pack64, PackZero -> V128 v + | Pack64, Pack8x8 SX -> V128.I16x8_convert.widen_low_s v + | Pack64, Pack8x8 ZX -> V128.I16x8_convert.widen_low_u v + | Pack64, Pack16x4 SX -> V128.I32x4_convert.widen_low_s v + | Pack64, Pack16x4 ZX -> V128.I32x4_convert.widen_low_u v + | Pack64, Pack32x2 SX -> V128.I64x2_convert.widen_low_s v + | Pack64, Pack32x2 ZX -> V128.I64x2_convert.widen_low_u v + | Pack8, PackSplat -> V128.I8x16.splat (I8.of_int_s (Int64.to_int x)) + | Pack16, PackSplat -> V128.I16x8.splat (I16.of_int_s (Int64.to_int x)) + | Pack32, PackSplat -> V128.I32x4.splat (I32.of_int_s (Int64.to_int x)) + | Pack64, PackSplat -> V128.I64x2.splat x + | Pack32, PackZero -> v + | Pack64, PackZero -> v | _ -> assert false +let load_simd_lane v pack_size mem a o t laneidx = + let n = packed_size pack_size in + assert (n < Types.size t); + let x = loadn mem a o n in + match pack_size with + | Pack8 -> V128.I8x16.replace_lane laneidx v (Int64.to_int32 x) + | Pack16 -> V128.I16x8.replace_lane laneidx v (Int64.to_int32 x) + | Pack32 -> V128.I32x4.replace_lane laneidx v (Int64.to_int32 x) + | Pack64 -> V128.I64x2.replace_lane laneidx v x + let store_packed sz mem a o v = assert (packed_size sz <= Types.size (Values.type_of v)); let n = packed_size sz in diff --git a/interpreter/runtime/memory.mli b/interpreter/runtime/memory.mli index 7936d0241..efef5df64 100644 --- a/interpreter/runtime/memory.mli +++ b/interpreter/runtime/memory.mli @@ -36,8 +36,10 @@ val load_packed : pack_size -> extension -> memory -> address -> offset -> value_type -> value (* raises Type, Bounds *) val load_simd_packed : - pack_size -> pack_simd -> memory -> address -> offset -> value_type -> value + pack_size -> pack_simd -> memory -> address -> offset -> value_type -> V128.t (* raises Type, Bounds *) +val load_simd_lane : + V128.t -> pack_size -> memory -> address -> offset -> value_type -> int (* lane index *) -> V128.t val store_packed : pack_size -> memory -> address -> offset -> value -> unit (* raises Type, Bounds *) diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 5943ede40..fcd9c22a6 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -114,6 +114,7 @@ type storeop = pack_size memop type simd_loadop = (pack_size * pack_simd) memop type empty type simd_storeop = empty memop +type simd_laneop = pack_size memop * int (* Expressions *) @@ -146,6 +147,7 @@ and instr' = | Load of loadop (* read memory at address *) | Store of storeop (* write memory at address *) | SimdLoad of simd_loadop (* read memory at address *) + | SimdLoadLane of simd_laneop (* read single lane at address *) | SimdStore of simd_storeop (* write memory at address *) | MemorySize (* size of linear memory *) | MemoryGrow (* grow linear memory *) diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index d775b0d68..44f7b9fd6 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -239,6 +239,15 @@ let v128_load32_splat align offset = let v128_load64_splat align offset = SimdLoad {ty= V128Type; align; offset; sz = Some (Pack64, PackSplat)} +let v128_load8_lane align offset imm = + SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack8}, imm) +let v128_load16_lane align offset imm = + SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack16}, imm) +let v128_load32_lane align offset imm = + SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack32}, imm) +let v128_load64_lane align offset imm = + SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack64}, imm) + let v128_load32_zero align offset = SimdLoad {ty= V128Type; align; offset; sz = Some (Pack32, PackZero)} let v128_load64_zero align offset = diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index 1e97a1dcd..8302bcd93 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -450,6 +450,18 @@ let simd_loadop (op : simd_loadop) = ) in memop ("load" ^ suffix) op (packed_size sz) +let simd_laneop (op, i) = + match op.sz with + | None -> assert false + | Some sz -> + let suffix = + match sz with + | Pack8 -> "8_lane" + | Pack16 -> "16_lane" + | Pack32 -> "32_lane" + | Pack64 -> "64_lane" + in memop ("load" ^ suffix) op (packed_size sz) ^ " " ^ (nat i) + let storeop op = match op.sz with | None -> memop "store" op (size op.ty) @@ -501,6 +513,7 @@ let rec instr e = | GlobalSet x -> "global.set " ^ var x, [] | Load op -> loadop op, [] | SimdLoad op -> simd_loadop op, [] + | SimdLoadLane op -> simd_laneop op, [] | SimdStore op -> simd_storeop op, [] | Store op -> storeop op, [] | MemorySize -> "memory.size", [] diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index 880b3390f..2bf89c9bf 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -306,6 +306,14 @@ rule token = parse { LOAD (fun a o -> (v128_load32_zero (opt a 2)) o) } | "v128.load64_zero" { LOAD (fun a o -> (v128_load64_zero (opt a 3)) o) } + | "v128.load8_lane" + { SIMD_LOAD_LANE (fun a o i -> (v128_load8_lane (opt a 0)) o i) } + | "v128.load16_lane" + { SIMD_LOAD_LANE (fun a o i -> (v128_load16_lane (opt a 1)) o i) } + | "v128.load32_lane" + { SIMD_LOAD_LANE (fun a o i -> (v128_load32_lane (opt a 2)) o i) } + | "v128.load64_lane" + { SIMD_LOAD_LANE (fun a o i -> (v128_load64_lane (opt a 3)) o i) } | (ixx as t)".store"(mem_size as sz) { if t = "i32" && sz = "32" then error lexbuf "unknown operator"; STORE (fun a o -> diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index 7685ef08d..d69ac52f7 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -204,7 +204,7 @@ let inline_type_explicit (c : context) x ft at = %token NOP DROP BLOCK END IF THEN ELSE SELECT LOOP BR BR_IF BR_TABLE %token CALL CALL_INDIRECT RETURN %token LOCAL_GET LOCAL_SET LOCAL_TEE GLOBAL_GET GLOBAL_SET -%token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT +%token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT SIMD_LOAD_LANE %token SPLAT EXTRACT_LANE REPLACE_LANE SHIFT SHUFFLE %token CONST V128_CONST UNARY BINARY TERNARY TEST COMPARE CONVERT %token UNREACHABLE MEMORY_SIZE MEMORY_GROW @@ -232,6 +232,7 @@ let inline_type_explicit (c : context) x ft at = %token COMPARE %token CONVERT %token Memory.offset -> Ast.instr'> LOAD +%token Memory.offset -> int -> Ast.instr'> SIMD_LOAD_LANE %token SPLAT %token Ast.instr'> EXTRACT_LANE %token Ast.instr'> REPLACE_LANE @@ -385,6 +386,7 @@ plain_instr : | GLOBAL_GET var { fun c -> global_get ($2 c global) } | GLOBAL_SET var { fun c -> global_set ($2 c global) } | LOAD offset_opt align_opt { fun c -> $1 $3 $2 } + | SIMD_LOAD_LANE offset_opt align_opt NAT { let at = at () in fun c -> $1 $3 $2 (simd_lane_index $4 at) } | STORE offset_opt align_opt { fun c -> $1 $3 $2 } | MEMORY_SIZE { fun c -> memory_size } | MEMORY_GROW { fun c -> memory_grow } diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index f91967438..7f195aa57 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -307,6 +307,14 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = check_memop c memop (Lib.Option.map fst) e.at; [I32Type] --> [memop.ty] + | SimdLoadLane (memop, i) -> + check_memop c memop (fun o -> o) e.at; + (match memop.sz with + | Some pack_size -> + require (i < 16 / packed_size pack_size) e.at "invalid lane index"; + [I32Type; V128Type] --> [memop.ty] + | _ -> assert false) + | Store memop -> check_memop c memop (fun sz -> sz) e.at; [I32Type; memop.ty] --> [] diff --git a/test/core/simd/meta/gen_tests.py b/test/core/simd/meta/gen_tests.py index 7ea8436b3..e1c03ecd2 100644 --- a/test/core/simd/meta/gen_tests.py +++ b/test/core/simd/meta/gen_tests.py @@ -31,6 +31,7 @@ 'simd_f32x4_pmin_pmax', 'simd_f64x2_pmin_pmax', 'simd_i32x4_dot_i16x8', + 'simd_load_lane', ) diff --git a/test/core/simd/meta/simd.py b/test/core/simd/meta/simd.py index 99ba46d57..5ff38bbe8 100644 --- a/test/core/simd/meta/simd.py +++ b/test/core/simd/meta/simd.py @@ -22,7 +22,7 @@ def const(value, value_type): value: constant data, string or list, lane_type: lane type, [i32, i64, f32, f64] """ - return SIMD.CONST.format(value_type=value_type, value=''.join(value)) + return SIMD.CONST.format(value_type=value_type, value=''.join(str(value))) @staticmethod def v128_const(value, lane_type): @@ -81,4 +81,4 @@ def v128_const(value, lane_type): data_elem = ' '.join(data_elem) # Returns v128 constant text - return SIMD.V128_CONST.format(lane_type=lane_type, value=data_elem) \ No newline at end of file + return SIMD.V128_CONST.format(lane_type=lane_type, value=data_elem) diff --git a/test/core/simd/meta/simd_load_lane.py b/test/core/simd/meta/simd_load_lane.py new file mode 100644 index 000000000..2900e9850 --- /dev/null +++ b/test/core/simd/meta/simd_load_lane.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 + +from simd import SIMD +from test_assert import AssertReturn, AssertInvalid + +def list_stringify(l): + return list(map(lambda x: str(x), l)) + +"""Base class for generating SIMD load lane tests. Subclasses only to: + - define self.LANE_LEN, self.LANE_TYPE, self.NUM_LANES, self.MAX_ALIGN + - override get_normal_case to provide test data (consult comments for details) + +It generates test cases that: + - load to all valid lane indices + - load using memarg offset + - load with memarg alignment + - load with invalid lane index + - load with invalid memarg alignment + - fails typecheck +""" +class SimdLoadLane: + def valid_alignments(self): + return [a for a in range(1, self.MAX_ALIGN+1) if a & (a-1) == 0] + + def get_case_data(self): + # return value should be a list of tuples: + # (address to load from : i32, initial value : v128, return value : v128) + # e.g. [(0, [0], [0x0100, 0, 0, 0, 0, 0, 0, 0]), ... ] + raise Exception("Subclasses should override this to provide test data") + + def get_normal_case(self): + s = SIMD() + cases = [] + + # load using arg + for (addr, val, ret) in self.get_case_data(): + i32_addr = s.const(addr, "i32") + v128_val = s.v128_const(list_stringify(val), self.LANE_TYPE) + v128_result = s.v128_const(list_stringify(ret), self.LANE_TYPE) + instr = "v128.load{lane_len}_lane_{idx}".format(lane_len=self.LANE_LEN, idx=addr) + cases.append(str(AssertReturn(instr, [i32_addr, v128_val], v128_result))) + + # load using offset + for (addr, val, ret) in self.get_case_data(): + v128_val = s.v128_const(list_stringify(val), self.LANE_TYPE) + v128_result = s.v128_const(list_stringify(ret), self.LANE_TYPE) + instr = "v128.load{lane_len}_lane_{idx}_offset_{idx}".format(lane_len=self.LANE_LEN, idx=addr) + cases.append(str(AssertReturn(instr, [v128_val], v128_result))) + + # load using offset with alignment + for (addr, val, ret) in self.get_case_data(): + for align in self.valid_alignments(): + i32_addr = s.const(addr, "i32") + v128_val = s.v128_const(list_stringify(val), self.LANE_TYPE) + v128_result = s.v128_const(list_stringify(ret), self.LANE_TYPE) + instr = "v128.load{lane_len}_lane_{idx}_align_{align}".format(lane_len=self.LANE_LEN, idx=addr, align=align) + cases.append(str(AssertReturn(instr, [i32_addr, v128_val], v128_result))) + + return '\n'.join(cases) + + def gen_test_func_template(self): + template = [ + ';; Tests for load lane operations.\n\n', + '(module', + ' (memory 1)', + ' (data (i32.const 0) "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0A\\0B\\0C\\0D\\0E\\0F")', + ] + + lane_indices = list(range(self.NUM_LANES)) + + # load using i32.const arg + for idx in lane_indices: + template.append( + ' (func (export "v128.load{lane_len}_lane_{idx}")\n' + ' (param $address i32) (param $x v128) (result v128)\n' + ' (v128.load{lane_len}_lane {idx} (local.get $address) (local.get $x)))' + .format(idx=idx, lane_len=self.LANE_LEN)) + + # load using memarg offset + for idx in lane_indices: + template.append( + ' (func (export "v128.load{lane_len}_lane_{idx}_offset_{idx}")\n' + ' (param $x v128) (result v128)\n' + ' (v128.load{lane_len}_lane offset={idx} {idx} (i32.const 0) (local.get $x)))' + .format(idx=idx, lane_len=self.LANE_LEN)) + + # with memarg aligment + for idx in lane_indices: + for align in self.valid_alignments(): + template.append( + ' (func (export "v128.load{lane_len}_lane_{idx}_align_{align}")\n' + ' (param $address i32) (param $x v128) (result v128)\n' + ' (v128.load{lane_len}_lane align={align} {idx} (local.get $address) (local.get $x)))' + .format(idx=idx, lane_len=self.LANE_LEN, align=align)) + + template.append(')\n') + return template + + def gen_test_template(self): + template = self.gen_test_func_template() + + template.append('{normal_cases}') + template.append('\n{invalid_cases}') + + return '\n'.join(template) + + def get_invalid_cases(self): + invalid_cases = [';; type check'] + invalid_cases.append( + '(assert_invalid' + ' (module (memory 1)\n' + ' (func (param $x v128) (result v128)\n' + ' (v128.load{lane_len}_lane 0 (local.get $x) (i32.const 0))))\n' + ' "type mismatch")'.format(lane_len=self.LANE_LEN)) + invalid_cases.append('') + + invalid_cases.append(';; invalid lane index') + invalid_cases.append( + '(assert_invalid' + ' (module (memory 1)\n' + ' (func (param $x v128) (result v128)\n' + ' (v128.load{lane_len}_lane {idx} (i32.const 0) (local.get $x))))\n' + ' "invalid lane index")'.format(idx=self.NUM_LANES, lane_len=self.LANE_LEN)) + + invalid_cases.append('') + + invalid_cases.append(';; invalid memarg alignment') + invalid_cases.append( + '(assert_invalid\n' + ' (module (memory 1)\n' + ' (func (param $x v128) (result v128)\n' + ' (v128.load{lane_len}_lane align={align} 0 (i32.const 0) (local.get $x))))\n' + ' "alignment must not be larger than natural")' + .format(lane_len=self.LANE_LEN, align=self.MAX_ALIGN*2)) + return '\n'.join(invalid_cases) + + def get_all_cases(self): + case_data = {'lane_len': self.LANE_LEN, + 'normal_cases': self.get_normal_case(), + 'invalid_cases': self.get_invalid_cases(), + } + return self.gen_test_template().format(**case_data) + + def gen_test_cases(self): + wast_filename = '../simd_load{lane_type}_lane.wast'.format(lane_type=self.LANE_LEN) + with open(wast_filename, 'w') as fp: + fp.write(self.get_all_cases()) + +class SimdLoad8Lane(SimdLoadLane): + LANE_LEN = '8' + LANE_TYPE = 'i8x16' + NUM_LANES = 16 + MAX_ALIGN = 1 + + def get_case_data(self): + return [ + (0, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (1, [0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (2, [0], [0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (3, [0], [0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (4, [0], [0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (5, [0], [0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (6, [0], [0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + (7, [0], [0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0]), + (8, [0], [0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0]), + (9, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0]), + (10, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0]), + (11, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0]), + (12, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0]), + (13, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0]), + (14, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0]), + (15, [0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15])] + +class SimdLoad16Lane(SimdLoadLane): + LANE_LEN = '16' + LANE_TYPE = 'i16x8' + NUM_LANES = 8 + MAX_ALIGN = 2 + + def get_case_data(self): + return [ + (0, [0], [0x0100, 0, 0, 0, 0, 0, 0, 0]), + (1, [0], [0, 0x0201, 0, 0, 0, 0, 0, 0]), + (2, [0], [0, 0, 0x0302, 0, 0, 0, 0, 0]), + (3, [0], [0, 0, 0, 0x0403, 0, 0, 0, 0]), + (4, [0], [0, 0, 0, 0, 0x0504, 0, 0, 0]), + (5, [0], [0, 0, 0, 0, 0, 0x0605, 0, 0]), + (6, [0], [0, 0, 0, 0, 0, 0, 0x0706, 0]), + (7, [0], [0, 0, 0, 0, 0, 0, 0, 0x0807])] + +class SimdLoad32Lane(SimdLoadLane): + LANE_LEN = '32' + LANE_TYPE = 'i32x4' + NUM_LANES = 4 + MAX_ALIGN = 4 + + def get_case_data(self): + return [ + (0, [0], [0x03020100, 0, 0, 0,]), + (1, [0], [0, 0x04030201, 0, 0,]), + (2, [0], [0, 0, 0x05040302, 0,]), + (3, [0], [0, 0, 0, 0x06050403,])] + +class SimdLoad64Lane(SimdLoadLane): + LANE_LEN = '64' + LANE_TYPE = 'i64x2' + NUM_LANES = 2 + MAX_ALIGN = 8 + + def get_case_data(self): + return [ + (0, [0], [0x0706050403020100, 0]), + (1, [0], [0, 0x0807060504030201])] + +def gen_test_cases(): + simd_load8_lane = SimdLoad8Lane() + simd_load8_lane.gen_test_cases() + simd_load16_lane = SimdLoad16Lane() + simd_load16_lane.gen_test_cases() + simd_load32_lane = SimdLoad32Lane() + simd_load32_lane.gen_test_cases() + simd_load64_lane = SimdLoad64Lane() + simd_load64_lane.gen_test_cases() + + +if __name__ == '__main__': + gen_test_cases() diff --git a/test/core/simd/simd_load16_lane.wast b/test/core/simd/simd_load16_lane.wast new file mode 100644 index 000000000..8c72a5733 --- /dev/null +++ b/test/core/simd/simd_load16_lane.wast @@ -0,0 +1,211 @@ +;; Tests for load lane operations. + + +(module + (memory 1) + (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F") + (func (export "v128.load16_lane_0") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 0 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 1 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 2 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_3") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 3 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_4") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 4 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_5") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 5 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_6") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 6 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_7") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane 7 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_0_offset_0") + (param $x v128) (result v128) + (v128.load16_lane offset=0 0 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_1_offset_1") + (param $x v128) (result v128) + (v128.load16_lane offset=1 1 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_2_offset_2") + (param $x v128) (result v128) + (v128.load16_lane offset=2 2 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_3_offset_3") + (param $x v128) (result v128) + (v128.load16_lane offset=3 3 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_4_offset_4") + (param $x v128) (result v128) + (v128.load16_lane offset=4 4 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_5_offset_5") + (param $x v128) (result v128) + (v128.load16_lane offset=5 5 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_6_offset_6") + (param $x v128) (result v128) + (v128.load16_lane offset=6 6 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_7_offset_7") + (param $x v128) (result v128) + (v128.load16_lane offset=7 7 (i32.const 0) (local.get $x))) + (func (export "v128.load16_lane_0_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 0 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_0_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 0 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_1_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 1 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_1_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 1 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_2_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 2 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_2_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 2 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_3_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 3 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_3_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 3 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_4_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 4 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_4_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 4 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_5_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 5 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_5_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 5 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_6_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 6 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_6_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 6 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_7_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=1 7 (local.get $address) (local.get $x))) + (func (export "v128.load16_lane_7_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load16_lane align=2 7 (local.get $address) (local.get $x))) +) + +(assert_return (invoke "v128.load16_lane_0" (i32.const 0) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 256 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_1" (i32.const 1) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 513 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_2" (i32.const 2) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 770 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_3" (i32.const 3) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 1027 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_4" (i32.const 4) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 1284 0 0 0)) +(assert_return (invoke "v128.load16_lane_5" (i32.const 5) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 1541 0 0)) +(assert_return (invoke "v128.load16_lane_6" (i32.const 6) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 1798 0)) +(assert_return (invoke "v128.load16_lane_7" (i32.const 7) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 0 2055)) +(assert_return (invoke "v128.load16_lane_0_offset_0" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 256 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_1_offset_1" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 513 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_2_offset_2" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 770 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_3_offset_3" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 1027 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_4_offset_4" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 1284 0 0 0)) +(assert_return (invoke "v128.load16_lane_5_offset_5" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 1541 0 0)) +(assert_return (invoke "v128.load16_lane_6_offset_6" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 1798 0)) +(assert_return (invoke "v128.load16_lane_7_offset_7" (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 0 2055)) +(assert_return (invoke "v128.load16_lane_0_align_1" (i32.const 0) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 256 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_0_align_2" (i32.const 0) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 256 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_1_align_1" (i32.const 1) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 513 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_1_align_2" (i32.const 1) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 513 0 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_2_align_1" (i32.const 2) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 770 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_2_align_2" (i32.const 2) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 770 0 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_3_align_1" (i32.const 3) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 1027 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_3_align_2" (i32.const 3) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 1027 0 0 0 0)) +(assert_return (invoke "v128.load16_lane_4_align_1" (i32.const 4) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 1284 0 0 0)) +(assert_return (invoke "v128.load16_lane_4_align_2" (i32.const 4) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 1284 0 0 0)) +(assert_return (invoke "v128.load16_lane_5_align_1" (i32.const 5) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 1541 0 0)) +(assert_return (invoke "v128.load16_lane_5_align_2" (i32.const 5) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 1541 0 0)) +(assert_return (invoke "v128.load16_lane_6_align_1" (i32.const 6) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 1798 0)) +(assert_return (invoke "v128.load16_lane_6_align_2" (i32.const 6) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 1798 0)) +(assert_return (invoke "v128.load16_lane_7_align_1" (i32.const 7) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 0 2055)) +(assert_return (invoke "v128.load16_lane_7_align_2" (i32.const 7) + (v128.const i16x8 0 0 0 0 0 0 0 0)) + (v128.const i16x8 0 0 0 0 0 0 0 2055)) + +;; type check +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load16_lane 0 (local.get $x) (i32.const 0)))) + "type mismatch") + +;; invalid lane index +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load16_lane 8 (i32.const 0) (local.get $x)))) + "invalid lane index") + +;; invalid memarg alignment +(assert_invalid + (module (memory 1) + (func (param $x v128) (result v128) + (v128.load16_lane align=4 0 (i32.const 0) (local.get $x)))) + "alignment must not be larger than natural") \ No newline at end of file diff --git a/test/core/simd/simd_load32_lane.wast b/test/core/simd/simd_load32_lane.wast new file mode 100644 index 000000000..e67690ff9 --- /dev/null +++ b/test/core/simd/simd_load32_lane.wast @@ -0,0 +1,143 @@ +;; Tests for load lane operations. + + +(module + (memory 1) + (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F") + (func (export "v128.load32_lane_0") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane 0 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_1") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane 1 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_2") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane 2 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_3") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane 3 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_0_offset_0") + (param $x v128) (result v128) + (v128.load32_lane offset=0 0 (i32.const 0) (local.get $x))) + (func (export "v128.load32_lane_1_offset_1") + (param $x v128) (result v128) + (v128.load32_lane offset=1 1 (i32.const 0) (local.get $x))) + (func (export "v128.load32_lane_2_offset_2") + (param $x v128) (result v128) + (v128.load32_lane offset=2 2 (i32.const 0) (local.get $x))) + (func (export "v128.load32_lane_3_offset_3") + (param $x v128) (result v128) + (v128.load32_lane offset=3 3 (i32.const 0) (local.get $x))) + (func (export "v128.load32_lane_0_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=1 0 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_0_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=2 0 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_0_align_4") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=4 0 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_1_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=1 1 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_1_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=2 1 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_1_align_4") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=4 1 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_2_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=1 2 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_2_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=2 2 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_2_align_4") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=4 2 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_3_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=1 3 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_3_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=2 3 (local.get $address) (local.get $x))) + (func (export "v128.load32_lane_3_align_4") + (param $address i32) (param $x v128) (result v128) + (v128.load32_lane align=4 3 (local.get $address) (local.get $x))) +) + +(assert_return (invoke "v128.load32_lane_0" (i32.const 0) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 50462976 0 0 0)) +(assert_return (invoke "v128.load32_lane_1" (i32.const 1) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 67305985 0 0)) +(assert_return (invoke "v128.load32_lane_2" (i32.const 2) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 84148994 0)) +(assert_return (invoke "v128.load32_lane_3" (i32.const 3) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 0 100992003)) +(assert_return (invoke "v128.load32_lane_0_offset_0" (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 50462976 0 0 0)) +(assert_return (invoke "v128.load32_lane_1_offset_1" (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 67305985 0 0)) +(assert_return (invoke "v128.load32_lane_2_offset_2" (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 84148994 0)) +(assert_return (invoke "v128.load32_lane_3_offset_3" (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 0 100992003)) +(assert_return (invoke "v128.load32_lane_0_align_1" (i32.const 0) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 50462976 0 0 0)) +(assert_return (invoke "v128.load32_lane_0_align_2" (i32.const 0) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 50462976 0 0 0)) +(assert_return (invoke "v128.load32_lane_0_align_4" (i32.const 0) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 50462976 0 0 0)) +(assert_return (invoke "v128.load32_lane_1_align_1" (i32.const 1) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 67305985 0 0)) +(assert_return (invoke "v128.load32_lane_1_align_2" (i32.const 1) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 67305985 0 0)) +(assert_return (invoke "v128.load32_lane_1_align_4" (i32.const 1) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 67305985 0 0)) +(assert_return (invoke "v128.load32_lane_2_align_1" (i32.const 2) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 84148994 0)) +(assert_return (invoke "v128.load32_lane_2_align_2" (i32.const 2) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 84148994 0)) +(assert_return (invoke "v128.load32_lane_2_align_4" (i32.const 2) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 84148994 0)) +(assert_return (invoke "v128.load32_lane_3_align_1" (i32.const 3) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 0 100992003)) +(assert_return (invoke "v128.load32_lane_3_align_2" (i32.const 3) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 0 100992003)) +(assert_return (invoke "v128.load32_lane_3_align_4" (i32.const 3) + (v128.const i32x4 0 0 0 0)) + (v128.const i32x4 0 0 0 100992003)) + +;; type check +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load32_lane 0 (local.get $x) (i32.const 0)))) + "type mismatch") + +;; invalid lane index +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load32_lane 4 (i32.const 0) (local.get $x)))) + "invalid lane index") + +;; invalid memarg alignment +(assert_invalid + (module (memory 1) + (func (param $x v128) (result v128) + (v128.load32_lane align=8 0 (i32.const 0) (local.get $x)))) + "alignment must not be larger than natural") \ No newline at end of file diff --git a/test/core/simd/simd_load64_lane.wast b/test/core/simd/simd_load64_lane.wast new file mode 100644 index 000000000..5883a6eae --- /dev/null +++ b/test/core/simd/simd_load64_lane.wast @@ -0,0 +1,97 @@ +;; Tests for load lane operations. + + +(module + (memory 1) + (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F") + (func (export "v128.load64_lane_0") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane 0 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_1") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane 1 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_0_offset_0") + (param $x v128) (result v128) + (v128.load64_lane offset=0 0 (i32.const 0) (local.get $x))) + (func (export "v128.load64_lane_1_offset_1") + (param $x v128) (result v128) + (v128.load64_lane offset=1 1 (i32.const 0) (local.get $x))) + (func (export "v128.load64_lane_0_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=1 0 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_0_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=2 0 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_0_align_4") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=4 0 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_0_align_8") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=8 0 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_1_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=1 1 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_1_align_2") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=2 1 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_1_align_4") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=4 1 (local.get $address) (local.get $x))) + (func (export "v128.load64_lane_1_align_8") + (param $address i32) (param $x v128) (result v128) + (v128.load64_lane align=8 1 (local.get $address) (local.get $x))) +) + +(assert_return (invoke "v128.load64_lane_0" (i32.const 0) + (v128.const i64x2 0 0)) + (v128.const i64x2 506097522914230528 0)) +(assert_return (invoke "v128.load64_lane_1" (i32.const 1) + (v128.const i64x2 0 0)) + (v128.const i64x2 0 578437695752307201)) +(assert_return (invoke "v128.load64_lane_0_offset_0" (v128.const i64x2 0 0)) + (v128.const i64x2 506097522914230528 0)) +(assert_return (invoke "v128.load64_lane_1_offset_1" (v128.const i64x2 0 0)) + (v128.const i64x2 0 578437695752307201)) +(assert_return (invoke "v128.load64_lane_0_align_1" (i32.const 0) + (v128.const i64x2 0 0)) + (v128.const i64x2 506097522914230528 0)) +(assert_return (invoke "v128.load64_lane_0_align_2" (i32.const 0) + (v128.const i64x2 0 0)) + (v128.const i64x2 506097522914230528 0)) +(assert_return (invoke "v128.load64_lane_0_align_4" (i32.const 0) + (v128.const i64x2 0 0)) + (v128.const i64x2 506097522914230528 0)) +(assert_return (invoke "v128.load64_lane_0_align_8" (i32.const 0) + (v128.const i64x2 0 0)) + (v128.const i64x2 506097522914230528 0)) +(assert_return (invoke "v128.load64_lane_1_align_1" (i32.const 1) + (v128.const i64x2 0 0)) + (v128.const i64x2 0 578437695752307201)) +(assert_return (invoke "v128.load64_lane_1_align_2" (i32.const 1) + (v128.const i64x2 0 0)) + (v128.const i64x2 0 578437695752307201)) +(assert_return (invoke "v128.load64_lane_1_align_4" (i32.const 1) + (v128.const i64x2 0 0)) + (v128.const i64x2 0 578437695752307201)) +(assert_return (invoke "v128.load64_lane_1_align_8" (i32.const 1) + (v128.const i64x2 0 0)) + (v128.const i64x2 0 578437695752307201)) + +;; type check +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load64_lane 0 (local.get $x) (i32.const 0)))) + "type mismatch") + +;; invalid lane index +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load64_lane 2 (i32.const 0) (local.get $x)))) + "invalid lane index") + +;; invalid memarg alignment +(assert_invalid + (module (memory 1) + (func (param $x v128) (result v128) + (v128.load64_lane align=16 0 (i32.const 0) (local.get $x)))) + "alignment must not be larger than natural") \ No newline at end of file diff --git a/test/core/simd/simd_load8_lane.wast b/test/core/simd/simd_load8_lane.wast new file mode 100644 index 000000000..d0706f535 --- /dev/null +++ b/test/core/simd/simd_load8_lane.wast @@ -0,0 +1,299 @@ +;; Tests for load lane operations. + + +(module + (memory 1) + (data (i32.const 0) "\00\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F") + (func (export "v128.load8_lane_0") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 0 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 1 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_2") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 2 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_3") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 3 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_4") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 4 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_5") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 5 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_6") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 6 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_7") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 7 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_8") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 8 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_9") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 9 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_10") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 10 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_11") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 11 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_12") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 12 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_13") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 13 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_14") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 14 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_15") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane 15 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_0_offset_0") + (param $x v128) (result v128) + (v128.load8_lane offset=0 0 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_1_offset_1") + (param $x v128) (result v128) + (v128.load8_lane offset=1 1 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_2_offset_2") + (param $x v128) (result v128) + (v128.load8_lane offset=2 2 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_3_offset_3") + (param $x v128) (result v128) + (v128.load8_lane offset=3 3 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_4_offset_4") + (param $x v128) (result v128) + (v128.load8_lane offset=4 4 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_5_offset_5") + (param $x v128) (result v128) + (v128.load8_lane offset=5 5 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_6_offset_6") + (param $x v128) (result v128) + (v128.load8_lane offset=6 6 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_7_offset_7") + (param $x v128) (result v128) + (v128.load8_lane offset=7 7 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_8_offset_8") + (param $x v128) (result v128) + (v128.load8_lane offset=8 8 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_9_offset_9") + (param $x v128) (result v128) + (v128.load8_lane offset=9 9 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_10_offset_10") + (param $x v128) (result v128) + (v128.load8_lane offset=10 10 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_11_offset_11") + (param $x v128) (result v128) + (v128.load8_lane offset=11 11 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_12_offset_12") + (param $x v128) (result v128) + (v128.load8_lane offset=12 12 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_13_offset_13") + (param $x v128) (result v128) + (v128.load8_lane offset=13 13 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_14_offset_14") + (param $x v128) (result v128) + (v128.load8_lane offset=14 14 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_15_offset_15") + (param $x v128) (result v128) + (v128.load8_lane offset=15 15 (i32.const 0) (local.get $x))) + (func (export "v128.load8_lane_0_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 0 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_1_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 1 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_2_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 2 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_3_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 3 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_4_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 4 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_5_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 5 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_6_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 6 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_7_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 7 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_8_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 8 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_9_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 9 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_10_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 10 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_11_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 11 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_12_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 12 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_13_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 13 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_14_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 14 (local.get $address) (local.get $x))) + (func (export "v128.load8_lane_15_align_1") + (param $address i32) (param $x v128) (result v128) + (v128.load8_lane align=1 15 (local.get $address) (local.get $x))) +) + +(assert_return (invoke "v128.load8_lane_0" (i32.const 0) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_1" (i32.const 1) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_2" (i32.const 2) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_3" (i32.const 3) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_4" (i32.const 4) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_5" (i32.const 5) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_6" (i32.const 6) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_7" (i32.const 7) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_8" (i32.const 8) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_9" (i32.const 9) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_10" (i32.const 10) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_11" (i32.const 11) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_12" (i32.const 12) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 12 0 0 0)) +(assert_return (invoke "v128.load8_lane_13" (i32.const 13) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 0)) +(assert_return (invoke "v128.load8_lane_14" (i32.const 14) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0)) +(assert_return (invoke "v128.load8_lane_15" (i32.const 15) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15)) +(assert_return (invoke "v128.load8_lane_0_offset_0" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_1_offset_1" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_2_offset_2" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_3_offset_3" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_4_offset_4" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_5_offset_5" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_6_offset_6" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_7_offset_7" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_8_offset_8" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_9_offset_9" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_10_offset_10" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_11_offset_11" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_12_offset_12" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 12 0 0 0)) +(assert_return (invoke "v128.load8_lane_13_offset_13" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 0)) +(assert_return (invoke "v128.load8_lane_14_offset_14" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0)) +(assert_return (invoke "v128.load8_lane_15_offset_15" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15)) +(assert_return (invoke "v128.load8_lane_0_align_1" (i32.const 0) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_1_align_1" (i32.const 1) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_2_align_1" (i32.const 2) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_3_align_1" (i32.const 3) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_4_align_1" (i32.const 4) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_5_align_1" (i32.const 5) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_6_align_1" (i32.const 6) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_7_align_1" (i32.const 7) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_8_align_1" (i32.const 8) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_9_align_1" (i32.const 9) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_10_align_1" (i32.const 10) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_11_align_1" (i32.const 11) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0)) +(assert_return (invoke "v128.load8_lane_12_align_1" (i32.const 12) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 12 0 0 0)) +(assert_return (invoke "v128.load8_lane_13_align_1" (i32.const 13) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 13 0 0)) +(assert_return (invoke "v128.load8_lane_14_align_1" (i32.const 14) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 0)) +(assert_return (invoke "v128.load8_lane_15_align_1" (i32.const 15) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15)) + +;; type check +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load8_lane 0 (local.get $x) (i32.const 0)))) + "type mismatch") + +;; invalid lane index +(assert_invalid (module (memory 1) + (func (param $x v128) (result v128) + (v128.load8_lane 16 (i32.const 0) (local.get $x)))) + "invalid lane index") + +;; invalid memarg alignment +(assert_invalid + (module (memory 1) + (func (param $x v128) (result v128) + (v128.load8_lane align=2 0 (i32.const 0) (local.get $x)))) + "alignment must not be larger than natural") \ No newline at end of file