Author: leo
Date: Tue Apr 12 06:40:41 2005
New Revision: 7811

Modified:
   trunk/docs/nanoparrot.c
   trunk/vtable.tbl
Log:
more run loops for nanoparrot; move math vtables together

Modified: trunk/docs/nanoparrot.c
==============================================================================
--- trunk/docs/nanoparrot.c     (original)
+++ trunk/docs/nanoparrot.c     Tue Apr 12 06:40:41 2005
@@ -1,23 +1,27 @@
 /*
  * nanoparrot.c
  *
- * - demonstrates how the interpreter basically is working
+ * - demonstrates how the interpreter interprets bytecode
  *   its vastly simplified but the very basics are the same
- *   and it totally lacks any error checking
- *
- * - proof of concept of the new indirect register addressing scheme
  *
  * - compile with:
- *   -DMOPS  ... run mops main loop
- *   -DINDIRECT ... use indirect register pointer
- *   -TRACE ... turn on opcode tracing
+ *   -DTRACE ...    turn on opcode tracing (FUNC_CORE, SWITCH_CORE only)
+ *   -DFUNC_CORE    run function base opcodes
+ *   -DF            same
+ *   -DSWITCH_CORE  run switched opcode core
+ *   -DS            same
+ *                  else run CGOTO core
+ *
+ * The CGOTO run core works only for compilers like gcc that allow
+ * labels as values.
  *
  * e.g.:
- * cc -o nanoparrot -Wall nanoparrot.c -O3  -DMOPS && time ./nanoparrot
+ * cc -o nanoparrot -Wall nanoparrot.c -O3 && time ./nanoparrot mops
  */
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 typedef int INTVAL;
 typedef int opcode_t;
@@ -27,8 +31,6 @@
 
 #define NUM_REGISTERS 32
 
