/SimpleVM

a simple virtual machine which simulates a register machine

Primary LanguageC

Simple VM

Simple VM is just what it claims to be, a simple virtual machine in pure ANSI C designed to emulate an infinite memory register or Turing machine. SimpleVM provides a RISC architecture with builtins such as pointers, integer arithmetic, and conditional branching.

Current State

At present, I would say that SimpleVM is in the 1.7 version range as all the basic functionality required for Turing completeness (integer math, branching) are in place and work as well as I could hope. Some limited parallelism is now featured as well, with the OPCODE language featuring fully functional FORK and JOIN operations. 1.7 added a simple binary file format for storing and transferring VM code somewhat like Pascal’s P-code of Java’s .class files.

ToDo List

* Support for user-defined named verbs
* Private memory space for such functions seperate from the program core
* Add a call stack for user-defined functions
* Storage of program instructions in the memory core with program data
* Add a framebuffer or other pixel display which can be manipulated by programs

ToDone List

* Support for a PASCAL P-CODE like compiled binary file            (v 1.7)
* Threading through FORK and JOIN words, exit on 0 running threads (v 1.6)
* Pointers                                                         (v 1.5) 
* Integer comparisons                                              (v 1.5)
* Conditional branching                                            (v 1.2)
* Integer math                                                     (v 1.2)
* Case-insensitivity                                               (v 1.0)
* Dynamic memory resizing                                          (v 1.0)
* RISC architecture                                                (v 1.0)

Instruction Set

REGS[ ] is the name I use for the machine’s RAM registers. C is the name I use for the instruction number cursor.

  OPCODE     | HASH      | ARGUMENTS | OPERATION
-------------+-----------+-----------+------------------------------------------
    ADD      | 64641     | N1 N2 N3  | REGS[N3] := REGS[N1] + REGS[N2]
    AND      | 64951     | N1 N2 N3  | REGS[N3] := REGS[N1] && REGS[N2]
    DECR     | 2094256   | N1        | REGS[N1] := REGS[N1] - 1
    DIV      | 67697     | N1 N2 N3  | REGS[N3] := REGS[N1] / REGS[N2]
    DSP      | 68001     |           | dumps the VM's RAM to STDOUT
    DUMP     | 2109940   |           | dumps the VM's program code to STDOUT
    EQUAL    | 66219796  | N1 N2 N3  | REGS[N3] := REGS[N1] == REGS[N2] 
    FORK     | 2163906   | N1 N2     | creates a new cursor at line N1, writes an ID to N2
    GETC     | 2184141   | N1        | reads a character code into register N1
    GETI     | 2184147   | N1        | reads an integer into register N1
    GOTO     | 2193763   | N1        | C := C + N1
    GOTOL    | 68006729  | N1        | C := N1
    GOTOR    | 68006735  | N1        | C := REGS[N1]
    GT       | 2285      | N1 N2 N3  | REGS[N3] := REGS[N1] > REGS[N2]
    HALT     | 2209857   | N1        | kills entire VM with exit code
    IF       | 2333      | N1        | IF(REGS[N1]){C := C+1} ELSE {C := C+2}
    INCR     | 2251860   | N1        | REGS[N1] := REGS[N1] + 1
    JOIN     | 2282794   | N1        | kills process with an ID at N1, or the current one if REGS[N1] <= 0
    LET      | 75259     | N1 N2     | REGS[N1] := N2
    LSFT     | 2346133   | N1        | REGS[N1] := REGS[N1]<<1
    LT       | 2440      | N1 N2 N3  | REGS[N3] := REGS[N1] < REGS[N2]
    MCPY     | 2360863   | N1 N2     | REGS[N2] := REGS[N1]
    MOD      | 76514     | N1 N2 N3  | REGS[N3] := REGS[N1] % REGS[N2]
    MUL      | 76708     | N1 N2 N3  | REGS[N3] := REGS[N1] * REGS[N2]
    NOOP     | 2402146   |           | no-op
    NOT      | 77491     | N1 N2     | REGS[N2] := !REGS[N1]
    OR       | 2531      | N1 N2 N3  | REGS[N3] := REGS[N1] || REGS[N2]
    PUTC     | 2467636   | N1        | printf("%c", regs[N1]);
    PUTI     | 2467642   | N1        | printf("%i\n", regs[N1]);
    RGET     | 2513316   | N1 N2     | regs[N2] = regs[regs[N1]] (pointer deref)
    RSET     | 2524848   | N1 N2     | regs[regs[N1]] = regs[N2] (pointer write)
    RSFT     | 2524879   | N1        | REGS[N1] := REGS[N1]>>1
    SUB      | 82464     | N1 N2 N3  | REGS[N3] := REGS[N1] - REGS[N2]
    SWAP     | 2558355   | N1 N2     | swaps the values of REGS[N1] & REGS[N2]
    XOR      | 87099     | N1 N2 N3  | REGS[N3] :=(REGS[N1] & !REGS[N2]) || (!REGS[N1] & REGS[N2])

Disclaimer

This program was hacked together by a college freshman who hadn’t touched C before in his life. If you use this code for anything important, you are nuts to put it kindly. That said, all code in this project is copyright 2011 Reid McKenzie <rmckenzie92 AT gmail.com>. This code and all other code in the project may be used or re-used for any purpose at all, so long as I am made aware of my contribution.