RPA Toolkit
merge the work on extended ops
authorMartin Stoilov <martin@rpasearch.com>
Mon, 8 Nov 2010 23:36:16 +0000 (15:36 -0800)
committerMartin Stoilov <martin@rpasearch.com>
Mon, 8 Nov 2010 23:36:16 +0000 (15:36 -0800)
15 files changed:
arch/linux/x86_64/rtypes.h
rvm/build/linux/rvm.mk
rvm/rvmcpu.c
rvm/rvmcpu.h
rvm/rvmoperator.c
rvm/rvmoperator.h
rvm/rvmoperatorcast.c [new file with mode: 0644]
rvm/rvmoperatorcast.h [new file with mode: 0644]
rvm/rvmreg.c
rvm/rvmreg.h
tests/asm-bl.c
tests/asm-cast.c [new file with mode: 0644]
tests/build/linux/robject-tests.mk
tests/loop-test.c [new file with mode: 0644]
tests/opmap-test.c

index afbeb50..1d9b271 100644 (file)
@@ -61,6 +61,8 @@ typedef unsigned int ratomic_t;
                        : "ir" (val), "m" (*ptr)); } while (0)
 
 
+#define R_DEBUG_BRAKE __asm__ ("int $3")
+#define ASSERT(__a__) do {if (!(__a__)) R_DEBUG_BRAKE; } while (0)
 
 #ifndef NULL
 #ifdef __cplusplus
index 93df776..ab737cd 100644 (file)
@@ -8,6 +8,7 @@ RVM_OBJECTS =   \
        $(OUTDIR)/rrefreg.o \
        $(OUTDIR)/rvmcpu.o \
        $(OUTDIR)/rvmoperator.o \
+       $(OUTDIR)/rvmoperatorcast.o \
        $(OUTDIR)/rvmoperatorcat.o \
        $(OUTDIR)/rvmoperatoradd.o \
        $(OUTDIR)/rvmoperatorsub.o \
index 27bb0b2..a6dc5d2 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include "rvmcpu.h"
+#include "rvmoperator.h"
+#include "rvmoperatorcast.h"
 #include "rmem.h"
 #include "rstring.h"
-#include "rvmcpu.h"
+#include "rvmreg.h"
 
 
 static const char *stropcalls[] = {
@@ -86,7 +89,10 @@ static const char *stropcalls[] = {
        "RVM_PUSHM",
        "RVM_POPM",     
        "RVM_TST",      
-       "RVM_TEQ",      
+       "RVM_TEQ",
+       "ERVM_CAST",            /* Cast: op1 = (op3)op2 */
+       "ERVM_TYPE",            /* Type: op1 = typeof(op2) */
+       "ERVM_MOV",
 };
 
 
@@ -777,8 +783,12 @@ int rvm_asm_dump_pi_to_str(rvm_asmins_t *pi, char *str, ruint size)
        str += ret;
        sz -= ret;
 
-       if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)RVM_REG_GETU(&pi->data))) < 0)
+//     if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)RVM_REG_GETU(&pi->data))) < 0)
+//             return ret;
+       if ((ret = rvm_snprintf(str, sz, "0x%lx  ", (unsigned long)pi->data)) < 0)
                return ret;
+
+
        str += ret;
        sz -= ret;
 
@@ -823,6 +833,223 @@ static void rvm_cpu_dumpregs(rvm_asmins_t *pi, rvmcpu_t *vm)
 }
 
 
