more complete and nicer assembler
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jun 2022 03:34:18 +0000 (22:34 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jun 2022 03:34:18 +0000 (22:34 -0500)
build.sh
docs/fileformat.md
include/assembler.h
include/vm.h
src/cli.c
src/tools/asm.l
src/tools/assembler.c
src/tools/lex.yy.c
src/vm/program_loader.c
src/vm/vm.c
test.asm

index b4bc9a79b3280b0dfb40e1c5467bbba16620e348..cea3591b3492b4e658db1806af4e332800061513 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -12,7 +12,7 @@ $CC $FLAGS $INCLUDES -shared -fPIC -o $TARGET $C_FILES $LIBS $WARNINGS
 
 C_FILES="src/cli.c"
 TARGET=onyx-debug
-LIBS="-L$(pwd) -lonyx_embedder -Wl,-rpath=./"
+LIBS="-L$(pwd) -lonyx_embedder -lm -Wl,-rpath=./"
 
 $CC $FLAGS $INCLUDES -o $TARGET $C_FILES $LIBS $WARNINGS
 
index 96b3947dac0edf4f87ba27805f422329eabc18a0..362fbc13b7f485f9245427fa96600fdba130db73 100644 (file)
@@ -38,3 +38,9 @@ The names in numerical order.
 
 func-count | (param-count | name-len-with-null (32-bit integer) | name data (null-terminated)) ...
 
+### Register Info
+Register count
+Register names
+
+register-count | (name-len-with-null (32-bit integer) | name data (null-terminated)) ...
+
index 2205e94d7b205d08db51b77278cfeb706de611b2..7ea656ebc6259ffa2aa3ec55fe7be596ed4f4f51 100644 (file)
@@ -7,7 +7,12 @@ typedef struct token_t token_t;
 enum token_type_t {
     token_none,
     token_newline,
+
     token_integer,
+    token_integer_long,
+    token_float,
+    token_float_double,
+
     token_command,
     token_symbol,
     token_register,
index 0a66d8ee10fdda4e5d8671c91a822a23d10144c3..6018f6fc13906c95035ecaa25298005a7438e158 100644 (file)
@@ -43,12 +43,12 @@ struct ovm_static_data_t {
 // VM. It can be constructed incrementally as needed.
 //
 struct ovm_program_t {
-    ovm_store_t *store;
-
+    bh_arr(ovm_instr_t)       code;
     bh_arr(ovm_func_t)        funcs;
     bh_arr(ovm_native_func_t) native_funcs;
 
-    bh_arr(ovm_instr_t)       code;
+    i32 register_count;
+    ovm_store_t *store;
 };
 
 ovm_program_t *ovm_program_new(ovm_store_t *store);
@@ -94,9 +94,10 @@ struct ovm_state_t {
     bh_arr(ovm_value_t) numbered_values;
     bh_arr(ovm_value_t) params;
     bh_arr(ovm_stack_frame_t) stack_frames;
+    bh_arr(ovm_value_t) registers;
 };
 
-ovm_state_t *ovm_state_new(ovm_engine_t *engine);
+ovm_state_t *ovm_state_new(ovm_engine_t *engine, ovm_program_t *program);
 void         ovm_state_delete(ovm_state_t *state);
 
 
@@ -126,8 +127,6 @@ struct ovm_func_t {
 
     i32 param_count;
     i32 value_number_count;
-
-    // return type
 };
  
 ovm_func_t  *ovm_func_new();
@@ -203,54 +202,69 @@ struct ovm_instr_t {
 
 
 #define OVMI_NOP               0x00
-#define OVMI_ADD               0x01   // $r = $a + $b
-#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_IMM               0x10   // $r = i/l/f/d
-#define OVMI_MOV               0x10   // $r = $a
-#define OVMI_LOAD              0x11   // $r = mem[$a]
-#define OVMI_STORE             0x12   // mem[$a] = $b
-#define OVMI_COPY              0x13   // memcpy($r, $a, $b)
-#define OVMI_FILL              0x14   // memset($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_NATIVE_CALL       0x33   // $r = a(...)
-#define OVMI_CALLI             0x34   // $r = $a(...)
-#define OVMI_NATIVE_CALLI      0x35   // $r = $a(...)
+#define OVMI_ADD               0x01   // %r = %a + %b
+#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_IMM               0x10   // %r = i/l/f/d
+#define OVMI_MOV               0x10   // %r = %a
+#define OVMI_LOAD              0x11   // %r = mem[%a]
+#define OVMI_STORE             0x12   // mem[%a] = %b
+#define OVMI_COPY              0x13   // memcpy(%r, %a, %b)
+#define OVMI_FILL              0x14   // memset(%r, %a, %b)
+#define OVMI_REG_GET           0x15   // %r = #a
+#define OVMI_REG_SET           0x16   // #r = %a
+
+#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_NATIVE_CALL       0x33   // %r = a(...)
+#define OVMI_CALLI             0x34   // %r = %a(...)
+#define OVMI_NATIVE_CALLI      0x35   // %r = %a(...)
 
 #define OVMI_BR                0x40   // br pc + a              // Relative branching
-#define OVMI_BR_NZ             0x41   // br pc + a if $b != 0
-#define OVMI_BRI               0x42   // br pc + $a             // Relative branching
-#define OVMI_BRI_NZ            0x43   // 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_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)
+
+// For conversion operations, the "type" of the instruction is
+// destination type, the type in the name is the source type.
+#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)
 
 //
 // OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32) == instruction for adding i32s
index 636f76402c4911f9ffae519250bdbefa70abab9b..a6dde3f3ff7c3ba7b1ef65f13fa100f0e86f39a8 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -1,93 +1,30 @@
 #include "vm.h"
 
+#include <math.h>
+
 void print_result(void *data, ovm_value_t *params, ovm_value_t *result) {
-    printf("Result: %d\n", params[0].i32);
+    switch (params[0].type) {
+        case OVM_TYPE_I32: printf("Result: %d\n", params[0].i32); break;
+        case OVM_TYPE_F32: printf("Result: %f\n", params[0].f32); break;
+    }
 }
 
-int main(int argc, char *argv[]) {
-
-    ovm_store_t *store = ovm_store_new();
-
-    ovm_program_t *prog = ovm_program_new(store);
-
-/*    ovm_instr_t func1_instrs[] = {
-        // { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 0, 10 },
-        // { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 1, 20 },
-        // { .full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_F32), 2, 0, 1 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 6, 10 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 7, 1 },
-        { .full_instr = OVMI_PARAM, 0, 0 },
-        { .full_instr = OVMI_PARAM, 0, 1 },
-        { .full_instr = OVMI_CALL, 2, 1 },
-        { .full_instr = OVMI_PARAM, 0, 2 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_F32), 4, 0 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_I32), 6, 6, 7 },
-        { .full_instr = OVMI_BR_NZ, 0, -4, 6 },
-        { .full_instr = OVMI_RETURN, 0, 4 },
-    };
-
-    ovm_instr_t func2_instrs[] = {
-        { .full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_F32), 2, 0, 1 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 3, 0x1000 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_STORE, OVM_TYPE_F32), 0, 3, 2 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 4, 0x2000 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 5, 4 },
-        { .full_instr = OVMI_COPY, 4, 3, 5 },
-
-        { .full_instr = OVM_TYPED_INSTR(OVMI_LOAD, OVM_TYPE_F32), 2, 4 },
-        { .full_instr = OVMI_RETURN, 0, 2 },
-    };
-    
-    ovm_program_begin_func(prog, "main", 2, 8);
-    ovm_program_add_instructions(prog, sizeof(func1_instrs) / sizeof(*func1_instrs), func1_instrs);
-    ovm_program_begin_func(prog, "add", 2, 6);
-    ovm_program_add_instructions(prog, sizeof(func2_instrs) / sizeof(*func2_instrs), func2_instrs);
-
-    ovm_instr_t add_instrs[] = {
-        { .full_instr = OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32), 2, 0, 1 },
-        { .full_instr = OVMI_RETURN, 2 },
-    };
-
-    ovm_instr_t count_instrs[] = {
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 1, .i = 1 },
-        { .full_instr = OVMI_PARAM, 0, 0 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_NONE), 0, 0 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_SUB, OVM_TYPE_I32), 0, 0, 1 },
-        { .full_instr = OVMI_BR_NZ, 0, -4, 0 },
-        { .full_instr = OVMI_RETURN, -1 },
-    };
-
-    ovm_instr_t main_instrs[] = {
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 0, 1 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 1, 2 },
-        { .full_instr = OVMI_PARAM, 0, 0 },
-        { .full_instr = OVMI_PARAM, 0, 1 },
-        { .full_instr = OVMI_CALL, 2, 0 },
-        { .full_instr = OVMI_PARAM, 0, 2 },
-        { .full_instr = OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_NONE), 0, 0 },
-
-        { .full_instr = OVM_TYPED_INSTR(OVMI_IMM, OVM_TYPE_I32), 3, .i = 10 },
-        { .full_instr = OVMI_PARAM, 0, 3 },
-        { .full_instr = OVMI_CALL, -1, 1 },
-    };
-
-    ovm_program_begin_func(prog, "add", 2, 3);
-    ovm_program_add_instructions(prog, sizeof(add_instrs) / sizeof(*add_instrs), add_instrs);
-    ovm_program_begin_func(prog, "count", 1, 2);
-    ovm_program_add_instructions(prog, sizeof(count_instrs) / sizeof(*count_instrs), count_instrs);
-    ovm_program_begin_func(prog, "main", 0, 4);
-    ovm_program_add_instructions(prog, sizeof(main_instrs) / sizeof(*main_instrs), main_instrs);
-*/
+void c_call_1f64(void *data, ovm_value_t *params, ovm_value_t *result) {
+     result->type = OVM_TYPE_F32;
+     result->f32  = (f32) ((f64 (*)(f64)) data)(params[0].f32);
+}
 
-    ovm_program_register_native_func(prog, "dummy", print_result, NULL, 0);
-    ovm_program_register_native_func(prog, "print_int", print_result, NULL, 1);
+int main(int argc, char *argv[]) {
 
     static ovm_native_func_t native_funcs[] = {
         { "dummy", 0, print_result, NULL },
-        { "print_int", 1, print_result, NULL },
+        { "print", 1, print_result, NULL },
+        { "sin", 1, c_call_1f64, sin },
         { NULL },
     };
 
+    ovm_store_t *store = ovm_store_new();
+    ovm_program_t *prog = ovm_program_new(store);
     ovm_engine_t *engine = ovm_engine_new(store);
 
     ovm_program_load_from_file(prog, engine, "./out.ovm");
@@ -95,15 +32,15 @@ int main(int argc, char *argv[]) {
 
     ovm_program_print_instructions(prog, 0, bh_arr_length(prog->code));
 
-    ovm_state_t  *state = ovm_state_new(engine);
+    ovm_state_t  *state = ovm_state_new(engine, prog);
 
     state->pc = 0;
     ovm_value_t values[] = {
-        { .type = OVM_TYPE_F32, .f32 = 20 },
-        { .type = OVM_TYPE_F32, .f32 = 40 },
+        { .type = OVM_TYPE_I32, .i32 = 20 },
+        { .type = OVM_TYPE_I32, .i32 = 40 },
     };
-    ovm_value_t result = ovm_func_call(engine, state, prog, 2, 0, NULL);
-    // printf("%d %f\n", result.type, result.f32);
+    ovm_value_t result = ovm_func_call(engine, state, prog, 2, 0, values);
+    printf("%d %d\n", result.type, result.i32);
 
     ovm_state_delete(state);
     ovm_engine_delete(engine);
index 8fde370d10895efed276c49394b322384f3a585b..94b2dd9ce34c8bc549ad20f08ffc3fed14b30220 100644 (file)
@@ -43,11 +43,15 @@ ident  [a-zA-Z][a-zA-Z.0-9_]*
 %%
 
 \n                     PUSH_TOKEN(token_newline)
+\/\/.*\n               continue;
 \.{ident}              PUSH_TOKEN(token_command)
+{ident}:               PUSH_TOKEN(token_label)
 {ident}                PUSH_TOKEN(token_symbol)
 \%[0-9]+               PUSH_TOKEN(token_register)
+[0-9]+\.[0-9]+f        PUSH_TOKEN(token_float)
+[0-9]+\.[0-9]+         PUSH_TOKEN(token_float_double)
+[0-9]+l                PUSH_TOKEN(token_integer_long)
 [0-9]+                 PUSH_TOKEN(token_integer)
-:{ident}               PUSH_TOKEN(token_label)
 ","                    PUSH_TOKEN(token_comma)
 
 .
index 7a2d76ac5464c0dc11afd4abb84c43b4e11fa9fc..7cb2af24b1134732f5c8a3e578eb2e4ca3a7442d 100644 (file)
@@ -28,6 +28,7 @@
 static bh_arr(ovm_instr_t) instrs;
 static bh_arr(ovm_func_t) funcs;
 static bh_arr(ovm_native_func_t) native_funcs;
+static bh_arr(char *) register_names;
 
 
 // 
@@ -47,6 +48,7 @@ typedef struct active_label_t {
 static i32 maximum_value_number = 0;
 static bh_arr(patch_t) call_patches;
 static bh_arr(patch_t) label_patches;
+static bh_arr(patch_t) register_patches;
 static bh_arr(active_label_t) active_labels;
 
 
@@ -107,13 +109,33 @@ static struct instruction_mapping_t instr_map[] = {
     { "rem.i32", OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I32), op_reg, op_imm },
     { "rem.i64", OVM_TYPED_INSTR(OVMI_REM, OVM_TYPE_I64), op_reg, op_imm },
 
+
+    { "eq.i8",  OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I8) , op_reg, op_reg, op_reg },
+    { "eq.i16", OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I16), op_reg, op_reg, op_reg },
+    { "eq.i32", OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I32), op_reg, op_reg, op_reg },
+    { "eq.i64", OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_I64), op_reg, op_reg, op_reg },
+    { "eq.f32", OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_F32), op_reg, op_reg, op_reg },
+    { "eq.f64", OVM_TYPED_INSTR(OVMI_EQ, OVM_TYPE_F64), op_reg, op_reg, op_reg },
+
+    { "ne.i8",  OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_I8) , op_reg, op_reg, op_reg },
+    { "ne.i16", OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_I16), op_reg, op_reg, op_reg },
+    { "ne.i32", OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_I32), op_reg, op_reg, op_reg },
+    { "ne.i64", OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_I64), op_reg, op_reg, op_reg },
+    { "ne.f32", OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_F32), op_reg, op_reg, op_reg },
+    { "ne.f64", OVM_TYPED_INSTR(OVMI_NE, OVM_TYPE_F64), op_reg, op_reg, op_reg },
+
     // More operands to do...
 
