#define OVMI_SUB 0x02 // %r = %a - %b
#define OVMI_MUL 0x03 // %r = %a * %b
#define OVMI_DIV 0x04 // %r = %a / %b
-#define OVMI_REM 0x05 // %r = %a % %b
-
-#define OVMI_AND 0x06 // %r = %a & %b
-#define OVMI_OR 0x07 // %r = %a | %b
-#define OVMI_XOR 0x08 // %r = %a ^ %b
-#define OVMI_NOT 0x09 // %r = ~%a
-#define OVMI_SHL 0x0A // %r = %a << %b
-#define OVMI_SHR 0x0B // %r = %a >> %b
-#define OVMI_SAR 0x0C // %r = %a >>> %b
+#define OVMI_DIV_S 0x05 // %r = %a / %b
+#define OVMI_REM 0x06 // %r = %a % %b
+#define OVMI_REM_S 0x07 // %r = %a % %b
+
+#define OVMI_AND 0x08 // %r = %a & %b
+#define OVMI_OR 0x09 // %r = %a | %b
+#define OVMI_XOR 0x0A // %r = %a ^ %b
+#define OVMI_NOT 0x0B // %r = ~%a // This one might not be needed, as WASM doesn't provide it
+#define OVMI_SHL 0x0C // %r = %a << %b
+#define OVMI_SHR 0x0D // %r = %a >> %b
+#define OVMI_SAR 0x0E // %r = %a >>> %b
#define OVMI_IMM 0x10 // %r = i/l/f/d
#define OVMI_MOV 0x10 // %r = %a
#define OVMI_CLZ 0x50 // %r = clz(%a)
#define OVMI_CTZ 0x51 // %r = ctr(%a)
#define OVMI_POPCNT 0x52 // %r = popcnt(%a)
+#define OVMI_ROTL 0x53 // %r = rotl(%a, %b)
+#define OVMI_ROTR 0x54 // %r = rotr(%a, %b)
+
+// These instructions are only implemented for floats.
+#define OVMI_ABS 0x55 // %r = |%a|
+#define OVMI_NEG 0x56 // %r = -%a
+#define OVMI_CEIL 0x57 // %r = ceil(%a)
+#define OVMI_FLOOR 0x58 // %r = floor(%a)
+#define OVMI_TRUNC 0x59 // %r = trunc(%a)
+#define OVMI_NEAREST 0x5A // %r = nearest(%a)
+#define OVMI_SQRT 0x5B // %r = sqrt(%a)
+#define OVMI_MIN 0x5C // %r = min(%a, %b)
+#define OVMI_MAX 0x5D // %r = max(%a, %b)
+#define OVMI_COPYSIGN 0x5E // %r = copysign(%a, %b)
// For conversion operations, the "type" of the instruction is
// destination type, the type in the name is the source type.
+//
+// There are a couple of cast operations that are not available,
+// such as unsigned conversion from 32-bit integers to floats.
#define OVMI_CVT_I8 0x60 // %r = (t) %a
-#define OVMI_CVT_I16 0x61 // %r = (t) %a
-#define OVMI_CVT_I32 0x62 // %r = (t) %a
-#define OVMI_CVT_I64 0x63 // %r = (t) %a
-#define OVMI_CVT_F32 0x64 // %r = (t) %a
-#define OVMI_CVT_F64 0x65 // %r = (t) %a
-#define OVMI_EXTEND_I8 0x66 // %r = (t) %a (sign extension for integers)
-#define OVMI_EXTEND_I16 0x67 // %r = (t) %a (sign extension for integers)
-#define OVMI_EXTEND_I32 0x68 // %r = (t) %a (sign extension for integers)
+#define OVMI_CVT_I8_S 0x61 // %r = (t) %a (sign aware)
+#define OVMI_CVT_I16 0x62 // %r = (t) %a
+#define OVMI_CVT_I16_S 0x63 // %r = (t) %a (sign aware)
+#define OVMI_CVT_I32 0x64 // %r = (t) %a
+#define OVMI_CVT_I32_S 0x65 // %r = (t) %a (sign aware)
+#define OVMI_CVT_I64 0x66 // %r = (t) %a
+#define OVMI_CVT_I64_S 0x67 // %r = (t) %a (sign aware)
+#define OVMI_CVT_F32 0x68 // %r = (t) %a
+#define OVMI_CVT_F64 0x69 // %r = (t) %a
+#define OVMI_TRANSMUTE_I32 0x6A // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_I64 0x6B // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F32 0x6C // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F64 0x6D // %r = *(t *) &%a (reinterpret bytes)
//
// OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32) == instruction for adding i32s
ovm_code_builder_t ovm_code_builder_new(ovm_program_t *program, i32 param_count, i32 local_count);
void ovm_code_builder_free(ovm_code_builder_t *builder);
void ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr);
+void ovm_code_builder_add_unop(ovm_code_builder_t *builder, u32 instr);
void ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *imm);
void ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 instr_delta);
void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx);
void ovm_code_builder_add_return(ovm_code_builder_t *builder);
-void ovm_code_builder_add_call(ovm_code_builder_t *builder, i32 param_count);
-void ovm_code_builder_add_indirect_call(ovm_code_builder_t *builder, i32 param_count);
+void ovm_code_builder_add_call(ovm_code_builder_t *builder, i32 func_idx, i32 param_count, bool has_return_value);
+void ovm_code_builder_add_indirect_call(ovm_code_builder_t *builder, i32 param_count, bool has_return_value);
void ovm_code_builder_drop_value(ovm_code_builder_t *builder);
void ovm_code_builder_add_local_get(ovm_code_builder_t *builder, i32 local_idx);
void ovm_code_builder_add_local_set(ovm_code_builder_t *builder, i32 local_idx);
void ovm_code_builder_add_register_get(ovm_code_builder_t *builder, i32 local_idx);
void ovm_code_builder_add_register_set(ovm_code_builder_t *builder, i32 local_idx);
void ovm_code_builder_add_load(ovm_code_builder_t *builder, u32 ovm_type, i32 offset);
+void ovm_code_builder_add_store(ovm_code_builder_t *builder, u32 ovm_type, i32 offset);
#endif
builder.next_label_idx = 0;
builder.label_stack = NULL;
+ builder.branch_patches = NULL;
bh_arr_new(bh_heap_allocator(), builder.label_stack, 32);
bh_arr_new(bh_heap_allocator(), builder.branch_patches, 32);
}
void ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *imm) {
- ovm_instr_t imm_instr;
+ ovm_instr_t imm_instr = {0};
imm_instr.full_instr = OVM_TYPED_INSTR(OVMI_IMM, ovm_type);
imm_instr.r = NEXT_VALUE(builder);
PUSH_VALUE(builder, imm_instr.r);
}
+void ovm_code_builder_add_unop(ovm_code_builder_t *builder, u32 instr) {
+ i32 operand = POP_VALUE(builder);
+
+ ovm_instr_t unop = {0};
+ unop.full_instr = instr;
+ unop.r = NEXT_VALUE(builder);
+ unop.a = operand;
+
+ ovm_program_add_instructions(builder->program, 1, &unop);
+ PUSH_VALUE(builder, unop.r);
+}
+
+void ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 instr_delta) {
+
+}
+
+void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx) {
+
+}
+
+void ovm_code_builder_add_return(ovm_code_builder_t *builder) {
+ ovm_instr_t instr = {0};
+ instr.full_instr = OVMI_RETURN;
+
+ i32 values_on_stack = bh_arr_length(builder->execution_stack);
+ assert(values_on_stack == 0 || values_on_stack == 1);
+
+ if (values_on_stack == 1) {
+ instr.a = POP_VALUE(builder);
+ }
+
+ ovm_program_add_instructions(builder->program, 1, &instr);
+}
+
+static void ovm_code_builder_add_params(ovm_code_builder_t *builder, i32 param_count) {
+ fori (i, 0, param_count) {
+ ovm_instr_t param_instr = {0};
+ param_instr.full_instr = OVMI_PARAM;
+ param_instr.a = POP_VALUE(builder);
+
+ ovm_program_add_instructions(builder->program, 1, ¶m_instr);
+ }
+}
+
+void ovm_code_builder_add_call(ovm_code_builder_t *builder, i32 func_idx, i32 param_count, bool has_return_value) {
+ ovm_code_builder_add_params(builder, param_count);
+
+ ovm_instr_t call_instr = {0};
+ call_instr.full_instr = OVMI_CALL;
+ call_instr.a = func_idx;
+ call_instr.r = -1;
+
+ if (has_return_value) {
+ call_instr.r = NEXT_VALUE(builder);
+ }
+
+ ovm_program_add_instructions(builder->program, 1, &call_instr);
+
+ if (has_return_value) {
+ PUSH_VALUE(builder, call_instr.r);
+ }
+}
+
+void ovm_code_builder_add_indirect_call(ovm_code_builder_t *builder, i32 param_count, bool has_return_value) {
+ ovm_instr_t call_instr = {0};
+ call_instr.full_instr = OVMI_CALLI;
+ call_instr.a = POP_VALUE(builder);
+ call_instr.r = -1;
+
+ ovm_code_builder_add_params(builder, param_count);
+
+ if (has_return_value) {
+ call_instr.r = NEXT_VALUE(builder);
+ }
+
+ ovm_program_add_instructions(builder->program, 1, &call_instr);
+
+ if (has_return_value) {
+ PUSH_VALUE(builder, call_instr.r);
+ }
+}
+
+void ovm_code_builder_drop_value(ovm_code_builder_t *builder) {
+ POP_VALUE(builder);
+}
+
+void ovm_code_builder_add_local_get(ovm_code_builder_t *builder, i32 local_idx) {
+ ovm_instr_t instr = {0};
+ instr.full_instr = OVMI_MOV;
+ instr.r = NEXT_VALUE(builder);
+ instr.a = local_idx; // This makes the assumption that the params will be in
+ // the lower "address space" of the value numbers. This
+ // will be true for web assembly, because that's how it
+ // it was spec'd; but in the future for other things,
+ // this will be incorrect.
+
+ ovm_program_add_instructions(builder->program, 1, &instr);
+
+ PUSH_VALUE(builder, instr.r);
+}
+
+void ovm_code_builder_add_local_set(ovm_code_builder_t *builder, i32 local_idx) {
+ ovm_instr_t instr = {0};
+ instr.full_instr = OVMI_MOV;
+ instr.r = local_idx; // This makes the assumption that the params will be in
+ // the lower "address space" of the value numbers. This
+ // will be true for web assembly, because that's how it
+ // it was spec'd; but in the future for other things,
+ // this will be incorrect.
+ instr.a = POP_VALUE(builder);
+
+ ovm_program_add_instructions(builder->program, 1, &instr);
+}
+
+void ovm_code_builder_add_register_get(ovm_code_builder_t *builder, i32 reg_idx) {
+ ovm_instr_t instr = {0};
+ instr.full_instr = OVMI_REG_GET;
+ instr.r = NEXT_VALUE(builder);
+ instr.a = reg_idx;
+
+ ovm_program_add_instructions(builder->program, 1, &instr);
+
+ PUSH_VALUE(builder, instr.r);
+}
+
+void ovm_code_builder_add_register_set(ovm_code_builder_t *builder, i32 reg_idx) {
+ ovm_instr_t instr = {0};
+ instr.full_instr = OVMI_REG_SET;
+ instr.r = reg_idx;
+ instr.a = POP_VALUE(builder);
+
+ ovm_program_add_instructions(builder->program, 1, &instr);
+}
+
+void ovm_code_builder_add_load(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
+ if (offset == 0) {
+ ovm_instr_t load_instr = {0};
+ load_instr.full_instr = OVM_TYPED_INSTR(OVMI_LOAD, ovm_type);
+ load_instr.a = POP_VALUE(builder);
+ load_instr.r = NEXT_VALUE(builder);
+
+ ovm_program_add_instructions(builder->program, 1, &load_instr);
+
+ PUSH_VALUE(builder, load_instr.r);
+ return;
+ }
+
+ ovm_instr_t instrs[3] = {0};
+ // imm.i32 %n, offset
+ instrs[0].full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32);
+ instrs[0].i = offset;
+ instrs[0].r = NEXT_VALUE(builder);
+
+ // add.i32 %n, %n, %i
+ instrs[1].full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32);
+ instrs[1].r = instrs[0].r;
+ instrs[1].a = instrs[0].r;
+ instrs[1].b = POP_VALUE(builder);
+
+ // load.x %m, %n
+ instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_LOAD, ovm_type);
+ instrs[2].r = NEXT_VALUE(builder);
+ instrs[2].a = instrs[1].r;
+
+ ovm_program_add_instructions(builder->program, 3, instrs);
+
+ PUSH_VALUE(builder, instrs[2].r);
+}
+
+void ovm_code_builder_add_store(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
+ if (offset == 0) {
+ ovm_instr_t store_instr = {0};
+ store_instr.full_instr = OVM_TYPED_INSTR(OVMI_STORE, ovm_type);
+ store_instr.b = POP_VALUE(builder);
+ store_instr.a = POP_VALUE(builder);
+
+ ovm_program_add_instructions(builder->program, 1, &store_instr);
+ return;
+ }
+
+ ovm_instr_t instrs[3] = {0};
+ instrs[2].b = POP_VALUE(builder);
+
+ // imm.i32 %n, offset
+ instrs[0].full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32);
+ instrs[0].i = offset;
+ instrs[0].r = NEXT_VALUE(builder);
+
+ // add.i32 %n, %n, %i
+ instrs[1].full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32);
+ instrs[1].r = instrs[0].r;
+ instrs[1].a = instrs[0].r;
+ instrs[1].b = POP_VALUE(builder);
+
+ // store.x %m, %n
+ instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_STORE, ovm_type);
+ instrs[2].a = instrs[1].r;
+
+ ovm_program_add_instructions(builder->program, 3, instrs);
+}
+
#include "vm.h"
#include <sys/mman.h>
+#include <x86intrin.h>
+#include <math.h> // REMOVE THIS!!! only needed for sqrt
//
// Store
C(OVMI_BRI_Z)
C(OVMI_BRI_NZ)
+ C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I8))
+ C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I16))
+ C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I32))
+ C(OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I64))
+ C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I8))
+ C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I16))
+ C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I32))
+ C(OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I64))
+ C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I8))
+ C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I16))
+ C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I32))
+ C(OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I64))
+ C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I8))
+ C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I16))
+ C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I32))
+ C(OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I64))
+ C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I8))
+ C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I16))
+ C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I32))
+ C(OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I64))
+
+ C(OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F32))
+ C(OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F32))
+
+ C(OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F64))
+ C(OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F64))
+
C(OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I16))
C(OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I32))
C(OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I64))
return bh_arr_pop(state->numbered_values);
}
+static inline double __ovm_abs(double f) {
+ return f >= 0 ? f : -f;
+}
+
+static inline double __ovm_floor(double f) {
+ if (f < 0) {
+ return (double) (((long long) f) - 1);
+ } else {
+ return (double) (long long) f;
+ }
+}
+
+static inline double __ovm_ceil(double f) {
+ if (f - (long long) f == 0) {
+ return (double) (long long) f;
+ } else {
+ return __ovm_floor(f) + 1;
+ }
+}
+
+static inline double __ovm_trunc(double f) {
+ return (double) (long long) f;
+}
+
+static inline double __ovm_nearest(double f) {
+ if (f > 0 && f <= 0.5) {
+ return +0;
+ }
+
+ if (f >= -0.5 && f < 0) {
+ return -0;
+ }
+
+ if (f - __ovm_floor(f) < 0.5) return __ovm_floor(f);
+ else return __ovm_ceil(f);
+}
+
+static inline double __ovm_copysign(a, b) double a, b; {
+ if ((a > 0 && b > 0) || (a < 0 && b < 0)) return a;
+ return -a;
+}
+
void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *program) {
assert(engine);
#undef OVM_OP
+#define OVM_OP(i, t, func, ctype) \
+ case OVM_TYPED_INSTR(i, t): \
+ VAL(instr.r).type = t; \
+ VAL(instr.r).ctype = func( VAL(instr.a).ctype, VAL(instr.b).ctype ); \
+ break;
+
+ OVM_OP(OVMI_ROTL, OVM_TYPE_I8 , __rolb, i8)
+ OVM_OP(OVMI_ROTL, OVM_TYPE_I16, __rolw, i16)
+ OVM_OP(OVMI_ROTL, OVM_TYPE_I32, __rold, i32)
+ OVM_OP(OVMI_ROTL, OVM_TYPE_I64, __rolq, i64)
+
+ OVM_OP(OVMI_ROTR, OVM_TYPE_I8 , __rorb, i8)
+ OVM_OP(OVMI_ROTR, OVM_TYPE_I16, __rorw, i16)
+ OVM_OP(OVMI_ROTR, OVM_TYPE_I32, __rord, i32)
+ OVM_OP(OVMI_ROTR, OVM_TYPE_I64, __rorq, i64)
+
+ OVM_OP(OVMI_MIN, OVM_TYPE_F32, bh_min, f32)
+ OVM_OP(OVMI_MAX, OVM_TYPE_F32, bh_max, f32)
+
+ OVM_OP(OVMI_MIN, OVM_TYPE_F64, bh_min, f64)
+ OVM_OP(OVMI_MAX, OVM_TYPE_F64, bh_max, f64)
+
+#undef OVM_OP
+
#define OVM_OP(i, t, op, ctype) \
case OVM_TYPED_INSTR(i, t): \
VAL(instr.r).type = t; \
- VAL(instr.r).ctype = op VAL(instr.a).ctype; \
+ VAL(instr.r).ctype = (ctype) op (VAL(instr.a).ctype); \
break;
OVM_OP(OVMI_NOT, OVM_TYPE_I8 , ~, i8)
OVM_OP(OVMI_NOT, OVM_TYPE_I32, ~, i32)
OVM_OP(OVMI_NOT, OVM_TYPE_I64, ~, i64)
+ OVM_OP(OVMI_CLZ, OVM_TYPE_I8 , __builtin_clz, i8)
+ OVM_OP(OVMI_CLZ, OVM_TYPE_I16, __builtin_clz, i16)
+ OVM_OP(OVMI_CLZ, OVM_TYPE_I32, __builtin_clz, i32)
+ OVM_OP(OVMI_CLZ, OVM_TYPE_I64, __builtin_clz, i64)
+
+ OVM_OP(OVMI_CTZ, OVM_TYPE_I8 , __builtin_ctz, i8)
+ OVM_OP(OVMI_CTZ, OVM_TYPE_I16, __builtin_ctz, i16)
+ OVM_OP(OVMI_CTZ, OVM_TYPE_I32, __builtin_ctz, i32)
+ OVM_OP(OVMI_CTZ, OVM_TYPE_I64, __builtin_ctz, i64)
+
+ OVM_OP(OVMI_POPCNT, OVM_TYPE_I8 , __builtin_popcount, i8)
+ OVM_OP(OVMI_POPCNT, OVM_TYPE_I16, __builtin_popcount, i16)
+ OVM_OP(OVMI_POPCNT, OVM_TYPE_I32, __builtin_popcount, i32)
+ OVM_OP(OVMI_POPCNT, OVM_TYPE_I64, __builtin_popcount, i64)
+
+ OVM_OP(OVMI_ABS, OVM_TYPE_F32, __ovm_abs, f32);
+ OVM_OP(OVMI_NEG, OVM_TYPE_F32, -, f32);
+ OVM_OP(OVMI_CEIL, OVM_TYPE_F32, __ovm_ceil, f32);
+ OVM_OP(OVMI_FLOOR, OVM_TYPE_F32, __ovm_floor, f32);
+ OVM_OP(OVMI_TRUNC, OVM_TYPE_F32, __ovm_trunc, f32);
+ OVM_OP(OVMI_NEAREST, OVM_TYPE_F32, __ovm_nearest, f32);
+ OVM_OP(OVMI_SQRT, OVM_TYPE_F32, sqrt, f32); // TODO: REMOVE THE NEED FOR libm!!!
+
+ OVM_OP(OVMI_ABS, OVM_TYPE_F64, __ovm_abs, f64);
+ OVM_OP(OVMI_NEG, OVM_TYPE_F64, -, f64);
+ OVM_OP(OVMI_CEIL, OVM_TYPE_F64, __ovm_ceil, f64);
+ OVM_OP(OVMI_FLOOR, OVM_TYPE_F64, __ovm_floor, f64);
+ OVM_OP(OVMI_TRUNC, OVM_TYPE_F64, __ovm_trunc, f64);
+ OVM_OP(OVMI_NEAREST, OVM_TYPE_F64, __ovm_nearest, f64);
+ OVM_OP(OVMI_SQRT, OVM_TYPE_F64, sqrt, f64); // TODO: REMOVE THE NEED FOR libm!!!
+
#undef OVM_OP
#define OVM_OP(i, t, op, ctype, cast_type) \
VAL(instr.r).dtype = (ctype) VAL(instr.a).stype; \
break
- case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I16): CVT(i8, i16, OVM_TYPE_I16, u16);
- case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I32): CVT(i8, i32, OVM_TYPE_I32, u32);
- case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I64): CVT(i8, i64, OVM_TYPE_I64, u64);
-
- case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I8): CVT(i16, i8, OVM_TYPE_I8, u8);
- case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I32): CVT(i16, i32, OVM_TYPE_I32, u32);
- case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I64): CVT(i16, i64, OVM_TYPE_I64, u64);
-
- case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I8): CVT(i32, i8, OVM_TYPE_I8, u8);
- case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I16): CVT(i32, i16, OVM_TYPE_I16, u16);
- case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I64): CVT(i32, i64, OVM_TYPE_I64, u64);
- case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F32): CVT(i32, f32, OVM_TYPE_F32, f32);
- case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F64): CVT(i32, f64, OVM_TYPE_F64, f64);
-
- case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I8): CVT(i64, i8, OVM_TYPE_I8, u8);
- case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I16): CVT(i64, i16, OVM_TYPE_I16, u16);
- case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I32): CVT(i64, i32, OVM_TYPE_I32, u32);
- case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F32): CVT(i64, f32, OVM_TYPE_F32, f32);
- case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F64): CVT(i64, f64, OVM_TYPE_F64, f64);
+ case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I16): CVT(u8, u16, OVM_TYPE_I16, u16);
+ case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I32): CVT(u8, u32, OVM_TYPE_I32, u32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I64): CVT(u8, u64, OVM_TYPE_I64, u64);
+ case OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I16): CVT(i8, i16, OVM_TYPE_I16, i16);
+ case OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I32): CVT(i8, i32, OVM_TYPE_I32, i32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I64): CVT(i8, i64, OVM_TYPE_I64, i64);
+
+ case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I8): CVT(u16, u8, OVM_TYPE_I8, u8);
+ case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I32): CVT(u16, u32, OVM_TYPE_I32, u32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I64): CVT(u16, u64, OVM_TYPE_I64, u64);
+ case OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I8): CVT(i16, i8, OVM_TYPE_I8, i8);
+ case OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I32): CVT(i16, i32, OVM_TYPE_I32, i32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I64): CVT(i16, i64, OVM_TYPE_I64, i64);
+
+ case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I8): CVT(u32, u8, OVM_TYPE_I8, u8);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I16): CVT(u32, u16, OVM_TYPE_I16, u16);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I64): CVT(u32, u64, OVM_TYPE_I64, u64);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I8): CVT(i32, i8, OVM_TYPE_I8, i8);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I16): CVT(i32, i16, OVM_TYPE_I16, i16);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64): CVT(i32, i64, OVM_TYPE_I64, i64);
+
+ case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F32): CVT(u32, f32, OVM_TYPE_F32, f32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F32): CVT(i32, f32, OVM_TYPE_F32, f32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F64): CVT(u32, f64, OVM_TYPE_F64, f64);
+ case OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F64): CVT(i32, f64, OVM_TYPE_F64, f64);
+
+ case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I8): CVT(u64, u8, OVM_TYPE_I8, u8);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I16): CVT(u64, u16, OVM_TYPE_I16, u16);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I32): CVT(u64, u32, OVM_TYPE_I32, u32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_I8): CVT(i64, i8, OVM_TYPE_I8, i8);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_I16): CVT(i64, i16, OVM_TYPE_I16, i16);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_I32): CVT(i64, i32, OVM_TYPE_I32, i32);
+
+ case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F32): CVT(u64, f32, OVM_TYPE_F32, f32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F32): CVT(i64, f32, OVM_TYPE_F32, f32);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F64): CVT(u64, f64, OVM_TYPE_F64, f64);
+ case OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F64): CVT(i64, f64, OVM_TYPE_F64, f64);
case OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32): CVT(f32, i32, OVM_TYPE_I32, u32);
case OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64): CVT(f32, f32, OVM_TYPE_I64, u64);
case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32): CVT(f64, f32, OVM_TYPE_F32, f32);
#undef CVT
+
+#define CVT(stype, dtype, otype, ctype) \
+ VAL(instr.r).type = otype; \
+ VAL(instr.r).dtype = *(ctype *) &VAL(instr.a).stype; \
+ break
+
+ case OVM_TYPED_INSTR(OVMI_TRANSMUTE_I32, OVM_TYPE_F32): CVT(u32, f32, OVM_TYPE_F32, f32);
+ case OVM_TYPED_INSTR(OVMI_TRANSMUTE_I64, OVM_TYPE_F64): CVT(u64, f64, OVM_TYPE_F64, f64);
+ case OVM_TYPED_INSTR(OVMI_TRANSMUTE_F32, OVM_TYPE_I32): CVT(f32, u32, OVM_TYPE_I32, u32);
+ case OVM_TYPED_INSTR(OVMI_TRANSMUTE_F64, OVM_TYPE_I64): CVT(f64, u64, OVM_TYPE_I64, u64);
+
+#undef CVT
+
default:
printf("ERROR:\n");
ovm_program_print_instructions(program, state->pc - 1, 1);
static void parse_expression(build_context *ctx);
static void parse_instruction(build_context *ctx) {
- char instr_byte;
+ unsigned char instr_byte;
switch (instr_byte = CONSUME_BYTE(ctx)) {
case 0x00: break;
case 0x01: break;
case 0x10: {
int func_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
int param_count = ctx->program->funcs[func_idx].param_count;
- ovm_code_builder_add_call(&ctx->builder, param_count);
+
+ wasm_functype_t *functype = ctx->module->functypes.data[func_idx];
+
+ ovm_code_builder_add_call(&ctx->builder, func_idx, param_count, functype->type.func.results.size != 0);
break;
}
int table_idx = uleb128_to_uint(ctx->binary.data, &ctx->offset);
assert(table_idx == 0);
- int param_count = ctx->module->type_section.data[type_idx]->type.func.params.size;
- ovm_code_builder_add_indirect_call(&ctx->builder, param_count);
+ wasm_functype_t *functype = ctx->module->type_section.data[type_idx];
+ int param_count = functype->type.func.params.size;
+ printf("indirect call with %d params.\n", param_count);
+ ovm_code_builder_add_indirect_call(&ctx->builder, param_count, functype->type.func.results.size != 0);
break;
}
// ... More loading and storing instruction here ...
+ case 0x36: {
+ int alignment = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ int offset = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_store(&ctx->builder, OVM_TYPE_I32, offset);
+ break;
+ }
+
+ case 0x37: {
+ int alignment = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ int offset = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_store(&ctx->builder, OVM_TYPE_I64, offset);
+ break;
+ }
+
+ case 0x38: {
+ int alignment = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ int offset = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_store(&ctx->builder, OVM_TYPE_F32, offset);
+ break;
+ }
+
+ case 0x39: {
+ int alignment = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ int offset = uleb128_to_uint(ctx->binary.data, &ctx->offset);
+ ovm_code_builder_add_store(&ctx->builder, OVM_TYPE_F64, offset);
+ break;
+ }
+
case 0x41: {
int value = uleb128_to_uint(ctx->binary.data, &ctx->offset);
ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I32, &value);
case 0x65: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_LE, OVM_TYPE_F64)); break;
case 0x66: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_GE, OVM_TYPE_F64)); break;
+ case 0x67: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I32)); break;
+ case 0x68: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I32)); break;
+ case 0x69: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I32)); break;
+ case 0x6A: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32)); break;
+ case 0x6B: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_I32)); break;
+ case 0x6C: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_I32)); break;
+ case 0x6D: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_I32)); break;
+ case 0x6E: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I32)); break;
+ case 0x6F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I32)); break;
+ case 0x70: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I32)); break;
+ case 0x71: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_AND, OVM_TYPE_I32)); break;
+ case 0x72: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_OR, OVM_TYPE_I32)); break;
+ case 0x73: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_XOR, OVM_TYPE_I32)); break;
+ case 0x74: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHL, OVM_TYPE_I32)); break;
+ case 0x75: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SAR, OVM_TYPE_I32)); break;
+ case 0x76: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHR, OVM_TYPE_I32)); break;
+ case 0x77: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I32)); break;
+ case 0x78: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I32)); break;
+
+ case 0x79: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CLZ, OVM_TYPE_I64)); break;
+ case 0x7A: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CTZ, OVM_TYPE_I64)); break;
+ case 0x7B: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_POPCNT, OVM_TYPE_I64)); break;
+ case 0x7C: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I64)); break;
+ case 0x7D: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_I64)); break;
+ case 0x7E: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_I64)); break;
+ case 0x7F: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_I64)); break;
+ case 0x80: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV_S, OVM_TYPE_I64)); break;
+ case 0x81: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I64)); break;
+ case 0x82: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_REM_S, OVM_TYPE_I64)); break;
+ case 0x83: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_AND, OVM_TYPE_I64)); break;
+ case 0x84: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_OR, OVM_TYPE_I64)); break;
+ case 0x85: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_XOR, OVM_TYPE_I64)); break;
+ case 0x86: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHL, OVM_TYPE_I64)); break;
+ case 0x87: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SAR, OVM_TYPE_I64)); break;
+ case 0x88: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SHR, OVM_TYPE_I64)); break;
+ case 0x89: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTL, OVM_TYPE_I64)); break;
+ case 0x8A: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ROTR, OVM_TYPE_I64)); break;
+
+ case 0x8B: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F32)); break;
+ case 0x8C: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F32)); break;
+ case 0x8D: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F32)); break;
+ case 0x8E: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F32)); break;
+ case 0x8F: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F32)); break;
+ case 0x90: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F32)); break;
+ case 0x91: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F32)); break;
+ case 0x92: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_F32)); break;
+ case 0x93: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_F32)); break;
+ case 0x94: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_F32)); break;
+ case 0x95: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_F32)); break;
+ case 0x96: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F32)); break;
+ case 0x97: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F32)); break;
+ case 0x98: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F32)); break;
+
+ case 0x99: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_ABS, OVM_TYPE_F64)); break;
+ case 0x9A: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEG, OVM_TYPE_F64)); break;
+ case 0x9B: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CEIL, OVM_TYPE_F64)); break;
+ case 0x9C: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_FLOOR, OVM_TYPE_F64)); break;
+ case 0x9D: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRUNC, OVM_TYPE_F64)); break;
+ case 0x9E: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_NEAREST, OVM_TYPE_F64)); break;
+ case 0x9F: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_SQRT, OVM_TYPE_F64)); break;
+ case 0xA0: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_F64)); break;
+ case 0xA1: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_F64)); break;
+ case 0xA2: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MUL, OVM_TYPE_F64)); break;
+ case 0xA3: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_DIV, OVM_TYPE_F64)); break;
+ case 0xA4: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MIN, OVM_TYPE_F64)); break;
+ case 0xA5: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_MAX, OVM_TYPE_F64)); break;
+ case 0xA6: ovm_code_builder_add_binop(&ctx->builder, OVM_TYPED_INSTR(OVMI_COPYSIGN, OVM_TYPE_F64)); break;
+
+ case 0xA7: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I32)); break;
+ case 0xA8: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32)); break;
+ case 0xA9: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32)); break;
+ case 0xAA: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32)); break;
+ case 0xAB: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32)); break;
+ case 0xAC: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64)); break;
+ case 0xAD: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I64)); break;
+ case 0xAE: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64)); break;
+ case 0xAF: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64)); break;
+ case 0xB0: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64)); break;
+ case 0xB1: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64)); break;
+ case 0xB2: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F32)); break;
+ case 0xB3: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F32)); break;
+ case 0xB4: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F32)); break;
+ case 0xB5: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F32)); break;
+ case 0xB6: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32)); break;
+ case 0xB7: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_F64)); break;
+ case 0xB8: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F64)); break;
+ case 0xB9: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64_S, OVM_TYPE_F64)); break;
+ case 0xBA: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F64)); break;
+ case 0xBB: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_F64)); break;
+ case 0xBC: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_F32, OVM_TYPE_I32)); break;
+ case 0xBD: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_F64, OVM_TYPE_I64)); break;
+ case 0xBE: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_I32, OVM_TYPE_F32)); break;
+ case 0xBF: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_TRANSMUTE_I64, OVM_TYPE_F64)); break;
+ case 0xC0: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I32)); break;
+ case 0xC1: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I32)); break;
+ case 0xC2: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I8_S, OVM_TYPE_I64)); break;
+ case 0xC3: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I16_S, OVM_TYPE_I64)); break;
+ case 0xC4: ovm_code_builder_add_unop (&ctx->builder, OVM_TYPED_INSTR(OVMI_CVT_I32_S, OVM_TYPE_I64)); break;
default: assert(("UNHANDLED INSTRUCTION", 0));
}
// Set up a lot of stuff...
ctx->builder = ovm_code_builder_new(ctx->program, 0, total_locals);
+ push_label_target(ctx, label_kind_func);
+
parse_expression(ctx);
+
+ ovm_code_builder_add_return(&ctx->builder);
ovm_code_builder_free(&ctx->builder);
}
}
#include "bh.h"
#include "wasm.h"
+#include "onyx_wasm.h"
+#include "vm.h"
int main(int argc, char *argv[]) {
const wasm_name_t *export_name = wasm_exporttype_name(exports.data[i]);
bh_printf("exports: %b %d\n", export_name->data, export_name->size, wasm_externtype_kind(wasm_exporttype_type(exports.data[i])));
}
+
+ ovm_program_print_instructions(module->program, 0, 100);
}