+static void ervm_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
+       rvmreg_t tmp;
+
+       RVM_REG_CLEAR(&tmp);
+       RVM_REG_SETTYPE(&tmp, type);
+       rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
+}
+
+
+static void ervm_op_type(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETTYPE(cpu, ins->op2);
+
+       RVM_CPUREG_CLEAR(cpu, ins->op1);
+       RVM_CPUREG_SETU(cpu, ins->op1, type);
+}
+
+
+static void ervm_op_mov(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rvm_op_mov(cpu, ins);
+}
+
+
+static void ervm_op_adc(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = op2 + op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 1 : 0);
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
+                                                       (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
+}
+
+
+static void ervm_op_adds(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = op2 + op3;
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, res < op2 || res < op3);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) == (op3 & RVM_SIGN_BIT) &&
+                                                       (res & RVM_SIGN_BIT) != (op2 & RVM_SIGN_BIT));
+}
+
+
+static void ervm_op_add(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rvmreg_type_t type;
+       rvmreg_t *r2 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op2));
+       rvmreg_t *r3 = rvm_reg_unshadow(RVM_CPUREG_PTR(cpu, ins->op3));
+
+       type = RVM_REG_GETTYPE(r2);
+
+
+       if (type != RVM_REG_GETTYPE(r3))
+               RVM_ABORT(cpu, RVM_E_CAST);
+
+       switch (type) {
+       case RVM_DTYPE_UNSIGNED:
+               RVM_CPUREG_SETU(cpu, ins->op1, RVM_REG_GETU(r2) + RVM_REG_GETU(r2));
+               RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_NONE);
+               RVM_CPUREG_CLRFLAG(cpu, ins->op1, RVM_INFOBIT_ROBJECT);
+               break;
+       case RVM_DTYPE_LONG:
+               RVM_CPUREG_SETU(cpu, ins->op1, RVM_REG_GETL(r2) + RVM_REG_GETL(r2));
+               RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_LONG);
+               RVM_CPUREG_CLRFLAG(cpu, ins->op1, RVM_INFOBIT_ROBJECT);
+               break;
+       case RVM_DTYPE_DOUBLE:
+               RVM_CPUREG_SETD(cpu, ins->op1, RVM_REG_GETD(r2) + RVM_REG_GETD(r2));
+               RVM_CPUREG_SETTYPE(cpu, ins->op1, RVM_DTYPE_DOUBLE);
+               RVM_CPUREG_CLRFLAG(cpu, ins->op1, RVM_INFOBIT_ROBJECT);
+               break;
+       default:
+               RVM_ABORT(cpu, RVM_E_CAST);
+       };
+}
+
+
+static void ervm_op_and(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = op2 & op3;
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_CLRALL(cpu);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+}
+
+
+static void ervm_op_eor(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = op2 ^ op3;
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_CLRALL(cpu);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+}
+
+
+static void ervm_op_mls(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rsword res;
+       rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = (rsword)(op2 * op3);
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       /* TBD: Not sure how to update the RVM_STATUS_C */
+       RVM_STATUS_CLRALL(cpu);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+}
+
+
+static void ervm_op_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) * RVM_CPUREG_GETU(cpu, ins->op3));
+}
+
+
+static void ervm_op_muls(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = op2 * op3;
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_CLRALL(cpu);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, op2 && (res / op2) != op3);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+}
+
+
+static void ervm_op_sub(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) - RVM_CPUREG_GETU(cpu, ins->op3));
+}
+
+
+static void ervm_op_subs(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = op2 - op3;
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));  /* borrow = !carry */
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
+                                                       (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
+}
+
+
+static void ervm_op_sbc(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       res = op2 - op3 + (RVM_STATUS_GETBIT(cpu, RVM_STATUS_C) ? 0 : -1);
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_C, !(res > op2));     /* borrow = !carry */
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_V, (op2 & RVM_SIGN_BIT) != (op3 & RVM_SIGN_BIT) &&
+                                                       (res & RVM_SIGN_BIT) == (op2 & RVM_SIGN_BIT));
+}
+
+
+static void ervm_op_div(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       if (!RVM_CPUREG_GETU(cpu, ins->op3))
+               RVM_ABORT(cpu, RVM_E_DIVZERO);
+
+       RVM_CPUREG_SETU(cpu, ins->op1, RVM_CPUREG_GETU(cpu, ins->op2) / RVM_CPUREG_GETU(cpu, ins->op3));
+}
+
+
+static void ervm_op_divs(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rword res, op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       if (!op3)
+               RVM_ABORT(cpu, RVM_E_DIVZERO);
+       res = op2 / op3;
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_CLRALL(cpu);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+}
+
+
+static void ervm_op_dvs(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rsword res;
+       rsword op2 = RVM_CPUREG_GETU(cpu, ins->op2), op3 = RVM_CPUREG_GETU(cpu, ins->op3);
+
+       if (!op3)
+               RVM_ABORT(cpu, RVM_E_DIVZERO);
+       res = (rsword)(op2 / op3);
+       RVM_CPUREG_SETU(cpu, ins->op1, res);
+       RVM_STATUS_CLRALL(cpu);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !res);
+       RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, res & RVM_SIGN_BIT);
+}
+
+
 static rvm_cpu_op ops[] = {
        rvm_op_exit,            // RVM_EXT
        rvm_op_asr,                     // RVM_ASR
@@ -883,6 +1110,25 @@ static rvm_cpu_op ops[] = {
        rvm_op_popm,            // RVM_POPM
        rvm_op_tst,             // RVM_TST
        rvm_op_teq,             // RVM_TEQ
+
+/* Extended VM instructions */
+       ervm_op_cast,           // ERVM_CAST
+       ervm_op_type,           // ERVM_TYPE
+       ervm_op_mov,            // ERVM_MOV
+       ervm_op_add,            // ERVM_ADD
+       ervm_op_adds,           // ERVM_ADDS
+       ervm_op_adc,            // ERVM_ADC
+       ervm_op_and,            // ERVM_AND
+       ervm_op_eor,            // ERVM_EOR
+       ervm_op_sub,            // ERVM_SUB
+       ervm_op_subs,           // ERVM_SUBS
+       ervm_op_sbc,            // ERVM_SBC
+       ervm_op_mul,            // ERVM_MUL
+       ervm_op_mls,            // ERVM_MLS
+       ervm_op_muls,           // ERVM_MULS
+       ervm_op_div,            // RVM_DIV
+       ervm_op_dvs,            // RVM_DVS
+       ervm_op_divs,           // RVM_DIVS
        (void*) 0,
        (void*) 0,
        (void*) 0,
@@ -905,6 +1151,8 @@ rvmcpu_t *rvm_cpu_create()
        r_memset(cpu, 0, sizeof(*cpu));
        cpu->switables = r_array_create(sizeof(rvm_switable_t*));
        cpu->stack = r_array_create(sizeof(rvmreg_t));
+       cpu->opmap = rvm_opmap_create();
+       rvm_op_cast_init(cpu->opmap);
        return cpu;
 }
 
@@ -914,6 +1162,7 @@ void rvm_cpu_destroy(rvmcpu_t *cpu)
 //     rvm_free(cpu->stack);
        r_array_destroy(cpu->switables);
        r_array_destroy(cpu->stack);
+       rvm_opmap_destroy(cpu->opmap);
        r_free(cpu);
 }
 