+    { "reg.get", OVMI_REG_GET, op_reg, op_sym },
+    { "reg.set", OVMI_REG_SET, op_sym, op_reg },
+
     { "param",  OVMI_PARAM,  op_none, op_reg },
     { "br",     OVMI_BR,     op_none, op_sym },
     { "bri",    OVMI_BRI,    op_none, op_reg },
     { "br_nz",  OVMI_BR_NZ,  op_none, op_sym, op_reg },
     { "bri_nz", OVMI_BRI_NZ, op_none, op_reg, op_reg },
+    { "br_z",   OVMI_BR_Z,  op_none, op_sym, op_reg },
+    { "bri_z",  OVMI_BRI_Z, op_none, op_reg, op_reg },
 
     { "return",     OVMI_RETURN },
     { "return.i8",  OVMI_RETURN, op_none, op_reg },
@@ -147,13 +169,42 @@ static struct instruction_mapping_t instr_map[] = {
     { "native_call.f32",  OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_F32),  op_reg , op_sym },
     { "native_call.f64",  OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_F64),  op_reg , op_sym },
 
-    { "native_calli",      OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_NONE), op_none, op_reg },
-    { "native_calli.i8",   OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_I8),   op_reg , op_reg },
-    { "native_calli.i16",  OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_I16),  op_reg , op_reg },
-    { "native_calli.i32",  OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_I32),  op_reg , op_reg },
-    { "native_calli.i64",  OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_I64),  op_reg , op_reg },
-    { "native_calli.f32",  OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_F32),  op_reg , op_reg },
-    { "native_calli.f64",  OVM_TYPED_INSTR(OVMI_NATIVE_CALL, OVM_TYPE_F64),  op_reg , op_reg },
+    { "native_calli",      OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_NONE), op_none, op_reg },
+    { "native_calli.i8",   OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_I8),   op_reg , op_reg },
+    { "native_calli.i16",  OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_I16),  op_reg , op_reg },
+    { "native_calli.i32",  OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_I32),  op_reg , op_reg },
+    { "native_calli.i64",  OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_I64),  op_reg , op_reg },
+    { "native_calli.f32",  OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_F32),  op_reg , op_reg },
+    { "native_calli.f64",  OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_F64),  op_reg , op_reg },
+
+
+    { "cvt.i8.i16", OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I16), op_reg, op_reg },
+    { "cvt.i8.i32", OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I32), op_reg, op_reg },
+    { "cvt.i8.i64", OVM_TYPED_INSTR(OVMI_CVT_I8, OVM_TYPE_I64), op_reg, op_reg },
+
+    { "cvt.i16.i8", OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I8), op_reg, op_reg },
+    { "cvt.i16.i32", OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I32), op_reg, op_reg },
+    { "cvt.i16.i64", OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I64), op_reg, op_reg },
+
+    { "cvt.i32.i8", OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I8), op_reg, op_reg },
+    { "cvt.i32.i16", OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I16), op_reg, op_reg },
+    { "cvt.i32.i64", OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I64), op_reg, op_reg },
+    { "cvt.i32.f32", OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F32), op_reg, op_reg },
+    { "cvt.i32.f64", OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F64), op_reg, op_reg },
+
+    { "cvt.i64.i8", OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I8), op_reg, op_reg },
+    { "cvt.i64.i16", OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I16), op_reg, op_reg },
+    { "cvt.i64.i32", OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I32), op_reg, op_reg },
+    { "cvt.i64.f32", OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F32), op_reg, op_reg },
+    { "cvt.i64.f64", OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F64), op_reg, op_reg },
+
+    { "cvt.f32.i32", OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32), op_reg, op_reg },
+    { "cvt.f32.i64", OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64), op_reg, op_reg },
+    { "cvt.f32.f64", OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_F64), op_reg, op_reg },
+
+    { "cvt.f64.i32", OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32), op_reg, op_reg },
+    { "cvt.f64.i64", OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64), op_reg, op_reg },
+    { "cvt.f64.f32", OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32), op_reg, op_reg },
 };
 
 void parse_register(i32 *dest) {
@@ -168,12 +219,27 @@ void parse_register(i32 *dest) {
 
 void parse_immediate(ovm_instr_t *instr) {
     token_t token = asm_lexer_next_token();
-    //
-    // Only integer immediates are supported right now.
-    EXPECT_TOKEN(token, token_integer);
 
-    if (OVM_INSTR_TYPE(*instr) == OVM_TYPE_I32) instr->i = atoi(token.text);
-    if (OVM_INSTR_TYPE(*instr) == OVM_TYPE_I64) instr->l = atol(token.text);
+    u32 type = OVM_INSTR_TYPE(*instr);
+    if (type == OVM_TYPE_I32 || type == OVM_TYPE_I16 || type == OVM_TYPE_I8) {
+        EXPECT_TOKEN(token, token_integer);
+        instr->i = atoi(token.text);
+    }
+
+    if (type == OVM_TYPE_I64) {
+        EXPECT_TOKEN(token, token_integer_long);
+        instr->l = atol(token.text);
+    }
+
+    if (type == OVM_TYPE_F32) {
+        EXPECT_TOKEN(token, token_float);
+        instr->f = atof(token.text);
+    }
+
+    if (type == OVM_TYPE_F64) {
+        EXPECT_TOKEN(token, token_float_double);
+        instr->d = atof(token.text);
+    }
 }
 
 void parse_symbol(u32 instr_offset, ovm_instr_t *instr) {
@@ -187,6 +253,7 @@ void parse_symbol(u32 instr_offset, ovm_instr_t *instr) {
 
     switch (patch.instr) {
         case OVMI_BR:
+        case OVMI_BR_Z:
         case OVMI_BR_NZ:
             bh_arr_push(label_patches, patch);
             break;
@@ -196,6 +263,11 @@ void parse_symbol(u32 instr_offset, ovm_instr_t *instr) {
             bh_arr_push(call_patches, patch);
             break;
 
+        case OVMI_REG_SET:
+        case OVMI_REG_GET:
+            bh_arr_push(register_patches, patch);
+            break;
+
         default: assert(("BAD CASE", 0));
     }
 }
@@ -241,20 +313,14 @@ void parse_instruction() {
             parse_symbol(bh_arr_length(instrs), &instr); \
             token = asm_lexer_peek_token(); \
             break; \
+    } \
+    if (token.type == token_comma) { \
+        asm_lexer_next_token(); \
+        token = asm_lexer_peek_token(); \
     }
 
     PARSE_OP(r)
-    if (token.type == token_comma) {
-        asm_lexer_next_token();
-        token = asm_lexer_peek_token();
-    }
-
     PARSE_OP(a)
-    if (token.type == token_comma) {
-        asm_lexer_next_token();
-        token = asm_lexer_peek_token();
-    }
-
     PARSE_OP(b)
 
     bh_arr_push(instrs, instr);
@@ -266,7 +332,9 @@ void parse_label() {
     
     active_label_t label;
     label.instr_offset = bh_arr_length(instrs);
-    label.name = token.text + 1;
+    label.name = token.text;
+    label.name[strlen(label.name) - 1] = '\0';
+
     bh_arr_push(active_labels, label);
 }
 
@@ -335,6 +403,14 @@ void parse_command() {
         return;
     }
 
+    if (!strcmp(token.text, ".register")) {
+        token_t name_token = asm_lexer_next_token();
+        EXPECT_TOKEN(name_token, token_symbol);
+
+        bh_arr_push(register_names, name_token.text);
+        return;
+    }
+
     UNEXPECTED_TOKEN(token);
 }
 
@@ -370,7 +446,7 @@ void parse(char *input_file) {
     bh_file_close(&file);
 }
 
-void patch_calls() {
+void patch() {
     bh_arr_each(patch_t, patch, call_patches) {
         ovm_instr_t *instr = &instrs[patch->instr_offset];
 
@@ -396,10 +472,29 @@ void patch_calls() {
         instr->a = func_idx;
     }
 
+    bh_arr_each(patch_t, patch, register_patches) {
+        ovm_instr_t *instr = &instrs[patch->instr_offset];
+
+        i32 result_idx = -1;
+        i32 tmp_idx = 0;
+        bh_arr_each(char *, name, register_names) {
+            if (!strcmp(*name, patch->name)) {
+                result_idx = tmp_idx;
+                break;
+            }
+
+            tmp_idx++;
+        }
+
+        assert(result_idx != -1);
+        if (patch->instr == OVMI_REG_GET) instr->a = result_idx;
+        if (patch->instr == OVMI_REG_SET) instr->r = result_idx;
+    }
 }
 
 void write_file(char *output_file) {
-    ovm_raw_print_instructions(bh_arr_length(instrs), instrs);
+    //
+    // ovm_raw_print_instructions(bh_arr_length(instrs), instrs);
 
     bh_file file;
     bh_file_error error = bh_file_open_mode(&file, BH_FILE_MODE_WRITE, output_file);
@@ -436,6 +531,14 @@ void write_file(char *output_file) {
         bh_file_write(&file, func->name, name_length);
     }
 
+    i32 register_count = bh_arr_length(register_names);
+    bh_file_write(&file, &register_count, 4); // Endian-dependent
+    bh_arr_each(char *, register_name, register_names) {
+        i32 name_length = strlen(*register_name) + 1;
+        bh_file_write(&file, &name_length, 4);
+        bh_file_write(&file, *register_name, name_length);
+    }
+
     bh_file_close(&file);
 }
 
@@ -449,7 +552,7 @@ int main(int argc, char *argv[]) {
     char *output_file = argv[2];
 
     parse(input_file);
-    patch_calls();
+    patch();
     write_file(output_file);
 }
 
@@ -459,7 +562,12 @@ int main(int argc, char *argv[]) {
 char *token_names[] = {
     T(token_none),
     T(token_newline),
+
     T(token_integer),
+    T(token_integer_long),
+    T(token_float),
+    T(token_float_double),
+
     T(token_command),
     T(token_symbol),
     T(token_register),
index 8e91a3a9c8a32b7f38ed9d78cae66f93cdeb32d0..686217e56f776a9388a923393c2e26eccb894080 100644 (file)
@@ -374,8 +374,8 @@ static void yynoreturn yy_fatal_error ( const char* msg  );
        (yy_hold_char) = *yy_cp; \
        *yy_cp = '\0'; \
        (yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 9
-#define YY_END_OF_BUFFER 10
+#define YY_NUM_RULES 13
+#define YY_END_OF_BUFFER 14
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -383,10 +383,11 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static const flex_int16_t yy_accept[20] =
+static const flex_int16_t yy_accept[26] =
     {   0,
-        0,    0,   10,    8,    1,    8,    7,    8,    5,    8,
-        3,    4,    2,    5,    6,    3,    2,    6,    0
+        0,    0,   14,   12,    1,   12,   11,   12,   12,   10,
+        5,    6,    3,    0,    0,   10,    9,    5,    4,    3,
+        0,    2,    8,    7,    0
     } ;
 
 static const YY_CHAR yy_ec[256] =
@@ -395,16 +396,16 @@ static const YY_CHAR yy_ec[256] =
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    3,    1,    1,    1,
-        1,    1,    1,    4,    1,    5,    1,    6,    6,    6,
-        6,    6,    6,    6,    6,    6,    6,    7,    1,    1,
-        1,    1,    1,    1,    8,    8,    8,    8,    8,    8,
-        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
-        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
-        1,    1,    1,    1,    9,    1,    8,    8,    8,    8,
-
-        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
-        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
-        8,    8,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    4,    1,    5,    6,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    8,    1,    1,
+        1,    1,    1,    1,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        1,    1,    1,    1,   10,    1,    9,    9,    9,    9,
+
+        9,   11,    9,    9,    9,    9,    9,   12,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -421,43 +422,48 @@ static const YY_CHAR yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static const YY_CHAR yy_meta[10] =
+static const YY_CHAR yy_meta[13] =
     {   0,
-        1,    1,    1,    1,    2,    2,    1,    2,    2
+        1,    1,    1,    1,    2,    1,    2,    3,    4,    2,
+        4,    4
     } ;
 
-static const flex_int16_t yy_base[23] =
+static const flex_int16_t yy_base[30] =
     {   0,
-        0,    0,   19,   20,   20,   12,   20,    9,   10,    7,
-        0,    8,    0,    7,    0,    0,    0,    0,   20,   10,
-        9,    8
+        0,    0,   36,   37,   37,   23,   37,    0,   18,    8,
+       15,   15,    0,   17,   11,    0,   37,    9,   37,    0,
+       14,   37,   14,   37,   37,   10,   24,   27,   31
     } ;
 
-static const flex_int16_t yy_def[23] =
+static const flex_int16_t yy_def[30] =
     {   0,
-       19,    1,   19,   19,   19,   19,   19,   19,   19,   19,
-       20,   19,   21,   19,   22,   20,   21,   22,    0,   19,
-       19,   19
+       25,    1,   25,   25,   25,   25,   25,   26,   25,   25,
+       27,   25,   28,   29,   25,   10,   25,   27,   25,   28,
+       29,   25,   25,   25,    0,   25,   25,   25,   25
     } ;
 
-static const flex_int16_t yy_nxt[30] =
+static const flex_int16_t yy_nxt[50] =
     {   0,
-        4,    5,    6,    7,    8,    9,   10,   11,    4,   18,
-       17,   16,   14,   12,   15,   14,   13,   12,   19,    3,
-       19,   19,   19,   19,   19,   19,   19,   19,   19
+        4,    5,    6,    7,    8,    9,   10,    4,   11,    4,
+       11,   11,   15,   13,   16,   22,   19,   23,   22,   17,
+       23,   12,   19,   14,   24,   18,   18,   18,   20,   12,
+       20,   21,   21,   21,   21,   25,    3,   25,   25,   25,
+       25,   25,   25,   25,   25,   25,   25,   25,   25
     } ;
 
-static const flex_int16_t yy_chk[30] =
+static const flex_int16_t yy_chk[50] =
     {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,   22,
-       21,   20,   14,   12,   10,    9,    8,    6,    3,   19,
-       19,   19,   19,   19,   19,   19,   19,   19,   19
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,   10,   26,   10,   21,   18,   15,   14,   10,
+       23,   12,   11,    9,   23,   27,   27,   27,   28,    6,
+       28,   29,   29,   29,   29,    3,   25,   25,   25,   25,
+       25,   25,   25,   25,   25,   25,   25,   25,   25
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static const flex_int32_t yy_rule_can_match_eol[10] =
+static const flex_int32_t yy_rule_can_match_eol[14] =
     {   0,
-1, 0, 0, 0, 0, 0, 0, 0, 0,     };
+1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     };
 
 static yy_state_type yy_last_accepting_state;
 static char *yy_last_accepting_cpos;
@@ -508,8 +514,8 @@ char *yytext;
 
 #define PUSH_TOKEN(t) return ((token_t) { .type = t, .text = bh_strdup(bh_heap_allocator(), yytext), .line = yylineno });
 
-#line 512 "src/tools/lex.yy.c"
-#line 513 "src/tools/lex.yy.c"
+#line 518 "src/tools/lex.yy.c"
+#line 519 "src/tools/lex.yy.c"
 
 #define INITIAL 0
 
@@ -729,7 +735,7 @@ YY_DECL
 #line 43 "src/tools/asm.l"
 
 
-#line 733 "src/tools/lex.yy.c"
+#line 739 "src/tools/lex.yy.c"
 
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@ -756,13 +762,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 20 )
+                               if ( yy_current_state >= 26 )
                                        yy_c = yy_meta[yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
                        ++yy_cp;
                        }
-               while ( yy_base[yy_current_state] != 20 );
+               while ( yy_base[yy_current_state] != 37 );
 
 yy_find_action:
                yy_act = yy_accept[yy_current_state];
@@ -803,46 +809,67 @@ YY_RULE_SETUP
 PUSH_TOKEN(token_newline)
        YY_BREAK
 case 2:
+/* rule 2 can match eol */
 YY_RULE_SETUP
 #line 46 "src/tools/asm.l"
-PUSH_TOKEN(token_command)
+continue;
        YY_BREAK
 case 3:
 YY_RULE_SETUP
 #line 47 "src/tools/asm.l"
-PUSH_TOKEN(token_symbol)
+PUSH_TOKEN(token_command)
        YY_BREAK
 case 4:
 YY_RULE_SETUP
 #line 48 "src/tools/asm.l"
-PUSH_TOKEN(token_register)
+PUSH_TOKEN(token_label)
        YY_BREAK
 case 5:
 YY_RULE_SETUP
 #line 49 "src/tools/asm.l"
-PUSH_TOKEN(token_integer)
+PUSH_TOKEN(token_symbol)
        YY_BREAK
 case 6:
 YY_RULE_SETUP
 #line 50 "src/tools/asm.l"
-PUSH_TOKEN(token_label)
+PUSH_TOKEN(token_register)
        YY_BREAK
 case 7:
 YY_RULE_SETUP
 #line 51 "src/tools/asm.l"
-PUSH_TOKEN(token_comma)
+PUSH_TOKEN(token_float)
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 53 "src/tools/asm.l"
-
+#line 52 "src/tools/asm.l"
+PUSH_TOKEN(token_float_double)
        YY_BREAK
 case 9:
 YY_RULE_SETUP
+#line 53 "src/tools/asm.l"
+PUSH_TOKEN(token_integer_long)
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 54 "src/tools/asm.l"
+PUSH_TOKEN(token_integer)
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
 #line 55 "src/tools/asm.l"
+PUSH_TOKEN(token_comma)
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 57 "src/tools/asm.l"
+
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 59 "src/tools/asm.l"
 ECHO;
        YY_BREAK
-#line 846 "src/tools/lex.yy.c"
+#line 873 "src/tools/lex.yy.c"
 case YY_STATE_EOF(INITIAL):
        yyterminate();
 
@@ -1139,7 +1166,7 @@ static int yy_get_next_buffer (void)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 20 )
+                       if ( yy_current_state >= 26 )
                                yy_c = yy_meta[yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1167,11 +1194,11 @@ static int yy_get_next_buffer (void)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 20 )
+               if ( yy_current_state >= 26 )
                        yy_c = yy_meta[yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
-       yy_is_jam = (yy_current_state == 19);
+       yy_is_jam = (yy_current_state == 25);
 
                return yy_is_jam ? 0 : yy_current_state;
 }
@@ -1859,7 +1886,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 55 "src/tools/asm.l"
+#line 59 "src/tools/asm.l"
 
 
 token_t asm_lexer_peek_token() {
index 78e902e911ee9bf3ca34000b3f5f3e5761d3efa6..4b710420091a2f6c12483d9685ef2ff068aada47 100644 (file)
@@ -81,13 +81,28 @@ bool ovm_program_load_from_file(ovm_program_t *program, ovm_engine_t *engine, ch
         ovm_program_register_native_func(program, name_buf, NULL, NULL, param_count);
     }
 
+    //
+    // Register section
+    //
+    bh_file_read(&file, &entry_count, sizeof(i32));
+    fori (i, 0, entry_count) {
+        i32 param_count, name_len;
+        bh_file_read(&file, &param_count, sizeof(i32));
+        bh_file_read(&file, &name_len, sizeof(i32));
+
+        char *name_buf = bh_alloc_array(program->store->arena_allocator, char, name_len);
+        bh_file_read(&file, name_buf, name_len);
+
+        // For now, these are just ignored...
+    }
+    program->register_count = entry_count;
 
     return true;
 }
 
 void ovm_program_link_native_funcs(ovm_program_t *program, ovm_native_func_t *funcs) {
     bh_arr_each(ovm_native_func_t, nf, program->native_funcs) {
-        if (nf->native_func && nf->userdata) continue;
+        if (nf->native_func || nf->userdata) continue;
         
         ovm_native_func_t *func = funcs;
         while (func->name) {
@@ -106,3 +121,4 @@ void ovm_program_link_native_funcs(ovm_program_t *program, ovm_native_func_t *fu
         }
     }
 }
+
index a004d49e6186a68367799bf46d3ca424280a4163..82bd96cc5b66d6debcfa422b30994f12b8e5623a 100644 (file)
@@ -26,6 +26,7 @@ void ovm_store_delete(ovm_store_t *store) {
 ovm_program_t *ovm_program_new(ovm_store_t *store) {
     ovm_program_t *program = bh_alloc_item(store->heap_allocator, ovm_program_t);
     program->store = store;
+    program->register_count = 0;
 
     bh_arr_new(store->heap_allocator, program->funcs, 16);
     bh_arr_new(store->heap_allocator, program->native_funcs, 16);
@@ -183,6 +184,9 @@ static char *ovm_instr_name(i32 full_instr) {
         C(OVMI_COPY)
         C(OVMI_FILL)
 
+        C(OVMI_REG_GET)
+        C(OVMI_REG_SET)
+
         C(OVM_TYPED_INSTR(OVMI_LT, OVM_TYPE_I8))
         C(OVM_TYPED_INSTR(OVMI_LT, OVM_TYPE_I16))
         C(OVM_TYPED_INSTR(OVMI_LT, OVM_TYPE_I32))
@@ -273,7 +277,39 @@ static char *ovm_instr_name(i32 full_instr) {
         C(OVM_TYPED_INSTR(OVMI_NATIVE_CALLI, OVM_TYPE_F64))
 
         C(OVMI_BR)
+        C(OVMI_BR_Z)
         C(OVMI_BR_NZ)
+        C(OVMI_BRI)
+        C(OVMI_BRI_Z)
+        C(OVMI_BRI_NZ)
+
+        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))
+
+        C(OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I16, OVM_TYPE_I64))
+
+        C(OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I32, OVM_TYPE_F64))
+
+        C(OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I8))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I16))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F32))
+        C(OVM_TYPED_INSTR(OVMI_CVT_I64, OVM_TYPE_F64))
+
+        C(OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_CVT_F32, OVM_TYPE_F64))
+
+        C(OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32))
+        C(OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64))
+        C(OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32))
 
         default:
             snprintf(buf, 64, "unknown (%d)", full_instr);
