diff --git a/src/Interpreter/instructions.cpp b/src/Interpreter/instructions.cpp index 04aea160..2eba848d 100644 --- a/src/Interpreter/instructions.cpp +++ b/src/Interpreter/instructions.cpp @@ -1268,6 +1268,31 @@ bool i_instr_conversion(Module *m, uint8_t opcode) { return true; } +bool i_instr_extension(Module *m, uint8_t opcode) { + auto &v = m->stack[m->sp].value; + + switch (opcode) { + case 0xc0: // i32.extend8_s + v.int32 = static_cast(v.int32); + break; + case 0xc1: // i32.extend16_s + v.int32 = static_cast(v.int32); + break; + case 0xc2: // i64.extend8_s + v.int64 = static_cast(v.int64); + break; + case 0xc3: // i64.extend16_s + v.int64 = static_cast(v.int64); + break; + case 0xc4: // i64.extend32_s + v.int64 = static_cast(v.int64); + break; + default: + return false; + } + return true; +} + /** * 0xe0 ... 0xe3 callback operations */ diff --git a/src/Interpreter/instructions.h b/src/Interpreter/instructions.h index 54a80f1b..f58f2cd4 100644 --- a/src/Interpreter/instructions.h +++ b/src/Interpreter/instructions.h @@ -72,4 +72,6 @@ bool i_instr_binary_f64(Module *m, uint8_t opcode); bool i_instr_conversion(Module *m, uint8_t opcode); +bool i_instr_extension(Module *m, uint8_t opcode); + bool i_instr_callback(Module *m, uint8_t opcode); diff --git a/src/Interpreter/interpreter.cpp b/src/Interpreter/interpreter.cpp index 9f22c6ac..834c4f4f 100644 --- a/src/Interpreter/interpreter.cpp +++ b/src/Interpreter/interpreter.cpp @@ -436,6 +436,11 @@ bool Interpreter::interpret(Module *m, bool waiting) { success &= i_instr_conversion(m, opcode); continue; + // extension operations + case 0xc0 ... 0xc4: + success &= i_instr_extension(m, opcode); + continue; + // callback operations case 0xe0 ... 0xe3: success &= i_instr_callback(m, opcode); diff --git a/tests/latch/core/i32_0.asserts.wast b/tests/latch/core/i32_0.asserts.wast index 86378302..3b98ccb7 100644 --- a/tests/latch/core/i32_0.asserts.wast +++ b/tests/latch/core/i32_0.asserts.wast @@ -198,9 +198,13 @@ (assert_return (invoke "popcnt" (i32.const 0xDEADBEEF)) (i32.const 24)) (assert_return (invoke "extend8_s" (i32.const 0)) (i32.const 0)) (assert_return (invoke "extend8_s" (i32.const 0x7f)) (i32.const 127)) + (assert_return (invoke "extend8_s" (i32.const 0x80)) (i32.const -128)) + (assert_return (invoke "extend8_s" (i32.const 0xff)) (i32.const -1)) (assert_return (invoke "extend8_s" (i32.const -1)) (i32.const -1)) (assert_return (invoke "extend16_s" (i32.const 0)) (i32.const 0)) (assert_return (invoke "extend16_s" (i32.const 0x7fff)) (i32.const 32767)) + (assert_return (invoke "extend16_s" (i32.const 0x8000)) (i32.const -32768)) + (assert_return (invoke "extend16_s" (i32.const 0xffff)) (i32.const -1)) (assert_return (invoke "extend16_s" (i32.const -1)) (i32.const -1)) (assert_return (invoke "eqz" (i32.const 0)) (i32.const 1)) (assert_return (invoke "eqz" (i32.const 1)) (i32.const 0)) diff --git a/tests/latch/core/i64_0.asserts.wast b/tests/latch/core/i64_0.asserts.wast index bad63ead..6aef3586 100644 --- a/tests/latch/core/i64_0.asserts.wast +++ b/tests/latch/core/i64_0.asserts.wast @@ -131,9 +131,13 @@ (assert_return (invoke "popcnt" (i64.const 0x00008000)) (i64.const 1)) (assert_return (invoke "extend8_s" (i64.const 0)) (i64.const 0)) (assert_return (invoke "extend8_s" (i64.const 0x7f)) (i64.const 127)) + (assert_return (invoke "extend8_s" (i64.const 0x80)) (i64.const -128)) + (assert_return (invoke "extend8_s" (i64.const 0xff)) (i64.const -1)) (assert_return (invoke "extend8_s" (i64.const -1)) (i64.const -1)) (assert_return (invoke "extend16_s" (i64.const 0)) (i64.const 0)) (assert_return (invoke "extend16_s" (i64.const 0x7fff)) (i64.const 32767)) + (assert_return (invoke "extend16_s" (i64.const 0x8000)) (i64.const -32768)) + (assert_return (invoke "extend16_s" (i64.const 0xffff)) (i64.const -1)) (assert_return (invoke "extend16_s" (i64.const -1)) (i64.const -1)) (assert_return (invoke "extend32_s" (i64.const 0)) (i64.const 0)) (assert_return (invoke "extend32_s" (i64.const 0x7fff)) (i64.const 32767))