@@ -927,8 +1176,12 @@ rint rvm_cpu_exec(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
        cpu->error = 0;
        do {
                pi = RVM_CPUREG_GETIP(cpu, PC);
-               cpu->r[DA] = pi->data;
+               RVM_CPUREG_SETU(cpu, DA, pi->data);
                ops[pi->opcode](cpu, pi);
+#ifdef DEBUG
+               if (RVM_CPUREG_GETTYPE(cpu, DA) || RVM_CPUREG_TSTFLAG(cpu, DA, RVM_INFOBIT_ALL))
+                       RVM_ABORT(cpu, RVM_E_ILLEGAL);
+#endif
                if (cpu->abort)
                        return -1;
                RVM_CPUREG_INCIP(cpu, PC, 1);
@@ -946,8 +1199,13 @@ rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off)
        cpu->error = 0;
        do {
                pi = RVM_CPUREG_GETIP(cpu, PC);
-               cpu->r[DA] = pi->data;
+               RVM_CPUREG_CLEAR(cpu, DA);
+               RVM_CPUREG_SETU(cpu, DA, pi->data);
                ops[pi->opcode](cpu, pi);
+#ifdef DEBUG
+               if (RVM_CPUREG_GETTYPE(cpu, DA) || RVM_CPUREG_TSTFLAG(cpu, DA, RVM_INFOBIT_ALL))
+                       RVM_ABORT(cpu, RVM_E_ILLEGAL);
+#endif
                if (cpu->abort)
                        return -1;
                rvm_cpu_dumpregs(pi, cpu);              
@@ -987,21 +1245,6 @@ rint rvmcpu_switable_add(rvmcpu_t *cpu, rvm_switable_t *switable)
 }
 
 
-rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data)
-{
-       rvm_asmins_t a;
-
-       r_memset(&a, 0, sizeof(a));
-       a.opcode = (unsigned char) opcode;
-       a.op1 = (unsigned char)op1;
-       a.op2 = (unsigned char)op2;
-       a.op3 = (unsigned char)op3;
-       RVM_REG_GETD(&a.data) = data;
-       RVM_REG_SETTYPE(&a.data, RVM_DTYPE_DOUBLE);
-       return a;
-}
-
-
 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data)
 {
        rvm_asmins_t a;
@@ -1011,13 +1254,15 @@ rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer da
        a.op1 = (unsigned char)op1;
        a.op2 = (unsigned char)op2;
        a.op3 = (unsigned char)op3;
-       RVM_REG_GETP(&a.data) = data;
-       RVM_REG_SETTYPE(&a.data, RVM_DTYPE_POINTER);
+       a.data = (rword)data;
+
+//     RVM_REG_GETP(&a.data) = data;
+//     RVM_REG_SETTYPE(&a.data, RVM_DTYPE_POINTER);
        return a;
 }
 
 
-rvm_asmins_t rvm_asmu(rword opcode, rword op1, rword op2, rword op3, rword data)
+rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
 {
        rvm_asmins_t a;
 
@@ -1026,8 +1271,10 @@ rvm_asmins_t rvm_asmu(rword opcode, rword op1, rword op2, rword op3, rword data)
        a.op1 = (unsigned char)op1;
        a.op2 = (unsigned char)op2;
        a.op3 = (unsigned char)op3;
-       RVM_REG_GETU(&a.data) = data;
-       RVM_REG_SETTYPE(&a.data, RVM_DTYPE_WORD);
+       a.data = (rword)data;
+
+//     RVM_REG_GETU(&a.data) = data;
+//     RVM_REG_SETTYPE(&a.data, RVM_DTYPE_WORD);
        return a;
 }
 
@@ -1041,17 +1288,14 @@ rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data)
        a.op1 = (unsigned char)op1;
        a.op2 = (unsigned char)op2;
        a.op3 = (unsigned char)op3;
-       RVM_REG_GETL(&a.data) = (rword)data;
-       RVM_REG_SETTYPE(&a.data, RVM_DTYPE_LONG);
+       a.data = (rword)data;
+
+//     RVM_REG_GETL(&a.data) = (rword)data;
+//     RVM_REG_SETTYPE(&a.data, RVM_DTYPE_LONG);
        return a;
 }
 
 
-rvm_asmins_t rvm_asmi(rword opcode, rword op1, rword op2, rword op3, rint data)
-{
-       return rvm_asml(opcode, op1, op2, op3, data);
-}
-
 
 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc)
 {
@@ -1062,8 +1306,11 @@ rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pR
        a.op1 = (unsigned char)op1;
        a.op2 = (unsigned char)op2;
        a.op3 = (unsigned char)op3;
-       RVM_REG_GETP(&a.data) = pReloc;
-       RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCPTR);
+       a.data = (rword)pReloc;
+       a.flags = RVM_ASMINS_RELOC | RVM_ASMINS_RELOCPTR;
+
+//     RVM_REG_GETP(&a.data) = pReloc;
+//     RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCPTR);
        return a;
 }
 
@@ -1077,15 +1324,12 @@ rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pR
        a.op1 = (unsigned char)op1;
        a.op2 = (unsigned char)op2;
        a.op3 = (unsigned char)op3;
-       RVM_REG_GETP(&a.data) = pReloc;
-       RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCINDEX);
-       return a;
-}
-
+       a.data = (rword)pReloc;
+       a.flags = RVM_ASMINS_RELOC;
 
-rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data)
-{
-       return rvm_asmu(opcode, op1, op2, op3, data);
+//     RVM_REG_GETP(&a.data) = pReloc;
+//     RVM_REG_SETTYPE(&a.data, RVM_DTYPE_RELOCINDEX);
+       return a;
 }
 
 
