A simple virtual machine written in C. (Assembler available here.)
Just like Intel-based computers, ToyVM is little-endian.
ToyVM features four 32-bit registers: REG1, REG2, REG3, REG4
. Each of them is represented as a single byte with values 0x0
, 0x1
, 0x2
, 0x3
, respectively.
ToyVM has only one data type: 32-bit signed integers.
The first byte is always an opcode specifying the instruction. It is immediately followed by arguments. If the instruction has both registers and immediate data as arguments, registers are specified before the immediate data.
0x01
:ADD REGi REGj
- adds the integer inREGi
toREGj
.0x02
:NEG REGi
- negates the integer stored inREGi
.0x03
:MUL REGi REGj
- copies the product ofREGi
andREGj
toREGj
.0x04
:DIV REGi REGj
- copies the ratio ofREGi
andREGj
toREGj
0x05
:MOD REGi REGj
- dividesREGi
byREGj
and stores the remainder inREGj
.
0x10
:CMP REGi REGj
- compares the value inREGi
to the value inREGj
.0x11
:JA ADDRESS
- jumps to addressADDRESS
only if thevm.cpu.status
has flagCOMPARISON_ABOVE
on.0x12
:JE ADDRESS
- jumps to addressADDRESS
only if thevm.cpu.status
has flagCOMPARISON_EQUAL
on.0x13
:JB ADDRESS
- jumps to addressADDRESS
only if thevm.cpu.status
has flagCOMPARISON_BELOW
on.0x14
:JMP ADDRESS
- jumps unconditionally to addressADDRESS
.
The three comparison flags above are mutually exclusive: at most only one of them is set on.
0x20
:CALL ADDRESS
- pushes the return address (i.e.,ADDRESS + 5
) into the stack and jumps to the instruction at the specified address.0x21
:RET
- pops the return address and sets it to the program counter, hence returning from a subroutine.
0x30
:LOAD REGi ADDRESS
- stores the value at addressADDRESS
to the registerREGi
.0x31
:STORE REGi ADDRESS
- stores the value inREGi
to the memory at addressADDRESS
.0x32
:CONST REGi DATA
- stores the valueDATA
in the registerREGi
.0x33
:RLOAD REGi REGj
- loads the word at the address in the registerREGi
to the registerREGj
.0x34
:RSTORE REGi REGj
- stores the contents of registerREGi
to the address atREGj
.
0x40
:HALT
- halts the virtual machine.0x41
:INT INTERRUPT_NUMBER
- issues an interrupt with numberINTERRUPT_NUMBER
.0x42
:NOP
- a no-op instruction, does nothing else but increase the program counter towards the next instruction.
0x50
:PUSH REGi
- pushes the contents of registerREGi
to the stack.0x51
:PUSH_ALL
- pushes all four registers to the stack.0x52
:POP REGi
- pops the stack into registerREGi
.0x53
:POP_ALL
- pops all values of registers from the stack back to the registers.0x54
:LSP REGi
- loads the value of the stack pointer to the registerREGi
.