@@ -293,14 +329,14 @@ void ovm_program_print_instructions(ovm_program_t *program, i32 start_instr, i32
         }
 
         ovm_instr_t instr = program->code[i];
-        printf("%48s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
+        printf("%50s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
     }
 }
 
 void ovm_raw_print_instructions(i32 instr_count, ovm_instr_t *instrs) {
     fori (i, 0, instr_count) {
         ovm_instr_t instr = instrs[i];
-        printf("%48s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
+        printf("%50s | r=%02d a=%02d b=%02d  i=%d f=%f l=%ld d=%lf\n", ovm_instr_name(instr.full_instr), instr.r, instr.a, instr.b, instr.i, instr.f, instr.l, instr.d);
     }
 }
 
@@ -335,7 +371,10 @@ void ovm_engine_memory_copy(ovm_engine_t *engine, i64 target, void *data, i64 si
 
 //
 // State
-ovm_state_t *ovm_state_new(ovm_engine_t *engine) {
+//
+// This takes in a program because it needs to know how many registers to allocate.
+// Should there be another mechanism for this? or is this the most concise way?
+ovm_state_t *ovm_state_new(ovm_engine_t *engine, ovm_program_t *program) {
     ovm_store_t *store = engine->store;
     ovm_state_t *state = bh_alloc_item(store->heap_allocator, ovm_state_t);
 
@@ -346,6 +385,8 @@ ovm_state_t *ovm_state_new(ovm_engine_t *engine) {
     bh_arr_new(store->heap_allocator, state->numbered_values, 64);
     bh_arr_new(store->heap_allocator, state->params, 16);
     bh_arr_new(store->heap_allocator, state->stack_frames, 32);
+    bh_arr_new(store->heap_allocator, state->registers, program->register_count);
+    bh_arr_insert_end(state->registers, program->register_count);
 
     return state;
 }
@@ -356,6 +397,7 @@ void ovm_state_delete(ovm_state_t *state) {
     bh_arr_free(state->numbered_values);
     bh_arr_free(state->params);
     bh_arr_free(state->stack_frames);
+    bh_arr_free(state->registers);
 
     bh_free(store->heap_allocator, state);
 }
@@ -364,7 +406,7 @@ void ovm_state_delete(ovm_state_t *state) {
 //
 // Function calling
 
-static void ovm__func_setup_stack_frame(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *program, i32 func_idx, i32 result_number) {
+static inline void ovm__func_setup_stack_frame(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *program, i32 func_idx, i32 result_number) {
     ovm_func_t *func = &program->funcs[func_idx];
 
     //
@@ -400,7 +442,8 @@ ovm_value_t ovm_func_call(ovm_engine_t *engine, ovm_state_t *state, ovm_program_
     state->pc = program->funcs[func_idx].start_instr;
     ovm_run_code(engine, state, program);
 
-    return state->numbered_values[state->value_number_offset--];
+    state->value_number_offset -= 1;
+    return bh_arr_pop(state->numbered_values);
 }
 
 
@@ -650,6 +693,16 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
                 break;
             }
 
+            case OVMI_REG_GET: {
+                VAL(instr.r) = state->registers[instr.a];
+                break;
+            }
+
+            case OVMI_REG_SET: {
+                state->registers[instr.r] = VAL(instr.a);
+                break;
+            }
+
             case OVMI_PARAM:
                 bh_arr_push(state->params, VAL(instr.a));
                 break;
@@ -703,6 +756,7 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             bh_arr_set_length(state->params, 0); \
  \
             if (OVM_INSTR_TYPE(instr) != OVM_TYPE_NONE) { \
+                assert(OVM_INSTR_TYPE(instr) == result.type); \
                 VAL(instr.r) = result; \
             }
 
@@ -734,7 +788,44 @@ void ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *progr
             case OVMI_BRI:    state->pc += VAL(instr.a).i32; break;
             case OVMI_BR_NZ:  if (VAL(instr.b).i32 != 0) state->pc += instr.a; break;
             case OVMI_BRI_NZ: if (VAL(instr.b).i32 != 0) state->pc += VAL(instr.a).i32; break;
+            case OVMI_BR_Z:   if (VAL(instr.b).i32 == 0) state->pc += instr.a; break;
+            case OVMI_BRI_Z:  if (VAL(instr.b).i32 == 0) state->pc += VAL(instr.a).i32; break;
+
+
+#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_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_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_F32, OVM_TYPE_F64): CVT(f32, f64, OVM_TYPE_F64, f64);
+
+            case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I32): CVT(f64, i32, OVM_TYPE_I32, u32);
+            case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_I64): CVT(f64, i64, OVM_TYPE_I64, u64);
+            case OVM_TYPED_INSTR(OVMI_CVT_F64, OVM_TYPE_F32): CVT(f64, f32, OVM_TYPE_F32, f32);
 
+#undef CVT
             default:
                 printf("ERROR:\n");
                 ovm_program_print_instructions(program, state->pc - 1, 1);
index d4b2e34078936bd8c8bdae1d75dc9eeb40d74d7d..27fc31e7f28a31cebf6fcae035c7df5361e7766d 100644 (file)
--- a/test.asm
+++ b/test.asm
@@ -1,6 +1,9 @@
 
 .native_func dummy 0
-.native_func print_int 1
+.native_func print 1
+.native_func sin 1
+
+.register stack_ptr
 
 .func add 2
     add.i32 %2, %0, %1
 
 .func count 1
     imm.i32 %1, 1
+    imm.i32 %2, 5
 
-  :loop
+  loop:
     param %0
-    native_call print_int
+    native_call print
     sub.i32 %0, %0, %1
-    br_nz loop, %0
 
-    br skip
+    eq.i32 %3, %0, %2
+    br_z loop, %3
+
+    // br skip
     imm.i32 %1, 123
     param %1
-    native_call print_int
-  :skip
+    native_call print
+  skip:
     return
 
 .func main 0
+    reg.get %10, stack_ptr
+
     imm.i32 %0, 1
     imm.i32 %1, 2
     param %0
     param %1
     call.i32 %2, add
     param %2
-    native_call print_int
+    native_call print
 
     imm.i32 %3, 10
     param %3
     call count
 
+    reg.set stack_ptr, %10
     return
 
+.func sin_test 0
+    imm.f32 %0, 3.14159265f
+    imm.f32 %1, 0.5f
+    mul.f32 %2, %0, %1
+
+    param %2
+    native_call.f32 %3, sin
+
+    param %3
+    native_call print
+
+    return
+
+