Skip to content
This repository has been archived by the owner on Jun 16, 2020. It is now read-only.
Temir edited this page Aug 30, 2016 · 2 revisions

ZHVM - simple virtual machine

Overview

ZHVM - simple register based virtual machine can be used in general applications. Currently uses assembler-like code with following format:

($d =)* opcode [ ($U)* , ($V)* (+|-)* {NUMBER}* ] # * Asterisks marks parts which can be ommited

# Examples
$a = add[,0x100]   # Set RA register to 0x100
$0 = mul[$a, $b]   # Set R0 register to sum of RA and RB
cll[,10]           # Call 10-th c-function
$c = add[$c, 1]    # Increment RC
$c = add[$c, $b-1] # RC = RC + (RB-1)

ZHVM have only one command encoding scheme consisting of 4 parts:

  1. Operation code [6-bit]
  2. Destination register [4-bit]
  3. Source 0 register [4-bit]
  4. Source 1 register [4-bit]
  5. Signed immediate constant [14-bit]

So each command can encode one of 64 operations on full set of registers with constant in range [-8192,+8192].


Registers

There are several general use registers: RZ, RA, RB, RC, R0-R8, RS, RD, RP. RZ register is always stores 0 (zero). RP register is used to select next VM command. Other registers can be used interchangeably. But there are some recommendation for typical usage:

  • RA - register accumulator
  • RB - base register
  • RC - counter register
  • R0-R8 - arguments registers
  • RD - data register
  • RS - stack pointer

Operations

VM uses 6-bit operation code length, which can be used to code 64 commands.

Current VM version has several reserved for future use codes. If any of reserved codes are found, VM halts with error.

Valid operation codes:

  • hlt - halt vm.
  • add - add two numbers. [$d = $s0 + ($s1 + imm)]
  • sub - substract two numbers. [$d = $s0 - ($s1 + imm)]
  • mul - two numbers multiplications. [$d = $s0 * ($s1 + imm)]
  • div - two numbers division. [$d = $s0 / ($s1 + imm)]
  • mod - two numbers division remainder. [$d = $s0 % ($s1 + imm)]
  • cmz - conditional move zero. [if ($s0 == 0) $d = ($s1 + imm)]
  • cmn - conditional move non-zero. [if ($s0 != 0) $d = ($s1 + imm)]
  • ldb - load 1-byte. [$d = mem[S0] + S1 + imm]
  • lds - load 2-bytes. [$d = mem[S0] + S1 + imm]
  • ldl - load 4-bytes. [$d = mem[S0] + S1 + imm]
  • ldq - load 8-bytes. [$d = mem[S0] + S1 + imm]
  • svb - store 1-byte. [mem[$d] = S0 + S1 + imm]
  • svs - store 2-bytes. [mem[$d] = S0 + S1 + imm]
  • svl - store 4-bytes. [mem[$d] = S0 + S1 + imm]
  • svq - store 8-bytes. [mem[$d] = S0 + S1 + imm]
  • and - bitwise and. [$d = $s0 & ($s1 + imm)]
  • or - bitwise or. [$d = $s0 | ($s1 + imm)]
  • xor - bitwise xor. [$d = $s0 ^ ($s1 + imm)]
  • gr - is greater. [$d = $s0 > ($s1 + imm)]
  • ls - is less. [$d = $s0 < ($s1 + imm)]
  • gre - is greater or equal. [$d = $s0 >= ($s1 + imm)]
  • lse - is less or equal. [$d = $s0 <= ($s1 + imm)]
  • eq - is equal. [$d = $s0 == ($s1 + imm)]
  • neq - is not equal. [$d = $s0 != ($s1 + imm)]
  • ccl - call c-func. [cfuncs[$s0 + $s1 + imm]()]
  • nop - do nothing.

Clone this wiki locally