refactored to remove many unnecessary switch statements
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 16 Dec 2022 05:00:08 +0000 (23:00 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 16 Dec 2022 05:00:08 +0000 (23:00 -0600)
interpreter/include/vm.h
interpreter/src/vm/code_builder.c
interpreter/src/vm/vm.c
shared/lib/linux_x86_64/lib/libovmwasm.so

index 5b0b195cf992e3667d600aca7fe15d4671607dd7..cb12a09ad2a55de143df25d6fb20dc87368d3ccd 100644 (file)
@@ -241,9 +241,9 @@ struct ovm_instr_t {
     };
 };
 
-#define OVM_INSTR_TYPE(instr)  ((instr).full_instr >> 24)
-#define OVM_INSTR_INSTR(instr) ((instr).full_instr & 0xffffff)
-#define OVM_INSTR_MASK         0xff
+#define OVM_INSTR_TYPE(instr)  ((instr).full_instr & 0x7)
+#define OVM_INSTR_INSTR(instr) (((instr).full_instr >> 3) & 0xff)
+#define OVM_INSTR_MASK         0x7ff
 
 #define OVMI_ATOMIC            0x00800000 // Flag an instruction as atomic
 
@@ -273,77 +273,77 @@ struct ovm_instr_t {
 #define OVMI_REG_SET           0x17   // #r = %a
 #define OVMI_IDX_ARR           0x18   // %r = (a)[%b]
 
-#define OVMI_LT                0x20   // %r = %a < %b
-#define OVMI_LT_S              0x21   // %r = %a < %b
-#define OVMI_LE                0x22   // %r = %a <= %b
-#define OVMI_LE_S              0x23   // %r = %a <= %b
-#define OVMI_EQ                0x24   // %r = %a == %b
-#define OVMI_GE                0x25   // %r = %a >= %b
-#define OVMI_GE_S              0x26   // %r = %a >= %b
-#define OVMI_GT                0x27   // %r = %a > %b
-#define OVMI_GT_S              0x28   // %r = %a > %b
-#define OVMI_NE                0x29   // %r = %a != %b
-
-#define OVMI_PARAM             0x30   // push %a
-#define OVMI_RETURN            0x31   // return %a
-#define OVMI_CALL              0x32   // %r = a(...)
-#define OVMI_CALLI             0x33   // %r = %a(...)
-
-#define OVMI_BR                0x40   // br pc + a              // Relative branching
-#define OVMI_BR_Z              0x41   // br pc + a if %b == 0
-#define OVMI_BR_NZ             0x42   // br pc + a if %b != 0
-#define OVMI_BRI               0x43   // br pc + %a             // Relative branching
-#define OVMI_BRI_Z             0x44   // br pc + %a if %b == 0
-#define OVMI_BRI_NZ            0x45   // br pc + %a if %b != 0
-
-#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)
+#define OVMI_LT                0x19   // %r = %a < %b
+#define OVMI_LT_S              0x1a   // %r = %a < %b
+#define OVMI_LE                0x1b   // %r = %a <= %b
+#define OVMI_LE_S              0x1c   // %r = %a <= %b
+#define OVMI_EQ                0x1d   // %r = %a == %b
+#define OVMI_GE                0x1e   // %r = %a >= %b
+#define OVMI_GE_S              0x1f   // %r = %a >= %b
+#define OVMI_GT                0x20   // %r = %a > %b
+#define OVMI_GT_S              0x21   // %r = %a > %b
+#define OVMI_NE                0x22   // %r = %a != %b
+
+#define OVMI_PARAM             0x23   // push %a
+#define OVMI_RETURN            0x24   // return %a
+#define OVMI_CALL              0x25   // %r = a(...)
+#define OVMI_CALLI             0x26   // %r = %a(...)
+
+#define OVMI_BR                0x27   // br pc + a              // Relative branching
+#define OVMI_BR_Z              0x28   // br pc + a if %b == 0
+#define OVMI_BR_NZ             0x29   // br pc + a if %b != 0
+#define OVMI_BRI               0x2a   // br pc + %a             // Relative branching
+#define OVMI_BRI_Z             0x2b   // br pc + %a if %b == 0
+#define OVMI_BRI_NZ            0x2c   // br pc + %a if %b != 0
+
+#define OVMI_CLZ               0x2d   // %r = clz(%a)
+#define OVMI_CTZ               0x2e   // %r = ctr(%a)
+#define OVMI_POPCNT            0x2f   // %r = popcnt(%a)
+#define OVMI_ROTL              0x30   // %r = rotl(%a, %b)
+#define OVMI_ROTR              0x31   // %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)
+#define OVMI_ABS               0x32   // %r = |%a|
+#define OVMI_NEG               0x33   // %r = -%a
+#define OVMI_CEIL              0x34   // %r = ceil(%a)
+#define OVMI_FLOOR             0x35   // %r = floor(%a)
+#define OVMI_TRUNC             0x36   // %r = trunc(%a)
+#define OVMI_NEAREST           0x37   // %r = nearest(%a)
+#define OVMI_SQRT              0x38   // %r = sqrt(%a)
+#define OVMI_MIN               0x39   // %r = min(%a, %b)
+#define OVMI_MAX               0x3a   // %r = max(%a, %b)
+#define OVMI_COPYSIGN          0x3b   // %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_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_F32_S         0x69   // %r = (t) %a (sign aware)
-#define OVMI_CVT_F64           0x6A   // %r = (t) %a
-#define OVMI_CVT_F64_S         0x6B   // %r = (t) %a (sign aware)
-#define OVMI_TRANSMUTE_I32     0x6C   // %r = *(t *) &%a (reinterpret bytes)
-#define OVMI_TRANSMUTE_I64     0x6D   // %r = *(t *) &%a (reinterpret bytes)
-#define OVMI_TRANSMUTE_F32     0x6E   // %r = *(t *) &%a (reinterpret bytes)
-#define OVMI_TRANSMUTE_F64     0x6F   // %r = *(t *) &%a (reinterpret bytes)
-
-#define OVMI_CMPXCHG           0x70   // %r = %r == %a ? %b : %r 
-
-#define OVMI_BREAK             0xff
+#define OVMI_CVT_I8            0x3c   // %r = (t) %a
+#define OVMI_CVT_I8_S          0x3d   // %r = (t) %a (sign aware)
+#define OVMI_CVT_I16           0x3e   // %r = (t) %a
+#define OVMI_CVT_I16_S         0x3f   // %r = (t) %a (sign aware)
+#define OVMI_CVT_I32           0x40   // %r = (t) %a
+#define OVMI_CVT_I32_S         0x41   // %r = (t) %a (sign aware)
+#define OVMI_CVT_I64           0x42   // %r = (t) %a
+#define OVMI_CVT_I64_S         0x43   // %r = (t) %a (sign aware)
+#define OVMI_CVT_F32           0x44   // %r = (t) %a
+#define OVMI_CVT_F32_S         0x45   // %r = (t) %a (sign aware)
+#define OVMI_CVT_F64           0x46   // %r = (t) %a
+#define OVMI_CVT_F64_S         0x47   // %r = (t) %a (sign aware)
+#define OVMI_TRANSMUTE_I32     0x48   // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_I64     0x49   // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F32     0x4a   // %r = *(t *) &%a (reinterpret bytes)
+#define OVMI_TRANSMUTE_F64     0x4b   // %r = *(t *) &%a (reinterpret bytes)
+
+#define OVMI_CMPXCHG           0x4c   // %r = %r == %a ? %b : %r 
+
+#define OVMI_BREAK             0x4d
 
 //
 // OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32) == instruction for adding i32s
 //
-#define OVM_TYPED_INSTR(instr, type)  (((type) << 24) | (instr))
+#define OVM_TYPED_INSTR(instr, type)  (((instr) << 3) | (type))
 
 
 #endif
index d7f696f2657064d9e2048227bf95140c3f0d0fd3..bb4429a255034258fdd18c28c041ea6e07a978cd 100644 (file)
@@ -144,7 +144,7 @@ void ovm_code_builder_add_nop(ovm_code_builder_t *builder) {
 
 void ovm_code_builder_add_break(ovm_code_builder_t *builder) {
     ovm_instr_t break_ = {0};
-    break_.full_instr = OVMI_BREAK;
+    break_.full_instr = OVM_TYPED_INSTR(OVMI_BREAK, OVM_TYPE_NONE);
     debug_info_builder_emit_location(builder->debug_builder);
     ovm_program_add_instructions(builder->program, 1, &break_);
 }
@@ -200,7 +200,7 @@ void ovm_code_builder_add_unop(ovm_code_builder_t *builder, u32 instr) {
 
 void ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 label_idx) {
     ovm_instr_t branch_instr = {0};
-    branch_instr.full_instr = OVMI_BR;
+    branch_instr.full_instr = OVM_TYPED_INSTR(OVMI_BR, OVM_TYPE_NONE);
     branch_instr.a = -1;
 
     branch_patch_t patch;
@@ -218,9 +218,9 @@ void ovm_code_builder_add_branch(ovm_code_builder_t *builder, i32 label_idx) {
 void ovm_code_builder_add_cond_branch(ovm_code_builder_t *builder, i32 label_idx, bool branch_if_true, bool targets_else) {
     ovm_instr_t branch_instr = {0};
     if (branch_if_true) {
-        branch_instr.full_instr = OVMI_BR_NZ;
+        branch_instr.full_instr = OVM_TYPED_INSTR(OVMI_BR_NZ, OVM_TYPE_NONE);
     } else {
-        branch_instr.full_instr = OVMI_BR_Z;
+        branch_instr.full_instr = OVM_TYPED_INSTR(OVMI_BR_Z, OVM_TYPE_NONE);
     }
 
     branch_instr.a = -1;
@@ -259,16 +259,16 @@ void ovm_code_builder_add_branch_table(ovm_code_builder_t *builder, i32 count, i
     instrs[1].a = index_register;
     instrs[1].b = tmp_register;
 
-    instrs[2].full_instr = OVMI_BR_Z;
+    instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_BR_Z, OVM_TYPE_NONE);
     instrs[2].a = -1;
     instrs[2].b = tmp_register;
 
-    instrs[3].full_instr = OVMI_IDX_ARR;
+    instrs[3].full_instr = OVM_TYPED_INSTR(OVMI_IDX_ARR, OVM_TYPE_NONE);
     instrs[3].r = tmp_register;
     instrs[3].a = table_idx;
     instrs[3].b = index_register;
     
-    instrs[4].full_instr = OVMI_BRI;
+    instrs[4].full_instr = OVM_TYPED_INSTR(OVMI_BRI, OVM_TYPE_NONE);
     instrs[4].a = tmp_register;
     
     POP_VALUE(builder);
@@ -301,7 +301,7 @@ void ovm_code_builder_add_branch_table(ovm_code_builder_t *builder, i32 count, i
 
 void ovm_code_builder_add_return(ovm_code_builder_t *builder) {
     ovm_instr_t instr = {0};
-    instr.full_instr = OVMI_RETURN;
+    instr.full_instr = OVM_TYPED_INSTR(OVMI_RETURN, OVM_TYPE_NONE);
 
     i32 values_on_stack = bh_arr_length(builder->execution_stack);
     assert(values_on_stack == 0 || values_on_stack == 1);
@@ -323,7 +323,7 @@ static void ovm_code_builder_add_params(ovm_code_builder_t *builder, i32 param_c
 
     fori (i, 0, param_count) {
         ovm_instr_t param_instr = {0};
-        param_instr.full_instr = OVMI_PARAM;
+        param_instr.full_instr = OVM_TYPED_INSTR(OVMI_PARAM, OVM_TYPE_NONE);
         param_instr.a = flipped_params[param_count - 1 - i];
 
         debug_info_builder_emit_location(builder->debug_builder);
@@ -335,7 +335,7 @@ void ovm_code_builder_add_call(ovm_code_builder_t *builder, i32 func_idx, i32 pa
     ovm_code_builder_add_params(builder, param_count);
 
     ovm_instr_t call_instr = {0};
-    call_instr.full_instr = OVMI_CALL;
+    call_instr.full_instr = OVM_TYPED_INSTR(OVMI_CALL, OVM_TYPE_NONE);
     call_instr.a = func_idx;
     call_instr.r = -1;
 
@@ -355,12 +355,12 @@ void ovm_code_builder_add_indirect_call(ovm_code_builder_t *builder, i32 param_c
     ovm_instr_t call_instrs[2] = {0};
 
     // idxarr %k, table, %j
-    call_instrs[0].full_instr = OVMI_IDX_ARR;
+    call_instrs[0].full_instr = OVM_TYPED_INSTR(OVMI_IDX_ARR, OVM_TYPE_NONE);
     call_instrs[0].r = NEXT_VALUE(builder);
     call_instrs[0].a = builder->func_table_arr_idx;
     call_instrs[0].b = POP_VALUE(builder);
 
-    call_instrs[1].full_instr = OVMI_CALLI;
+    call_instrs[1].full_instr = OVM_TYPED_INSTR(OVMI_CALLI, OVM_TYPE_NONE);
     call_instrs[1].a = call_instrs[0].r;
     call_instrs[1].r = -1;
 
@@ -385,7 +385,7 @@ 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) {
     ovm_instr_t instr = {0};
-    instr.full_instr = OVMI_MOV;
+    instr.full_instr = OVM_TYPED_INSTR(OVMI_MOV, OVM_TYPE_NONE);
     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
@@ -401,7 +401,7 @@ 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) {
     ovm_instr_t instr = {0};
-    instr.full_instr = OVMI_MOV;
+    instr.full_instr = OVM_TYPED_INSTR(OVMI_MOV, OVM_TYPE_NONE);
     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
@@ -415,7 +415,7 @@ void ovm_code_builder_add_local_set(ovm_code_builder_t *builder, i32 local_idx)
 
 void ovm_code_builder_add_local_tee(ovm_code_builder_t *builder, i32 local_idx) {
     ovm_instr_t instr = {0};
-    instr.full_instr = OVMI_MOV;
+    instr.full_instr = OVM_TYPED_INSTR(OVMI_MOV, OVM_TYPE_NONE);
     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
@@ -431,7 +431,7 @@ void ovm_code_builder_add_local_tee(ovm_code_builder_t *builder, i32 local_idx)
 
 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.full_instr = OVM_TYPED_INSTR(OVMI_REG_GET, OVM_TYPE_NONE);
     instr.r = NEXT_VALUE(builder);
     instr.a = reg_idx;
 
@@ -443,7 +443,7 @@ void ovm_code_builder_add_register_get(ovm_code_builder_t *builder, i32 reg_idx)
 
 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.full_instr = OVM_TYPED_INSTR(OVMI_REG_SET, OVM_TYPE_NONE);
     instr.r = reg_idx;
     instr.a = POP_VALUE(builder);
 
@@ -479,7 +479,7 @@ void ovm_code_builder_add_store(ovm_code_builder_t *builder, u32 ovm_type, i32 o
 void ovm_code_builder_add_cmpxchg(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
     if (offset == 0) {
         ovm_instr_t cmpxchg_instr = {0};
-        cmpxchg_instr.full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_CMPXCHG, ovm_type);
+        cmpxchg_instr.full_instr = OVMI_ATOMIC | OVM_TYPED_INSTR(OVMI_CMPXCHG, ovm_type);
         cmpxchg_instr.b = POP_VALUE(builder);
         cmpxchg_instr.a = POP_VALUE(builder);
         cmpxchg_instr.r = POP_VALUE(builder);
@@ -510,7 +510,7 @@ void ovm_code_builder_add_cmpxchg(ovm_code_builder_t *builder, u32 ovm_type, i32
     instrs[1].b = instrs[0].r;
 
     // cmpxchg.x %m, %n
-    instrs[2].full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_CMPXCHG, ovm_type);
+    instrs[2].full_instr = OVMI_ATOMIC | OVM_TYPED_INSTR(OVMI_CMPXCHG, ovm_type);
     instrs[2].r = instrs[1].r;
     instrs[2].a = expected_reg;
     instrs[2].b = value_reg;
@@ -525,7 +525,7 @@ void ovm_code_builder_add_cmpxchg(ovm_code_builder_t *builder, u32 ovm_type, i32
 
 void ovm_code_builder_add_memory_copy(ovm_code_builder_t *builder) {
     ovm_instr_t instr = {0};
-    instr.full_instr = OVMI_COPY;
+    instr.full_instr = OVM_TYPED_INSTR(OVMI_COPY, OVM_TYPE_NONE);
     instr.b = POP_VALUE(builder);
     instr.a = POP_VALUE(builder);
     instr.r = POP_VALUE(builder);
@@ -536,7 +536,7 @@ void ovm_code_builder_add_memory_copy(ovm_code_builder_t *builder) {
 
 void ovm_code_builder_add_memory_fill(ovm_code_builder_t *builder) {
     ovm_instr_t instr = {0};
-    instr.full_instr = OVMI_FILL;
+    instr.full_instr = OVM_TYPED_INSTR(OVMI_FILL, OVM_TYPE_NONE);
     instr.b = POP_VALUE(builder);
     instr.a = POP_VALUE(builder);
     instr.r = POP_VALUE(builder);
@@ -549,7 +549,7 @@ void ovm_code_builder_add_memory_fill(ovm_code_builder_t *builder) {
 // CopyNPaste from _add_load
 void ovm_code_builder_add_atomic_load(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
     ovm_instr_t load_instr = {0};
-    load_instr.full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_LOAD, ovm_type);
+    load_instr.full_instr = OVMI_ATOMIC | OVM_TYPED_INSTR(OVMI_LOAD, ovm_type);
     load_instr.b = offset;
     load_instr.a = POP_VALUE(builder);
     load_instr.r = NEXT_VALUE(builder);
@@ -564,7 +564,7 @@ void ovm_code_builder_add_atomic_load(ovm_code_builder_t *builder, u32 ovm_type,
 // CopyNPaste from _add_store
 void ovm_code_builder_add_atomic_store(ovm_code_builder_t *builder, u32 ovm_type, i32 offset) {
     ovm_instr_t store_instr = {0};
-    store_instr.full_instr = OVM_TYPED_INSTR(OVMI_ATOMIC | OVMI_STORE, ovm_type);
+    store_instr.full_instr = OVMI_ATOMIC | OVM_TYPED_INSTR(OVMI_STORE, ovm_type);
     store_instr.b = offset;
     store_instr.a = POP_VALUE(builder);
     store_instr.r = POP_VALUE(builder);
index e9f123c1935282e6045a80e0b5b18b50a6e29e8b..1c4c4d72e38ca058cd38db033adbd8eeb90c8210 100644 (file)
@@ -135,6 +135,11 @@ void ovm_program_add_instructions(ovm_program_t *program, i32 instr_count, ovm_i
 }
 
 
+static char *ovm_instr_name(i32 full_instr) {
+    return "";
+}
+
+#if 0
 static char *ovm_instr_name(i32 full_instr) {
 #define C(...) \
     case __VA_ARGS__: return #__VA_ARGS__; \
@@ -411,6 +416,7 @@ static char *ovm_instr_name(i32 full_instr) {
             return buf;
     }
 }
+#endif
 
 void ovm_program_print_instructions(ovm_program_t *program, i32 start_instr, i32 instr_count) {
     fori (i, start_instr, start_instr + instr_count) {
@@ -739,7 +745,7 @@ static inline void __ovm_debug_hook(ovm_engine_t *engine, ovm_state_t *state) {
 
 #define NEXT_OP \
     if (instr->full_instr & OVMI_ATOMIC) pthread_mutex_unlock(&state->engine->atomic_mutex); \
-    __ovm_debug_hook(state->engine, state); \
+    if (state->debug) __ovm_debug_hook(state->engine, state); \
     instr = &code[state->pc++]; \
     if (instr->full_instr & OVMI_ATOMIC) pthread_mutex_lock(&state->engine->atomic_mutex); \
     return ovmi_dispatch[instr->full_instr & OVM_INSTR_MASK](instr, state, memory, code);
@@ -766,68 +772,34 @@ OVMI_INSTR_EXEC(ovmi_exec_nop) {
 //
 
 #define OVM_OP_EXEC(name, op) \
-    OVMI_INSTR_EXEC(ovmi_exec_##name) { \
-        switch (OVM_INSTR_TYPE(*instr)) { \
-            OVM_OP(OVM_TYPE_I8 , op, i8) \
-            OVM_OP(OVM_TYPE_I16, op, i16) \
-            OVM_OP(OVM_TYPE_I32, op, i32) \
-            OVM_OP(OVM_TYPE_I64, op, i64) \
-            OVM_OP(OVM_TYPE_F32, op, f32) \
-            OVM_OP(OVM_TYPE_F64, op, f64) \
-        } \
-        NEXT_OP; \
-    }
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i32) { OVM_OP(OVM_TYPE_I32, op, i32); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i64) { OVM_OP(OVM_TYPE_I64, op, i64); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_f32) { OVM_OP(OVM_TYPE_F32, op, f32); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_f64) { OVM_OP(OVM_TYPE_F64, op, f64); NEXT_OP; }
 
 #define OVM_OP_UNSIGNED_EXEC(name, op) \
-    OVMI_INSTR_EXEC(ovmi_exec_##name) { \
-        switch (OVM_INSTR_TYPE(*instr)) { \
-            OVM_OP(OVM_TYPE_I8 , op, u8) \
-            OVM_OP(OVM_TYPE_I16, op, u16) \
-            OVM_OP(OVM_TYPE_I32, op, u32) \
-            OVM_OP(OVM_TYPE_I64, op, u64) \
-            OVM_OP(OVM_TYPE_F32, op, f32) \
-            OVM_OP(OVM_TYPE_F64, op, f64) \
-        } \
-        NEXT_OP; \
-    }
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i32) { OVM_OP(OVM_TYPE_I32, op, u32); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i64) { OVM_OP(OVM_TYPE_I64, op, u64); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_f32) { OVM_OP(OVM_TYPE_F32, op, f32); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_f64) { OVM_OP(OVM_TYPE_F64, op, f64); NEXT_OP; }
 
 #define OVM_OP_INTEGER_EXEC(name, op) \
-    OVMI_INSTR_EXEC(ovmi_exec_##name) { \
-        switch (OVM_INSTR_TYPE(*instr)) { \
-            OVM_OP(OVM_TYPE_I8 , op, i8) \
-            OVM_OP(OVM_TYPE_I16, op, i16) \
-            OVM_OP(OVM_TYPE_I32, op, i32) \
-            OVM_OP(OVM_TYPE_I64, op, i64) \
-        } \
-        NEXT_OP; \
-    }
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i32) { OVM_OP(OVM_TYPE_I32, op, i32); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i64) { OVM_OP(OVM_TYPE_I64, op, i64); NEXT_OP; }
 
 #define OVM_OP_INTEGER_UNSIGNED_EXEC(name, op) \
-    OVMI_INSTR_EXEC(ovmi_exec_##name) { \
-        switch (OVM_INSTR_TYPE(*instr)) { \
-            OVM_OP(OVM_TYPE_I8 , op, u8) \
-            OVM_OP(OVM_TYPE_I16, op, u16) \
-            OVM_OP(OVM_TYPE_I32, op, u32) \
-            OVM_OP(OVM_TYPE_I64, op, u64) \
-        } \
-        NEXT_OP; \
-    }
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i32) { OVM_OP(OVM_TYPE_I32, op, u32); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_i64) { OVM_OP(OVM_TYPE_I64, op, u64); NEXT_OP; }
 
 #define OVM_OP_FLOAT_EXEC(name, op) \
-    OVMI_INSTR_EXEC(ovmi_exec_##name) { \
-        switch (OVM_INSTR_TYPE(*instr)) { \
-            OVM_OP(OVM_TYPE_F32, op, f32) \
-            OVM_OP(OVM_TYPE_F64, op, f64) \
-        } \
-        NEXT_OP; \
-    }
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_f32) { OVM_OP(OVM_TYPE_F32, op, f32); NEXT_OP; } \
+    OVMI_INSTR_EXEC(ovmi_exec_##name##_f64) { OVM_OP(OVM_TYPE_F64, op, f64); NEXT_OP; }
+
 
 #define OVM_OP(t, op, ctype) \
-    case t: \
-        ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
-        VAL(instr->r).ctype = VAL(instr->a).ctype op VAL(instr->b).ctype; \
-        VAL(instr->r).type = t; \
-        break;
+    ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
+    VAL(instr->r).ctype = VAL(instr->a).ctype op VAL(instr->b).ctype; \
+    VAL(instr->r).type = t;
 
 OVM_OP_EXEC(add, +)
 OVM_OP_EXEC(sub, -)
@@ -846,31 +818,14 @@ OVM_OP_INTEGER_EXEC(sar, >>)
 #undef OVM_OP
 
 #define OVM_OP(t, func, ctype) \
-    case t: \
-        ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
-        VAL(instr->r).ctype = func( VAL(instr->a).ctype, VAL(instr->b).ctype ); \
-        VAL(instr->r).type = t; \
-        break;
-
-OVMI_INSTR_EXEC(ovmi_exec_rotl) {
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_OP(OVM_TYPE_I8 , __rolb, u8)
-        OVM_OP(OVM_TYPE_I16, __rolw, u16)
-        OVM_OP(OVM_TYPE_I32, __rold, u32)
-        OVM_OP(OVM_TYPE_I64, __rolq, u64)
-    }
-    NEXT_OP;
-}
+    ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
+    VAL(instr->r).ctype = func( VAL(instr->a).ctype, VAL(instr->b).ctype ); \
+    VAL(instr->r).type = t;
 
-OVMI_INSTR_EXEC(ovmi_exec_rotr) {
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_OP(OVM_TYPE_I8 , __rorb, u8)
-        OVM_OP(OVM_TYPE_I16, __rorw, u16)
-        OVM_OP(OVM_TYPE_I32, __rord, u32)
-        OVM_OP(OVM_TYPE_I64, __rorq, u64)
-    }
-    NEXT_OP;
-}
+OVMI_INSTR_EXEC(ovmi_exec_rotl_i32) { OVM_OP(OVM_TYPE_I32, __rold, u32); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_rotl_i64) { OVM_OP(OVM_TYPE_I64, __rolq, u64); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_rotr_i32) { OVM_OP(OVM_TYPE_I32, __rord, u32); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_rotr_i64) { OVM_OP(OVM_TYPE_I64, __rorq, u64); NEXT_OP; }
 
 OVM_OP_FLOAT_EXEC(min, bh_min)
 OVM_OP_FLOAT_EXEC(max, bh_max)
@@ -880,41 +835,16 @@ OVM_OP_FLOAT_EXEC(copysign, __ovm_copysign)
 
 
 #define OVM_OP(t, op, ctype) \
-    case t: \
-        ovm_assert(VAL(instr->a).type == t); \
-        VAL(instr->r).type = t; \
-        VAL(instr->r).ctype = (ctype) op (VAL(instr->a).ctype); \
-        break;
-
-OVMI_INSTR_EXEC(ovmi_exec_clz) {
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_OP(OVM_TYPE_I8 , __builtin_clz, u8)
-        OVM_OP(OVM_TYPE_I16, __builtin_clz, u16)
-        OVM_OP(OVM_TYPE_I32, __builtin_clz, u32)
-        OVM_OP(OVM_TYPE_I64, __builtin_clzll, u64)
-    }
-    NEXT_OP;
-}
+    ovm_assert(VAL(instr->a).type == t); \
+    VAL(instr->r).type = t; \
+    VAL(instr->r).ctype = (ctype) op (VAL(instr->a).ctype);
 
-OVMI_INSTR_EXEC(ovmi_exec_ctz) {
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_OP(OVM_TYPE_I8 , __builtin_ctz, u8)
-        OVM_OP(OVM_TYPE_I16, __builtin_ctz, u16)
-        OVM_OP(OVM_TYPE_I32, __builtin_ctz, u32)
-        OVM_OP(OVM_TYPE_I64, __builtin_ctzll, u64)
-    }
-    NEXT_OP;
-}
-
-OVMI_INSTR_EXEC(ovmi_exec_popcount) {
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_OP(OVM_TYPE_I8 , __builtin_popcount, u8)
-        OVM_OP(OVM_TYPE_I16, __builtin_popcount, u16)
-        OVM_OP(OVM_TYPE_I32, __builtin_popcount, u32)
-        OVM_OP(OVM_TYPE_I64, __builtin_popcountll, u64)
-    }
-    NEXT_OP;
-}
+OVMI_INSTR_EXEC(ovmi_exec_clz_i32) { OVM_OP(OVM_TYPE_I32, __builtin_clz, u32);   NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_clz_i64) { OVM_OP(OVM_TYPE_I64, __builtin_clzll, u64); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_ctz_i32) { OVM_OP(OVM_TYPE_I32, __builtin_ctz, u32);   NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_ctz_i64) { OVM_OP(OVM_TYPE_I64, __builtin_ctzll, u64); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_popcount_i32) { OVM_OP(OVM_TYPE_I32, __builtin_popcount, u32);   NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_popcount_i64) { OVM_OP(OVM_TYPE_I64, __builtin_popcountll, u64); NEXT_OP; }
 
 OVM_OP_FLOAT_EXEC(abs,     __ovm_abs)
 OVM_OP_FLOAT_EXEC(neg,     -)
@@ -928,11 +858,9 @@ OVM_OP_FLOAT_EXEC(sqrt,    sqrt)
 
 
 #define OVM_OP(t, op, ctype) \
-    case t: \
-        ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
-        VAL(instr->r).type = OVM_TYPE_I32; \
-        VAL(instr->r).i32 = ((VAL(instr->a).ctype op VAL(instr->b).ctype)) ? 1 : 0; \
-        break;
+    ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
+    VAL(instr->r).type = OVM_TYPE_I32; \
+    VAL(instr->r).i32 = ((VAL(instr->a).ctype op VAL(instr->b).ctype)) ? 1 : 0;
 
 OVM_OP_EXEC(eq, ==)
 OVM_OP_EXEC(ne, !=)
@@ -954,24 +882,15 @@ OVM_OP_EXEC(ge_s, >=)
 //
 
 #define OVM_IMM(t, dtype, stype) \
-    case t: \
-        VAL(instr->r).type = t; \
-        VAL(instr->r).u64 = 0; \
-        VAL(instr->r).dtype = instr->stype; \
-        break;
-
-
-OVMI_INSTR_EXEC(ovmi_exec_imm) {
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_IMM(OVM_TYPE_I8,  u8,  i);
-        OVM_IMM(OVM_TYPE_I16, u16, i);
-        OVM_IMM(OVM_TYPE_I32, u32, i);
-        OVM_IMM(OVM_TYPE_I64, u64, l);
-        OVM_IMM(OVM_TYPE_F32, f32, f);
-        OVM_IMM(OVM_TYPE_F64, f64, d);
-    }
-    NEXT_OP;
-}
+    VAL(instr->r).type = t; \
+    VAL(instr->r).u64 = 0; \
+    VAL(instr->r).dtype = instr->stype;
+
+
+OVMI_INSTR_EXEC(ovmi_exec_imm_i32) { OVM_IMM(OVM_TYPE_I32, u32, i); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_imm_i64) { OVM_IMM(OVM_TYPE_I64, u64, l); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_imm_f32) { OVM_IMM(OVM_TYPE_F32, f32, f); NEXT_OP; }
+OVMI_INSTR_EXEC(ovmi_exec_imm_f64) { OVM_IMM(OVM_TYPE_F64, f64, d); NEXT_OP; }
 
 #undef OVM_IMM
 
@@ -980,52 +899,41 @@ OVMI_INSTR_EXEC(ovmi_exec_mov) {
     NEXT_OP;
 }
 
-#define OVM_LOAD(type_, stype) \
-    case type_: {\
+#define OVM_LOAD(otype, type_, stype) \
+    OVMI_INSTR_EXEC(ovmi_exec_load_##otype) { \
+        ovm_assert(VAL(instr->a).type == OVM_TYPE_I32); \
+        u32 dest = VAL(instr->a).u32 + (u32) instr->b; \
+        if (dest == 0) __ovm_trigger_exception(state); \
         VAL(instr->r).stype = * (stype *) &memory[dest]; \
         VAL(instr->r).type = type_; \
-        break; \
+        NEXT_OP; \
     }
 
-OVMI_INSTR_EXEC(ovmi_exec_load) {
-    ovm_assert(VAL(instr->a).type == OVM_TYPE_I32);
-    u32 dest = VAL(instr->a).u32 + (u32) instr->b;
-    if (dest == 0) __ovm_trigger_exception(state);
-
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_LOAD(OVM_TYPE_I8,  u8)
-        OVM_LOAD(OVM_TYPE_I16, u16)
-        OVM_LOAD(OVM_TYPE_I32, u32)
-        OVM_LOAD(OVM_TYPE_I64, u64)
-        OVM_LOAD(OVM_TYPE_F32, f32)
-        OVM_LOAD(OVM_TYPE_F64, f64)
-    }
-    NEXT_OP;
-}
+OVM_LOAD(i8,  OVM_TYPE_I8,  u8)
+OVM_LOAD(i16, OVM_TYPE_I16, u16)
+OVM_LOAD(i32, OVM_TYPE_I32, u32)
+OVM_LOAD(i64, OVM_TYPE_I64, u64)
+OVM_LOAD(f32, OVM_TYPE_F32, f32)
+OVM_LOAD(f64, OVM_TYPE_F64, f64)
 
 #undef OVM_LOAD
 
-#define OVM_STORE(type_, stype) \
-    case type_: \
+#define OVM_STORE(otype, type_, stype) \
+    OVMI_INSTR_EXEC(ovmi_exec_store_##otype) { \
+        ovm_assert(VAL(instr->r).type == OVM_TYPE_I32); \
+        u32 dest = VAL(instr->r).u32 + (u32) instr->b; \
+        if (dest == 0) __ovm_trigger_exception(state); \
         *(stype *) &memory[dest] = VAL(instr->a).stype; \
-        break;
-
+        NEXT_OP; \
+    }
 
-OVMI_INSTR_EXEC(ovmi_exec_store) {
-    ovm_assert(VAL(instr->r).type == OVM_TYPE_I32);
-    u32 dest = VAL(instr->r).u32 + (u32) instr->b;
-    if (dest == 0) __ovm_trigger_exception(state);
 
-    switch (OVM_INSTR_TYPE(*instr)) {
-        OVM_STORE(OVM_TYPE_I8,  u8)
-        OVM_STORE(OVM_TYPE_I16, u16)
-        OVM_STORE(OVM_TYPE_I32, u32)
-        OVM_STORE(OVM_TYPE_I64, u64)
-        OVM_STORE(OVM_TYPE_F32, f32)
-        OVM_STORE(OVM_TYPE_F64, f64)
-    }
-    NEXT_OP;
-}
+OVM_STORE(i8,  OVM_TYPE_I8,  u8)
+OVM_STORE(i16, OVM_TYPE_I16, u16)
+OVM_STORE(i32, OVM_TYPE_I32, u32)
+OVM_STORE(i64, OVM_TYPE_I64, u64)
+OVM_STORE(f32, OVM_TYPE_F32, f32)
+OVM_STORE(f64, OVM_TYPE_F64, f64)
 
 #undef OVM_STORE
 
@@ -1242,10 +1150,10 @@ OVMI_INSTR_EXEC(ovmi_exec_cvt) {
     VAL(instr->r) = tmp_val; \
     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);
+        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
     }
@@ -1259,7 +1167,7 @@ OVMI_INSTR_EXEC(ovmi_exec_cvt) {
 //
 
 #define CMPXCHG(otype, ctype) \
-    case otype: {\
+    OVMI_INSTR_EXEC(ovmi_exec_cmpxchg_##ctype) { \
         if (VAL(instr->r).u32 == 0) __ovm_trigger_exception(state); \
         ctype *addr = (ctype *) &memory[VAL(instr->r).u32]; \
  \
@@ -1270,19 +1178,11 @@ OVMI_INSTR_EXEC(ovmi_exec_cvt) {
         if (*addr == VAL(instr->a).ctype) { \
             *addr = VAL(instr->b).ctype ; \
         } \
-        break; \
-    }
-
-OVMI_INSTR_EXEC(ovmi_exec_cmpxchg) {
-    switch (OVM_INSTR_TYPE(*instr)) {
-        CMPXCHG(OVM_TYPE_I8,  i8)
-        CMPXCHG(OVM_TYPE_I16, i16)
-        CMPXCHG(OVM_TYPE_I32, i32)
-        CMPXCHG(OVM_TYPE_I64, i64)
+        NEXT_OP; \
     }
 
-    NEXT_OP;
-}
+CMPXCHG(OVM_TYPE_I32, i32)
+CMPXCHG(OVM_TYPE_I64, i64)
 
 #undef CMPXCHG
 
@@ -1296,198 +1196,92 @@ OVMI_INSTR_EXEC(ovmi_exec_illegal) {
 // Dispatch table
 //
 
-static ovmi_instr_exec_t ovmi_dispatch[256] = {
-    // 0x00
-    ovmi_exec_nop,
-    ovmi_exec_add,
-    ovmi_exec_sub,
-    ovmi_exec_mul,
-    ovmi_exec_div,
-    ovmi_exec_div_s,
-    ovmi_exec_rem,
-    ovmi_exec_rem_s,
-    ovmi_exec_and,
-    ovmi_exec_or,
-    ovmi_exec_xor,
-    ovmi_exec_shl,
-    ovmi_exec_shr,
-    ovmi_exec_sar,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-
-    // 0x10
-    ovmi_exec_imm,
-    ovmi_exec_mov,
-    ovmi_exec_load,
-    ovmi_exec_store,
-    ovmi_exec_copy,
-    ovmi_exec_fill,
-    ovmi_exec_reg_get,
-    ovmi_exec_reg_set,
-    ovmi_exec_idx_arr,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-
-    // 0x20
-    ovmi_exec_lt,
-    ovmi_exec_lt_s,
-    ovmi_exec_le,
-    ovmi_exec_le_s,
-    ovmi_exec_eq,
-    ovmi_exec_ge,
-    ovmi_exec_ge_s,
-    ovmi_exec_gt,
-    ovmi_exec_gt_s,
-    ovmi_exec_ne,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-
-    // 0x30
-    ovmi_exec_param,
-    ovmi_exec_return,
-    ovmi_exec_call,
-    ovmi_exec_calli,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-
-    // 0x40
-    ovmi_exec_br,
-    ovmi_exec_br_z,
-    ovmi_exec_br_nz,
-    ovmi_exec_bri,
-    ovmi_exec_bri_z,
-    ovmi_exec_bri_nz,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-
-    // 0x50
-    ovmi_exec_clz,
-    ovmi_exec_ctz,
-    ovmi_exec_popcount,
-    ovmi_exec_rotl,
-    ovmi_exec_rotr,
-    ovmi_exec_abs,
-    ovmi_exec_neg,
-    ovmi_exec_ceil,
-    ovmi_exec_floor,
-    ovmi_exec_trunc,
-    ovmi_exec_nearest,
-    ovmi_exec_sqrt,
-    ovmi_exec_min,
-    ovmi_exec_max,
-    ovmi_exec_copysign,
-    ovmi_exec_illegal,
-
-    // 0x60
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-    ovmi_exec_cvt,
-
-    // 0x70
-    ovmi_exec_cmpxchg,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-    ovmi_exec_illegal,
-
-    // 0x80
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-
-    // 0x90
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-
-    // 0xA0
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-
-    // 0xB0
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-
-    // 0xC0
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-
-    // 0xD0
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-
-    // 0xE0
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-
-    // 0xF0
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
-    ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal, ovmi_exec_illegal,
+#define IROW_UNTYPED(name) ovmi_exec_##name, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+#define IROW_TYPED(name)   NULL, ovmi_exec_##name##_i8, ovmi_exec_##name##_i16, ovmi_exec_##name##_i32, ovmi_exec_##name##_i64, ovmi_exec_##name##_f32, ovmi_exec_##name##_f64, NULL,
+#define IROW_PARTIAL(name) NULL, NULL, NULL, ovmi_exec_##name##_i32, ovmi_exec_##name##_i64, ovmi_exec_##name##_f32, ovmi_exec_##name##_f64, NULL,
+#define IROW_INT(name)     NULL, NULL, NULL, ovmi_exec_##name##_i32, ovmi_exec_##name##_i64, NULL, NULL, NULL,
+#define IROW_FLOAT(name)   NULL, NULL, NULL, NULL, NULL, ovmi_exec_##name##_f32, ovmi_exec_##name##_f64, NULL,
+#define IROW_SAME(name)    ovmi_exec_##name,ovmi_exec_##name,ovmi_exec_##name,ovmi_exec_##name,ovmi_exec_##name,ovmi_exec_##name,ovmi_exec_##name,NULL,
+
+static ovmi_instr_exec_t ovmi_dispatch[] = {
+    IROW_UNTYPED(nop) // 0x00
+    IROW_PARTIAL(add)
+    IROW_PARTIAL(sub)
+    IROW_PARTIAL(mul)
+    IROW_PARTIAL(div)
+    IROW_PARTIAL(div_s)
+    IROW_INT(rem)
+    IROW_INT(rem_s)
+    IROW_INT(and)
+    IROW_INT(or)
+    IROW_INT(xor)
+    IROW_INT(shl)
+    IROW_INT(shr)
+    IROW_INT(sar)
+    IROW_SAME(illegal)
+    IROW_SAME(illegal)
+    IROW_PARTIAL(imm) // 0x10
+    IROW_UNTYPED(mov)
+    IROW_TYPED(load)
+    IROW_TYPED(store)
+    IROW_UNTYPED(copy)
+    IROW_UNTYPED(fill)
+    IROW_UNTYPED(reg_get)
+    IROW_UNTYPED(reg_set)
+    IROW_UNTYPED(idx_arr)
+    IROW_PARTIAL(lt)
+    IROW_PARTIAL(lt_s)
+    IROW_PARTIAL(le)
+    IROW_PARTIAL(le_s)
+    IROW_PARTIAL(eq)
+    IROW_PARTIAL(ge)
+    IROW_PARTIAL(ge_s)
+    IROW_PARTIAL(gt)  // 0x20
+    IROW_PARTIAL(gt_s)
+    IROW_PARTIAL(ne)
+    IROW_UNTYPED(param)
+    IROW_UNTYPED(return)
+    IROW_UNTYPED(call)
+    IROW_UNTYPED(calli)
+    IROW_UNTYPED(br)
+    IROW_UNTYPED(br_z)
+    IROW_UNTYPED(br_nz)
+    IROW_UNTYPED(bri)
+    IROW_UNTYPED(bri_z)
+    IROW_UNTYPED(bri_nz)
+    IROW_INT(clz)
+    IROW_INT(ctz)
+    IROW_INT(popcount)
+    IROW_INT(rotl)  // 0x30
+    IROW_INT(rotr)
+    IROW_FLOAT(abs)
+    IROW_FLOAT(neg)
+    IROW_FLOAT(ceil)
+    IROW_FLOAT(floor)
+    IROW_FLOAT(trunc)
+    IROW_FLOAT(nearest)
+    IROW_FLOAT(sqrt)
+    IROW_FLOAT(min)
+    IROW_FLOAT(max)
+    IROW_FLOAT(copysign)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt) // 0x40
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_SAME(cvt)
+    IROW_INT(cmpxchg)
+    IROW_SAME(illegal)
 };
 
 
index d21e744dba52aaa704687139e9df8c5855a64881..eb055686ed7786936dbac85973d90f5bed61406d 100755 (executable)
Binary files a/shared/lib/linux_x86_64/lib/libovmwasm.so and b/shared/lib/linux_x86_64/lib/libovmwasm.so differ