-#ifdef INDIRECT
-
 struct Reg {
     INTVAL int_reg;
     FLOATVAL num_reg;
@@ -38,26 +40,14 @@
 
 #define REG_INT(x) interpreter->bp[x].int_reg
 
+#if defined(PREDEREF_CORE)
+#  define IREG(x)   (_reg_base + pc[x])
+#  define ICONST(x) *(INTVAL*)pc[x]
+#  define SCONST(x) *(STRING**)pc[x]
 #else
-
-struct IReg {
-    INTVAL registers[NUM_REGISTERS];
-};
-
-struct NReg {
-    FLOATVAL registers[NUM_REGISTERS];
-};
-
-struct SReg {
-    STRING *registers[NUM_REGISTERS];
-};
-
-struct PReg {
-    PMC *registers[NUM_REGISTERS];
-};
-
-#define REG_INT(x) interpreter->int_reg.registers[x]
-
+#  define IREG(x)   REG_INT(pc[x])
+#  define ICONST(x) pc[x]
+#  define SCONST(x) interpreter->code->const_table[pc[x]]
 #endif
 
 struct pf {
@@ -65,146 +55,236 @@
     char **const_table;
 };
 
-typedef Interp {
-#ifdef INDIRECT
+typedef struct Interp {
     struct Reg *bp;
-#else
-    struct IReg int_reg;
-    struct NReg num_reg;
-    struct SReg string_reg;
-    struct PReg pmc_reg;
-#endif
     struct pf *code;
-    opcode_t *(**op_func)(opcode_t *, Interp*);
+    opcode_t *(**op_func)(opcode_t *, struct Interp*);
     const char **op_info;
     int flags;
 } Interp;
 
-static opcode_t *
-end(opcode_t *pc, Interp *interpreter) {
-    return 0;
-}
+/*
+ * list of all opcodes
+ */
 
-static opcode_t *
-set_i_ic(opcode_t *pc, Interp *interpreter) {
-    REG_INT(pc[1]) = pc[2];
-    return pc + 3;
-}
+#define OPCODES OP(end),      OP(print_sc), OP(print_i),  \
+                OP(set_i_ic), OP(if_i_ic),  OP(sub_i_i_i), \
+                OP(MAX)
 
-static opcode_t *
-print_i(opcode_t *pc, Interp *interpreter) {
-    printf("%d", REG_INT(pc[1]));
-    return pc + 2;
-}
+/*
+ * some macros to get 3 different kinds of run loops
+ * you might skip this uglyness and continue
+ * at dispatch loop ~90 lines below
+ *
+ * or for the curious: look at the preprocessor output
+ */
+
+#define OP(x) OP_ ## x
+typedef enum { OPCODES } opcodes;
+#undef OP
 
-static opcode_t *
-add_bp_ic(opcode_t *pc, Interp *interpreter) {
-#ifdef INDIRECT
-    interpreter->bp += pc[1];
+#ifdef F
+#  define FUNC_CORE
+#endif
+#ifdef S
+#  define SWITCH_CORE
 #endif
-    return pc + 2;
-}
 
-static opcode_t *
-if_i_ic(opcode_t *pc, Interp *interpreter) {
-    if (REG_INT(pc[1]))
-       return pc + pc[2];
-    return pc + 3;
+#if defined(FUNC_CORE)
+#  ifdef TRACE
+#    define ENDRUN \
+static void \
+run(Interp *interpreter, opcode_t *pc) \
+{ \
+    while (pc) { \
+       printf("PC %2d %s\n", pc - interpreter->code->byte_code, \
+               interpreter->op_info[*pc]); \
+       pc = interpreter->op_func[*pc](pc, interpreter); \
+    } \
 }
-
-static opcode_t *
-sub_i_i_i(opcode_t *pc, Interp *interpreter) {
-    REG_INT(pc[1]) = REG_INT(pc[2]) - REG_INT(pc[3]);
-    return pc + 4;
+#  else
+#    define ENDRUN \
+static void \
+run(Interp *interpreter, opcode_t *pc) \
+{ \
+    while (pc) { \
+       pc = interpreter->op_func[*pc](pc, interpreter); \
+    } \
 }
+#  endif
 
-static opcode_t *
-print_sc(opcode_t *pc, Interp *interpreter) {
-    printf("%s", interpreter->code->const_table[pc[1]]);
-    return pc + 2;
-}
+#  define DISPATCH
+#  define ENDDISPATCH
+#  define CASE(function) \
+static opcode_t * \
+function (opcode_t *pc, Interp *interpreter) {
+
+#  define NEXT return pc; }
+#  define DONE            return 0; }
+
+#else   /* !FUNC_CORE */
+
+#  define ENDRUN  }
+
+#if defined(SWITCH_CORE)
 
 static void
-init(Interp *interpreter, opcode_t *prog)
+run(Interp *interpreter, opcode_t *pc)
+{
+#    ifdef TRACE
+#       define DISPATCH  \
+    for (;;) { \
+       printf("PC %2d %s\n", pc - interpreter->code->byte_code, \
+               interpreter->op_info[*pc]); \
+        switch(*pc) {
+#    else
+#       define DISPATCH \
+    for (;;) { \
+        switch(*pc) {
+#    endif
+
+#    define CASE(x)         case OP_ ## x:
+#    define NEXT            continue;
+#    define DONE            return;
+#    define ENDDISPATCH     default : printf("illegal instruction"); \
+                                 exit(1);                           \
+                       }}
+# else  /* CGOTO */
+
+static void
+run(Interp *interpreter, opcode_t *pc)
 {
-#ifdef INDIRECT
-    interpreter->bp = calloc(32, sizeof(struct Reg));
+#    define OP(x)          &&lOP_##x
+    static  void *labels[] = { OPCODES };
+#    undef OP
+#    define CASE(x)         lOP_##x:
+#    define NEXT            goto *labels[*pc];
+#    define DISPATCH        NEXT
+#    define ENDDISPATCH
+#    define DONE            return;
+
+#  endif        /* SWITCH or CGOTO */
+#endif  /* !FUNC_CORE */
+
+/*
+ * dispatch loop / opcode (function) bodies i.e. the .ops files
+ */
+
+    DISPATCH
+        CASE(end)
+            DONE
+        CASE(print_sc)
+            printf("%s", SCONST(1));
+            pc += 2;
+            NEXT
+        CASE(print_i)
+            printf("%d", IREG(1));
+            pc += 2;
+            NEXT
+        CASE(set_i_ic)
+            IREG(1) = ICONST(2);
+            pc += 3;
+            NEXT
+        CASE(if_i_ic)
+            if (IREG(1))
+                pc += ICONST(2);
+            else
+                pc += 3;
+            NEXT
+        CASE(sub_i_i_i)
+            IREG(1) = IREG(2) - IREG(3);
+            pc += 4;
+            NEXT
+        CASE(MAX)
+            printf("illegal opcode\n");
+            exit(1);
+            NEXT
+    ENDDISPATCH
+ENDRUN
+
+#ifdef FUNC_CORE
+#  define DEF_OP(op) \
+    interpreter->op_func[OP_ ## op] = op; \
+    interpreter->op_info[OP_ ## op] = #op
+#  else
+#  define DEF_OP(op) \
+    interpreter->op_info[OP_ ## op] = #op
 #endif
-#define N_OPS 7
-#define N_CONSTS 2
-    interpreter->op_func = malloc(N_OPS * sizeof(void*));
-    interpreter->op_func[0] = end;
-    interpreter->op_func[1] = set_i_ic;
-    interpreter->op_func[2] = print_i;
-    interpreter->op_func[3] = add_bp_ic;
-    interpreter->op_func[4] = if_i_ic;
-    interpreter->op_func[5] = sub_i_i_i;
-    interpreter->op_func[6] = print_sc;
-    interpreter->op_info = malloc(N_OPS * sizeof(char*));
-    interpreter->op_info[0] = "end";
-    interpreter->op_info[1] = "set_i_ic";
-    interpreter->op_info[2] = "print_i";
-    interpreter->op_info[3] = "add_bp_ic";
-    interpreter->op_info[4] = "if_i_ic";
-    interpreter->op_info[5] = "sub_i_i_i";
-    interpreter->op_info[6] = "print_sc";
+
+static void
+init(Interp *interpreter, opcode_t *prog)
+{
+    /*
+     * create 1 register frame
+     */
+    interpreter->bp = calloc(NUM_REGISTERS, sizeof(struct Reg));
+    /*
+     * and some space for opcodes
+     */
+    interpreter->op_func = malloc(OP_MAX * sizeof(void*));
+    interpreter->op_info = malloc(OP_MAX * sizeof(char*));
+    /*
+     * define opcode function and opcode info
+     */
+    DEF_OP(end);
+    DEF_OP(print_sc);
+    DEF_OP(print_i);
+    DEF_OP(set_i_ic);
+    DEF_OP(if_i_ic);
+    DEF_OP(sub_i_i_i);
+
+    /*
+     * the "packfile"
+     */
     interpreter->code = malloc(sizeof(struct pf));
     interpreter->code->byte_code = prog;
+
+    /*
+     * create a simplified constant table
+     */
+#define N_CONSTS 4
     interpreter->code->const_table = malloc(N_CONSTS * sizeof(char*));
     interpreter->code->const_table[0] = "\n";
     interpreter->code->const_table[1] = "done\n";
-}
-
-static void
-run(Interp *interpreter)
-{
-    opcode_t *pc = interpreter->code->byte_code;
-
-    while (pc) {
-#ifdef TRACE
-       printf("PC %2d %s\n", pc - interpreter->code->byte_code,
-               interpreter->op_info[*pc]);
-#endif
-       pc = interpreter->op_func[*pc](pc, interpreter);
-    }
+    interpreter->code->const_table[2] = "error\n";
+    interpreter->code->const_table[3] = "usage: ./nanoparrot mops\n";
 }
 
 int
 main(int argc, char *argv[]) {
-#ifdef MOPS
+    opcode_t *prog;
+
     /*
-     * run the mops main loop
+     * the mops main loop
      */
-    opcode_t prog[] =
-       { 1, 4, 100000000,      /* set I4, n */
-         2, 4,         /* print I4 */
-         6, 0,         /* print "\n" */
-          1, 5, 1,     /* set I5, 1 */
-         5, 4, 4, 5,   /* L1: sub I4, I4, I5 */
-         4, 4, -4,     /* if I4, L1 */
-         6, 1,         /* print "done\n" */
-         0             /* end */
+    opcode_t mops[] =
+       { OP_set_i_ic, 4, 100000000,    /* set I4, n */
+         OP_print_i, 4,        /* print I4 */
+         OP_print_sc, 0,       /* print "\n" */
+          OP_set_i_ic, 5, 1,   /* set I5, 1 */
+         OP_sub_i_i_i, 4, 4, 5,        /* L1: sub I4, I4, I5 */
+         OP_if_i_ic, 4, -4,    /* if I4, L1 */
+         OP_print_sc, 1,       /* print "done\n" */
+         OP_end                /* end */
        };
-#else
-    /*
-     * show moving the register base pointer
-     */
-    opcode_t prog[] =
-       { 1, 4, 4,      /* set I4, 4 */
-          1, 5, 5,     /* set I5, 5 */
-         2, 4,         /* print I4 */
-         6, 0,         /* print "\n" */
-         2, 5,         /* print I5 */
-         6, 0,         /* print "\n" */
-         3, 1,         /* add_pb 1 */
-         2, 4,         /* print I4 */
-         6, 0,         /* print "\n" */
-         0             /* end */
+    opcode_t usage[] =
+       {
+          OP_set_i_ic, 0, 2,   /* set I0, 2 */
+         OP_if_i_ic, 0, 6,     /* if I0, L1 */
+         OP_print_sc, 2,       /* print "error\n" */
+         OP_end,               /* end */
+         OP_print_sc, 3,       /* L1: print "usage...\n" */
+         OP_end                /* end */
        };
-#endif
     Interp *interpreter = malloc(sizeof(Interp));
+
+    prog = usage;
+    if (argc > 1) {
+        if (!strcmp(argv[1], "mops"))
+            prog = mops;
+    }
     init(interpreter, prog);
-    run(interpreter);
+    run(interpreter, prog);
     return 0;
 }
 

Modified: trunk/vtable.tbl
==============================================================================
--- trunk/vtable.tbl    (original)
+++ trunk/vtable.tbl    Tue Apr 12 06:40:41 2005
@@ -176,6 +176,9 @@
 void pow_int(INTVAL value, PMC* dest) MMD_POW_INT
 void pow_float(FLOATVAL value, PMC* dest) MMD_POW_FLOAT
 
+void increment()
+void decrement()
+void absolute(PMC* dest)
 void neg(PMC* dest)
 
 [BITWISE]
@@ -233,11 +236,6 @@
 void repeat(PMC* value, PMC* dest)           MMD_REPEAT
 void repeat_int(INTVAL value, PMC* dest)     MMD_REPEAT_INT
 
-[MATH]
-void increment()
-void decrement()
-void absolute(PMC* dest)
-
 [EXISTS]
 INTVAL exists_keyed(PMC* key)
 INTVAL exists_keyed_int(INTVAL key)

Reply via email to