@@ -1096,14 +1340,16 @@ void rvm_relocate(rvm_asmins_t *code, rsize_t size)
        rulong off;
 
        for (off = 0; off < size; off++, code++) {
-               if (RVM_REG_GETTYPE(&code->data) == RVM_DTYPE_RELOCPTR) {
-                       RVM_REG_SETTYPE(&code->data, RVM_DTYPE_NONE);
-                       reloc = *((rvm_asmins_t **)RVM_REG_GETP(&code->data));
-                       RVM_REG_GETU(&code->data) = reloc - code;
-               } else if (RVM_REG_GETTYPE(&code->data) == RVM_DTYPE_RELOCINDEX) {
-                       RVM_REG_SETTYPE(&code->data, RVM_DTYPE_NONE);
-                       relocindex = *((rulong *)RVM_REG_GETP(&code->data));
-                       RVM_REG_GETU(&code->data) = relocindex - off;
+               if (code->flags & RVM_ASMINS_RELOC) {
+                       if (code->flags & RVM_ASMINS_RELOCPTR) {
+                               reloc = *((rvm_asmins_t **)code->data);
+                               code->data = reloc - code;
+                       } else {
+                               relocindex = *((rulong *)code->data);
+                               code->data = relocindex - off;
+                       }
+                       code->flags &= ~(RVM_ASMINS_RELOCPTR | RVM_ASMINS_RELOC);
                }
        }
 }
+
index 214643e..db603aa 100644 (file)
@@ -92,11 +92,31 @@ enum {
        RVM_POPM,
        RVM_TST,
        RVM_TEQ,
+
+/* Extended VM opcodes, */
+       ERVM_CAST,              /* Cast: op1 = (op3)op2 */
+       ERVM_TYPE,              /* Type: op1 = typeof(op2) */
+       ERVM_MOV,
+       ERVM_ADD,
+       ERVM_ADDS,              /* Add: op1 = op2 + op3, update the status register */
+       ERVM_ADC,               /* Add: op1 = op2 + op3 + C, update the status register */
+       ERVM_AND,               /* Bitwise AND: op1 = op2 & op3, update status register */
+       ERVM_EOR,               /* XOR: op1 = op2 ^ op3, update the status register */
+       ERVM_SUB,
+       ERVM_SUBS,
+       ERVM_SBC,
+       ERVM_MUL,
+       ERVM_MLS,               /* Signed multiplication: op1 = op2 * op3 */
+       ERVM_MULS,
+       ERVM_DIV,               /* Divide: op1 = op2 / op3 */
+       ERVM_DVS,               /* Signed division: op1 = op2 / op3 */
+       ERVM_DIVS,              /* Divide: op1 = op2 / op3, Update the status register */
 };
 
 
 #define RVM_DTYPE_NONE 0
 #define RVM_DTYPE_WORD RVM_DTYPE_NONE
+#define RVM_DTYPE_UNSIGNED RVM_DTYPE_NONE
 #define RVM_DTYPE_LONG 1
 #define RVM_DTYPE_DOUBLE 2
 #define RVM_DTYPE_BOOLEAN 3
