Skip to content
Jason Hansel edited this page Jan 20, 2017 · 2 revisions

This wiki contains documentation for KineticVM's architecture and assembly language. The codebase itself will be documented using rustdoc (see the README for further details).

Memory

KineticVM has a rather unusual memory model with the following features:

  • KineticVM's memory is divided into fixed-sized arrays called "objects." These objects can be arbitrarily reordered by the virtual machine during garbage collection.
  • Two objects are allocated during VM startup: one holds the register file, and one holds the program's code. The program can use system registers to dynamically allocate new objects.
  • Every value in KineticVM is either a 16-bit signed integer or a pointer to an object. These two types are distinguished to allow for precise (non-conservative) garbage collection. Types are checked dynamically, at runtime.

Instruction Format

Since KineticVM is a transport-triggered architecture, the only instruction available is "move." Thus any KineticVM assembly file consists of a series of moves; instructions can also be given labels for use in control flow. The move instruction has two operands (a source and a destination), and is written as SOURCE -> DESTINATION. These operands can be of one of four types, which are documented below.

Operand Types

Immediate Constants

Constants such as 123 and -5 can be used as the source for a move instruction. So, for instance, 123 -> %OUT moves the number 123 into the system register OUT, thus printing it to the screen.

User-Defined Registers

User-defined registers such as count or return_addr can be used as the source or destination for a move instruction. The KineticVM assembler will allocate a VM register for every unique identifier used in the program; thus the virtual machine (much like LLVM) has no limit on the number of registers. So, for instance, consider the code:

5 -> my_var
my_var -> %OUT

The KineticVM assembler will create a register for the identifier my_var. When running the program, the VM will store 5 in this register, and then print the register's contents to the screen. User-defined registers can also hold pointers to objects in memory; such objects are allocated and modified using system registers.

System Registers

System registers (such as %OUT) can be used as the source or destination of a move instruction. All operations (including simple ones like addition) are accomplished by reading and writing these system registers. Their names are prefixed with a % to distinguish them from ordinary user-defined registers.

Label Addresses

The address corresponding to an instruction label can be used as the source of a move instruction. Consider the following code:

	:line_two -> test
line_two:
	test -> %OUT

The first line moves the address of the label line_two (which, in this case, is 1) into a user-defined register, and then prints that value. If we had instead written:

	0 -> test
	:line_two -> test
line_two:
	test -> %OUT

Then the address of line_two would be 2, so the value 2 would be printed. Control flow is generally achieved by moving label addresses into the system register %PC, which holds the address of the next instruction to execute. More simply: the instruction :line_two -> %PC jumps to the label line_two.

This instruction has two operands: a source and a destination. The source can be an immediate constant (such as $1), a user-defined register (such as count), a system register (such as %SUM), or the address of an instruction label (such as :loop_start).

Clone this wiki locally