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.
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.
* 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
* 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)
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])
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.