@@ -158,12 +178,12 @@ do { \
 #define SP R13
 #define LR R14
 #define PC R15
-#define DA 16
+#define DA 16          /* The DA register should never be modified manually, otherwise the result is undefined */
 #define RLST 16
 #define XX 255
 
 #define RVM_STACK_CHUNK 256
-#define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; return; } while (0)
+#define RVM_ABORT(__cpu__, __e__) do { __cpu__->error = (__e__); (__cpu__)->abort = 1; ASSERT(0); return; } while (0)
 #define BIT(__shiftby__) (1 << (__shiftby__))
 
 #define RVM_CPUREG_PTR(__cpu__, __r__) (&(__cpu__)->r[(__r__)])
@@ -172,13 +192,13 @@ do { \
 
 #define RVM_REG_GETTYPE(__r__) (__r__)->type
 #define RVM_REG_SETTYPE(__r__, __val__) do { (__r__)->type = (__val__); } while(0);
-#define RVM_CPUREG_GETTYPE(__cpu__, __r__) RVM_CPUREG_GETTYPE(RVM_CPUREG_PTR(__cpu__, __r__))
+#define RVM_CPUREG_GETTYPE(__cpu__, __r__) RVM_REG_GETTYPE(RVM_CPUREG_PTR(__cpu__, __r__))
 #define RVM_CPUREG_SETTYPE(__cpu__, __r__, __val__) RVM_REG_SETTYPE(RVM_CPUREG_PTR(__cpu__, __r__), __val__)
 
 #define RVM_REG_TSTFLAG(__r__, __flag__) ((__r__)->flags & (__flag__)) ? TRUE : FALSE
 #define RVM_REG_SETFLAG(__r__, __flag__) do { (__r__)->flags |= (__flag__); } while (0)
 #define RVM_REG_CLRFLAG(__r__, __flag__) do { (__r__)->flags &= ~(__flag__); } while (0)
-#define RVM_CPUREG_GETFLAG(__cpu__, __r__, __flag__) RVM_REG_TSTFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
+#define RVM_CPUREG_TSTFLAG(__cpu__, __r__, __flag__) RVM_REG_TSTFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
 #define RVM_CPUREG_SETFLAG(__cpu__, __r__, __flag__) RVM_REG_SETFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
 #define RVM_CPUREG_CLRFLAG(__cpu__, __r__, __flag__) RVM_REG_CLRFLAG(RVM_CPUREG_PTR(__cpu__, __r__), __flag__)
 
@@ -212,17 +232,20 @@ do { \
 //#define RVM_REG_REF(__r__) do { if (rvm_reg_gettype(__r__) == RVM_DTYPE_REFREG) r_ref_inc((rref_t*)RVM_REG_GETP(__r__));} while (0)
 //#define RVM_REG_UNREF(__r__) do { if (rvm_reg_gettype(__r__) == RVM_DTYPE_REFREG) r_ref_dec((rref_t*)RVM_REG_GETP(__r__));} while (0)
 #define RVM_REG_CLEAR(__r__) do { (__r__)->v.w = 0UL; (__r__)->type = 0; (__r__)->flags = 0;  } while (0)
+#define RVM_CPUREG_CLEAR(__cpu__, __r__) RVM_REG_CLEAR(RVM_CPUREG_PTR(__cpu__, __r__))
+
 
 #define RVM_SWI_TABLE(__op__) ((__op__) >> 16)
 #define RVM_SWI_NUM(__op__) ((__op__) & ((1 << 16) - 1))
 #define RVM_SWI_ID(__t__, __o__) ((((__t__) & ((1 << 16) - 1))  << 16) | ((__o__) & ((1 << 16) - 1)))
 
 
-#define RVM_E_DIVZERO  (1)
-#define RVM_E_ILLEGAL  (2)
-#define RVM_E_SWINUM   (3)
-#define RVM_E_SWITABLE (4)
-
+#define RVM_E_DIVZERO          (1)
+#define RVM_E_ILLEGAL          (2)
+#define RVM_E_CAST                     (3)
+#define RVM_E_SWINUM           (4)
+#define RVM_E_SWITABLE         (5)
+#define RVM_E_ILLEGALDST       (6)
 
 typedef struct rvm_asmins_s rvm_asmins_t;
 typedef struct rvmcpu_s rvmcpu_t;
@@ -235,6 +258,9 @@ typedef struct rvm_switable_s {
 } rvm_switable_t;
 
 
+typedef ruint16 rvmreg_type_t;
+typedef ruint16 rvmreg_flags_t;
+
 typedef struct rvmreg_s {
        union {
                rword w;
@@ -243,20 +269,24 @@ typedef struct rvmreg_s {
                rdouble d;
                ruint8 c[RVM_MIN_REGSIZE];
        } v;
-       ruint16 type;
-       ruint16 flags;
+       rvmreg_type_t type;
+       rvmreg_flags_t flags;
        ruint32 size;
 } rvmreg_t;
 
+#define RVM_ASMINS_RELOC (1 << 0)
+#define RVM_ASMINS_RELOCPTR (1 << 1)
 
 struct rvm_asmins_s {
        ruint8 opcode;
-       ruint8 op1;
-       ruint8 op2;
-       ruint8 op3;
-       rvmreg_t data;  
+       ruint8 flags;
+       ruint16 op1:5;
+       ruint16 op2:5;
+       ruint16 op3:5;
+       rword data;
 };
 
+struct rvm_opmap_s;
 
 struct rvmcpu_s {
        rvmreg_t r[DA + 1];
@@ -265,6 +295,7 @@ struct rvmcpu_s {
        rword abort;
        rarray_t *switables;
        rarray_t *stack;
+       struct rvm_opmap_s *opmap;
        void *userdata;
 };
 
@@ -277,13 +308,10 @@ rint rvm_cpu_exec_debug(rvmcpu_t *cpu, rvm_asmins_t *prog, rword off);
 rint rvm_cpu_getswi(rvmcpu_t *cpu, const rchar *swiname);
 void rvm_relocate(rvm_asmins_t *code, rsize_t size);
 rvm_asmins_t rvm_asm(rword opcode, rword op1, rword op2, rword op3, rword data);
-rvm_asmins_t rvm_asmi(rword opcode, rword op1, rword op2, rword op3, rint data);
 rvm_asmins_t rvm_asml(rword opcode, rword op1, rword op2, rword op3, rlong data);
-rvm_asmins_t rvm_asmu(rword opcode, rword op1, rword op2, rword op3, rword data);
 rvm_asmins_t rvm_asmp(rword opcode, rword op1, rword op2, rword op3, rpointer data);
 rvm_asmins_t rvm_asmr(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
 rvm_asmins_t rvm_asmx(rword opcode, rword op1, rword op2, rword op3, rpointer pReloc);
-rvm_asmins_t rvm_asmd(rword opcode, rword op1, rword op2, rword op3, rdouble data);
 void rvm_asm_dump(rvm_asmins_t *pi, ruint count);
 
 
index e272b80..73c45f5 100644 (file)
@@ -58,10 +58,11 @@ void rvm_opmap_add_unary_operator(rvm_opmap_t *opmap, rushort opid)
 rint rvm_opmap_set_binary_handler(rvm_opmap_t *opmap, rushort opid, rvm_binaryop_handler func, ruchar firstType, ruchar secondType)
 {
        rvm_ophandler_t *h;
+       ruint index = RVM_OP_HANDLER(firstType, secondType);
        rvm_opinfo_t *opinfo = ((rvm_opinfo_t*)r_array_slot(opmap->operators, opid));
        if (!opinfo->handlers)
                return -1;
-       h = &opinfo->handlers[RVM_OP_HANDLER(firstType, secondType)];
+       h = &opinfo->handlers[index];
        h->op = func;
        return 0;
 }
index fca8242..7ee2616 100644 (file)
@@ -15,6 +15,7 @@
 #define RVM_OPID_MUL 3
 #define RVM_OPID_DIV 4
 #define RVM_OPID_CAT 5
+#define RVM_OPID_CAST 6
 
 /*
  * Important: the res pointer might be the same as one of the arguments, the operator must
diff --git a/rvm/rvmoperatorcast.c b/rvm/rvmoperatorcast.c
new file mode 100644 (file)
index 0000000..ef6df31
--- /dev/null
@@ -0,0 +1,100 @@
+#include "rvmoperatorcast.h"
+#include "rvmreg.h"
+
+
+void rvm_op_cast_static_static(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       *res = *arg1;
+}
+
+
+void rvm_op_cast_double_unsigned(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       rword r = (rword)RVM_REG_GETD(arg1);
+
+       RVM_REG_CLEAR(res);
+       RVM_REG_SETTYPE(res, RVM_DTYPE_UNSIGNED);
+       RVM_REG_SETL(res, r);
+}
+
+void rvm_op_cast_double_long(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       rlong r = (rlong)RVM_REG_GETD(arg1);
+
+       RVM_REG_CLEAR(res);
+       RVM_REG_SETTYPE(res, RVM_DTYPE_LONG);
+       RVM_REG_SETL(res, r);
+}
+
+
+void rvm_op_cast_long_unsigned(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       rword r = (rword)RVM_REG_GETL(arg1);
+
+       RVM_REG_CLEAR(res);
+       RVM_REG_SETTYPE(res, RVM_DTYPE_UNSIGNED);
+       RVM_REG_SETU(res, r);
+}
+
+
+void rvm_op_cast_long_double(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       rdouble r = (rdouble)RVM_REG_GETL(arg1);
+
+       RVM_REG_CLEAR(res);
+       RVM_REG_SETTYPE(res, RVM_DTYPE_DOUBLE);
+       RVM_REG_SETL(res, r);
+}
+
+
+void rvm_op_cast_unsigned_long(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       rlong r = (rlong)RVM_REG_GETU(arg1);
+
+       RVM_REG_CLEAR(res);
+       RVM_REG_SETTYPE(res, RVM_DTYPE_LONG);
+       RVM_REG_SETL(res, r);
+}
+
+
+void rvm_op_cast_unsigned_double(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       rdouble r = (rdouble)RVM_REG_GETU(arg1);
+
+       RVM_REG_CLEAR(res);
+       RVM_REG_SETTYPE(res, RVM_DTYPE_DOUBLE);
+       RVM_REG_SETD(res, r);
+}
+
+
+void rvm_op_cast_string_string(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       if (res == arg1)
+               RVM_ABORT(cpu, RVM_E_ILLEGALDST);
+       rvm_reg_setstring(res, r_string_copy(RVM_REG_GETP(arg1)));
+}
+
+
+void rvm_op_cast_refreg_string(rvmcpu_t *cpu, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       if (res == arg1)
+               RVM_ABORT(cpu, RVM_E_ILLEGALDST);
+       rvm_reg_refer(res, arg1);
+}
+
+
+void rvm_op_cast_init(rvm_opmap_t *opmap)
+{
+       rvm_opmap_add_binary_operator(opmap, RVM_OPID_CAST);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_static_static, RVM_DTYPE_DOUBLE, RVM_DTYPE_DOUBLE);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_static_static, RVM_DTYPE_LONG, RVM_DTYPE_LONG);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_long_double, RVM_DTYPE_LONG, RVM_DTYPE_DOUBLE);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_long_unsigned, RVM_DTYPE_LONG, RVM_DTYPE_UNSIGNED);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_double_long, RVM_DTYPE_DOUBLE, RVM_DTYPE_LONG);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_double_unsigned, RVM_DTYPE_DOUBLE, RVM_DTYPE_UNSIGNED);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_unsigned_long, RVM_DTYPE_UNSIGNED, RVM_DTYPE_LONG);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_unsigned_double, RVM_DTYPE_UNSIGNED, RVM_DTYPE_DOUBLE);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_refreg_string, RVM_DTYPE_REFREG, RVM_DTYPE_STRING);
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_CAST, rvm_op_cast_string_string, RVM_DTYPE_STRING, RVM_DTYPE_STRING);
+}
+
diff --git a/rvm/rvmoperatorcast.h b/rvm/rvmoperatorcast.h
new file mode 100644 (file)
index 0000000..cfe2ab8
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _RVMOPERATORCAST_H_
+#define _RVMOPERATORCAST_H_
+
+#include "rvmoperator.h"
+
+void rvm_op_cast_init(rvm_opmap_t *opmap);
+
+#endif
index 7f58097..65d759a 100644 (file)
@@ -209,7 +209,7 @@ void rvm_reg_setlong(rvmreg_t *r, rlong l)
 {
        RVM_REG_SETL(r, l);
        RVM_REG_SETTYPE(r, RVM_DTYPE_LONG);
-       RVM_REG_CLRFLAG(r, RVM_INFOBIT_ALL);
+       RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
 }
 
 
@@ -217,7 +217,7 @@ void rvm_reg_setdouble(rvmreg_t *r, rdouble d)
 {
        RVM_REG_SETD(r, d);
        RVM_REG_SETTYPE(r, RVM_DTYPE_DOUBLE);
-       RVM_REG_CLRFLAG(r, RVM_INFOBIT_ALL);
+       RVM_REG_CLRFLAG(r, RVM_INFOBIT_ROBJECT);
 
 }
 
@@ -241,3 +241,11 @@ void rvm_reg_convert_to_refreg(rvmreg_t *reg)
        RVM_REG_CLEAR(reg);
        rvm_reg_setrefreg(reg, refreg);
 }
+
+
+rvmreg_t *rvm_reg_unshadow(rvmreg_t *reg)
+{
+       if (rvm_reg_gettype(reg) != RVM_DTYPE_REFREG)
+               return reg;
+       return REFREG2REGPTR(RVM_REG_GETP(reg));
+}
index aae6782..c7dadc2 100644 (file)
@@ -38,6 +38,7 @@ void rvm_reg_setstring(rvmreg_t *r, rstring_t *ptr);
 void rvm_reg_setarray(rvmreg_t *r, rarray_t *ptr);
 void rvm_reg_setharray(rvmreg_t *r, rharray_t *ptr);
 void rvm_reg_convert_to_refreg(rvmreg_t *r);
+rvmreg_t *rvm_reg_unshadow(rvmreg_t *reg);
 
 struct rrefreg_s;
 void rvm_reg_setrefreg(rvmreg_t *r, struct rrefreg_s *ptr);
index 777ac5f..55c2dc8 100644 (file)
@@ -27,32 +27,32 @@ int main(int argc, char *argv[])
         * R0 = R0 + R1 + R2
         */
        l_add3 = &vmcode[off];
-       vmcode[off++] = rvm_asmu(RVM_PUSHM,DA, XX, XX, BIT(R7)|BIT(R8)|BIT(SP)|BIT(LR));
-       vmcode[off++] = rvm_asmi(RVM_PUSH, R2, XX, XX, 0);
+       vmcode[off++] = rvm_asm(RVM_PUSHM,DA, XX, XX, BIT(R7)|BIT(R8)|BIT(SP)|BIT(LR));
+       vmcode[off++] = rvm_asm(RVM_PUSH, R2, XX, XX, 0);
        vmcode[off++] = rvm_asmr(RVM_BL,   DA, XX, XX, &l_add2);
-       vmcode[off++] = rvm_asmi(RVM_POP,  R1, XX, XX, 0);
+       vmcode[off++] = rvm_asm(RVM_POP,  R1, XX, XX, 0);
        vmcode[off++] = rvm_asmr(RVM_BL,   DA, XX, XX, &l_add2);
-       vmcode[off++] = rvm_asmi(RVM_POPM, DA, XX, XX, BIT(R7)|BIT(R8)|BIT(SP)|BIT(LR));
-       vmcode[off++] = rvm_asmi(RVM_RET,  XX, XX, XX, 0);
+       vmcode[off++] = rvm_asm(RVM_POPM, DA, XX, XX, BIT(R7)|BIT(R8)|BIT(SP)|BIT(LR));
+       vmcode[off++] = rvm_asm(RVM_RET,  XX, XX, XX, 0);
        /*
         * We could directly restore the LR in the PC, so we will not need the RET instruction after POPM
         *
-        * vmcode[off++] = rvm_asmi(RVM_POPM, DA, XX, XX, BIT(R7)|BIT(R8)|BIT(SP)|BIT(PC));
+        * vmcode[off++] = rvm_asm(RVM_POPM, DA, XX, XX, BIT(R7)|BIT(R8)|BIT(SP)|BIT(PC));
         *
         */
 
 
        l_main = &vmcode[off];
-       vmcode[off++] = rvm_asmi(RVM_MOV, R0, DA, XX, 1);
-       vmcode[off++] = rvm_asmi(RVM_MOV, R1, DA, XX, 2);
+       vmcode[off++] = rvm_asm(RVM_MOV, R0, DA, XX, 1);
+       vmcode[off++] = rvm_asm(RVM_MOV, R1, DA, XX, 2);
        vmcode[off++] = rvm_asmr(RVM_BL,  DA, XX, XX, &l_add2);
        VMTEST_REG(vmcode, off, 0, 3, "BL/RET");
-       vmcode[off++] = rvm_asmi(RVM_MOV, R0, DA, XX, 1);
-       vmcode[off++] = rvm_asmi(RVM_MOV, R1, DA, XX, 2);
-       vmcode[off++] = rvm_asmi(RVM_MOV, R2, DA, XX, 4);
+       vmcode[off++] = rvm_asm(RVM_MOV, R0, DA, XX, 1);
+       vmcode[off++] = rvm_asm(RVM_MOV, R1, DA, XX, 2);
+       vmcode[off++] = rvm_asm(RVM_MOV, R2, DA, XX, 4);
        vmcode[off++] = rvm_asmr(RVM_BL,  DA, XX, XX, &l_add3);
        VMTEST_REG(vmcode, off, 0, 7, "BL/RET");
-       vmcode[off++] = rvm_asmi(RVM_EXT, R0, XX, XX, 0);
+       vmcode[off++] = rvm_asm(RVM_EXT, R0, XX, XX, 0);
 
 
        rvm_relocate(vmcode, off);
diff --git a/tests/asm-cast.c b/tests/asm-cast.c
new file mode 100644 (file)
index 0000000..745416f
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include "rrefreg.h"
+#include "rvmcpu.h"
+#include "common.h"
+
+static void test_swi_print_r(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rvmreg_t *r = RVM_CPUREG_PTR(cpu, ins->op2);
+
+       if (rvm_reg_gettype(r) == RVM_DTYPE_REFREG)
+               r = REFREG2REGPTR(RVM_REG_GETP(r));
+       if (rvm_reg_gettype(r) == RVM_DTYPE_WORD)
+               fprintf(stdout, "R%d = %ld\n", ins->op2, RVM_REG_GETL(r));
+       else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
+               fprintf(stdout, "R%d = %ld\n", ins->op2, RVM_REG_GETL(r));
+       else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
+               fprintf(stdout, "R%d = %5.2f\n", ins->op2, RVM_REG_GETD(r));
+       else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
+               fprintf(stdout, "R%d = %s\n", ins->op2, ((rstring_t*) RVM_REG_GETP(r))->s.str);
+       else
+               fprintf(stdout, "R%d = Unknown type\n", ins->op2);
+}
+
+
+static rvm_switable_t switable[] = {
+               {"print", test_swi_print_r},
+               {NULL, NULL},
+};
+
+       
+int main(int argc, char *argv[])
+{
+       ruint ret = 0;
+       ruint off = 0;
+       rvmreg_t d1 = rvm_reg_create_double(1.0);
+       rvmreg_t d2 = rvm_reg_create_double(-1.0);
+       rvm_asmins_t vmcode[256];
+       rvmcpu_t *vm = rvm_cpu_create();
+       
+       rvmcpu_switable_add(vm, common_calltable);
+       rvmcpu_switable_add(vm, switable);
+       vmcode[off++] = rvm_asmp(RVM_LDRR, R0, DA, XX, &d1);
+       vmcode[off++] = rvm_asm(ERVM_TYPE, R1, R0, XX, 0);
+       vmcode[off++] = rvm_asm(RVM_SWI, DA, R1, XX, rvm_cpu_getswi(vm, "print"));
+       vmcode[off++] = rvm_asm(ERVM_CAST, R0, R0, DA, RVM_DTYPE_UNSIGNED);
+       vmcode[off++] = rvm_asm(RVM_MOV, R1, DA, XX, 2);
+       vmcode[off++] = rvm_asm(RVM_ADD, R0, R1, R0, 0);
+       vmcode[off++] = rvm_asm(RVM_SWI, DA, R0, XX, rvm_cpu_getswi(vm, "print"));
+       VMTEST_REG(vmcode, off, 0, 3, "CAST");
+       VMTEST_STATUS(vmcode, off, 0, "CAST STATUS");
+
+       vmcode[off++] = rvm_asmp(RVM_LDRR, R0, DA, XX, &d2);
+       vmcode[off++] = rvm_asm(ERVM_TYPE, R1, R0, XX, 0);
+       vmcode[off++] = rvm_asm(RVM_SWI, DA, R1, XX, rvm_cpu_getswi(vm, "print"));
+       vmcode[off++] = rvm_asm(ERVM_CAST, R0, R0, DA, RVM_DTYPE_LONG);
+       vmcode[off++] = rvm_asm(RVM_SWI, DA, R0, XX, rvm_cpu_getswi(vm, "print"));
+       vmcode[off++] = rvm_asm(RVM_MOV, R1, DA, XX, 2);
+       vmcode[off++] = rvm_asm(RVM_ADD, R0, R1, R0, 0);
+       vmcode[off++] = rvm_asm(RVM_SWI, DA, R0, XX, rvm_cpu_getswi(vm, "print"));
+       VMTEST_REG(vmcode, off, 0, 1, "CAST");
+       VMTEST_STATUS(vmcode, off, 0, "CAST STATUS");
+
+
+       vmcode[off++] = rvm_asm(RVM_EXT, R0, XX, XX, 0);
+#ifdef EXECDEBUG
+       ret = rvm_cpu_exec_debug(vm, vmcode, 0);
+#else
+       ret = rvm_cpu_exec(vm, vmcode, 0);
+#endif
+       rvm_cpu_destroy(vm);
+       return 0;
+}
index 38d7051..ab3386d 100644 (file)
@@ -21,7 +21,9 @@ TESTS = \
        $(OUTDIR)/scope-test \
        $(OUTDIR)/rhash-test \
        $(OUTDIR)/rvm-test \
+       $(OUTDIR)/loop-test \
        $(OUTDIR)/memalloc-test \
+       $(OUTDIR)/asm-cast \
        $(OUTDIR)/asm-add \
        $(OUTDIR)/asm-adds \
        $(OUTDIR)/asm-b \
diff --git a/tests/loop-test.c b/tests/loop-test.c
new file mode 100644 (file)
index 0000000..d14fb79
--- /dev/null
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include "common.h"
+
+
+       
+int main(int argc, char *argv[])
+{
+       ruint ret = 0;
+       ruint off = 0;
+       rvm_asmins_t vmcode[256];
+       rvmcpu_t *vm = rvm_cpu_create();
+       
+       rvmcpu_switable_add(vm, common_calltable);
+
+       vmcode[off++] = rvm_asm(RVM_MOV, R4, DA, XX, 0);
+       vmcode[off++] = rvm_asm(RVM_MOV, R5, DA, XX, 1000*1000 * 200);
+       vmcode[off++] = rvm_asm(RVM_ADD, R4, R4, DA, 1);
+       vmcode[off++] = rvm_asm(RVM_MOV, R1, DA, XX, 1);
+       vmcode[off++] = rvm_asm(RVM_MOV, R2, DA, XX, 2);
+       vmcode[off++] = rvm_asm(RVM_ADD, R0, R1, R2, 0);
+       vmcode[off++] = rvm_asm(RVM_CMP, R4, R5, XX, 0);
+       vmcode[off++] = rvm_asml(RVM_BLES, DA, XX, XX, -5);
+       vmcode[off++] = rvm_asm(RVM_EXT, R0, XX, XX, 0);
+
+
+       rvm_relocate(vmcode, off);
+       ret = rvm_cpu_exec(vm, vmcode, 0);
+       fprintf(stdout, "R0 = %ld (%ld operations)\n", (unsigned long) RVM_CPUREG_GETU(vm, R0), (unsigned long)RVM_CPUREG_GETU(vm, R5));
+       rvm_cpu_destroy(vm);
+       return 0;
+}
index b528501..181a34b 100644 (file)
@@ -101,8 +101,8 @@ int main(int argc, char *argv[])
        rvm_opmap_set_binary_handler(opmap, RVM_OPID_DIV, rvm_op_div_long_long, RVM_DTYPE_LONG, RVM_DTYPE_LONG);
 
        ntable = rvmcpu_switable_add(cpu, switable);
-       code[off++] = rvm_asmd(RVM_MOV, R1, DA, XX, 1);
-       code[off++] = rvm_asml(RVM_MOV, R2, DA, XX, 3.2);
+       code[off++] = rvm_asm(RVM_MOV, R1, DA, XX, 1);
+       code[off++] = rvm_asm(RVM_MOV, R2, DA, XX, 3);
 //     code[off++] = rvm_asm(RVM_SWI, DA, XX, XX, RVM_SWI_ID(ntable, 1));                      // mul
        code[off++] = rvm_asm(RVM_MOV, R0, DA, XX, rvm_cpu_getswi(cpu, "add"));         // add
        code[off++] = rvm_asm(RVM_SWI, R0, R1, R2, 0);