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 inREGitoREGj.0x02:NEG REGi- negates the integer stored inREGi.0x03:MUL REGi REGj- copies the product ofREGiandREGjtoREGj.0x04:DIV REGi REGj- copies the ratio ofREGiandREGjtoREGj0x05:MOD REGi REGj- dividesREGibyREGjand stores the remainder inREGj.
0x10:CMP REGi REGj- compares the value inREGito the value inREGj.0x11:JA ADDRESS- jumps to addressADDRESSonly if thevm.cpu.statushas flagCOMPARISON_ABOVEon.0x12:JE ADDRESS- jumps to addressADDRESSonly if thevm.cpu.statushas flagCOMPARISON_EQUALon.0x13:JB ADDRESS- jumps to addressADDRESSonly if thevm.cpu.statushas flagCOMPARISON_BELOWon.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 addressADDRESSto the registerREGi.0x31:STORE REGi ADDRESS- stores the value inREGito the memory at addressADDRESS.0x32:CONST REGi DATA- stores the valueDATAin the registerREGi.0x33:RLOAD REGi REGj- loads the word at the address in the registerREGito the registerREGj.0x34:RSTORE REGi REGj- stores the contents of registerREGito 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 registerREGito 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.