Design

July 22, 2017 · View on GitHub

Status: Initial draft

The virtual machine doesn't have a name yet, but to keep it short, we refer to it as the machine.

This document contains the specification for available registers, error codes, a list of instructions together with their arguments and descriptions.

For a syntactic overview of the language, see the assembly.md file.

For the specification on binary encoding, see the encoding.md file.

Error codes

NameValueDescription
REGULAR_EXIT0x00The machine exited normally
ILLEGAL_MEMORY_ACCESS0x01Memory read or write is out-of-bounds
INVALID_INSTRUCTION0x02Unknown instruction
INVALID_REGISTER0x03Unknown register
INVALID_SYSCALL0x04Unknown syscall id
EXECUTABLE_TOO_BIG0x05Executable won't fit into memory
INVALID_EXECUTABLE0x06Executable is invalid
ALLOCATION_FAILURE0x07Memory allocation failure
INTERNAL_FAILURE0x08Internal failure

Registers

Name Description
r0 .. r59General purpose
ipInstruction pointer
spStack pointer
fpFrame pointer
flagsFlags register
  • ip holds a pointer to the current instruction
  • sp holds a pointer to the top-most item on the stack
  • fp holds a pointer to the base of the current stack-frame
  • flags each bit is a specific flag that can be set by other instructions

Currently, only the lower byte of the flags register has anything meaningful in it. All other bytes are untouched by the machine.

      + Reserved / Undefined
      |
vvvvvvv
00000000
^^^^^^^^
       |
       +-- Zero flag - Set if the last operation resulted in zero (or a comparison resulted in true)

Registers can hold a 64-bit value. The default addressing mode is 32-bit (dword). You can target the lower byte, word or the full register qword by either appending b, w or q to the register name. Below is a visual representation of how a register can be accessed:

r0q:  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
r0:   00000000 00000000 00000000 00000000
r0w:  00000000 00000000
r0b:  00000000

When writing a value to a register that is bigger than what can ultimately fit into it, the value is trimmed.

; Before
;
; r0w: 00000011 11000000
; r0b: 00000000

mov r0b, r0w

; After
;
; r0b: 00000011

Memory

Memory layout is described in the encoding doc.

Size specifiers

Size specifiers can be used to describe a given amount of bytes.

A few constants are available for commonly used sizes.

  • byte - 1 byte
  • word - 2 bytes
  • dword - 4 bytes
  • qword - 8 bytes

Instructions

Instructions are names assigned to a specific opcode. Instruction encoding is described in the encoding doc.

Instruction descriptions

Each instruction in the machine is documented below. The Arguments section, if present, follows the following naming convention:

  • value Immediate value.
  • reg Register descriptor.
  • type Size specifier (e.g byte or word).
  • address Absolute address
  • offset Relative offset from a given point

If a register is surrounded with brackets, the value inside the register is meant.

Reading from and writing to registers

Name Arguments Description
rpushregPush reg onto the stack
rpopregPop a reg.size value from the stack into reg
movreg1, reg2Copies reg2 into r1
loadireg, valueRead an immediate reg.size and store it in reg
rstregReset a register to 0

Integer arithmetic instructions

NameArgumentsDescription
addreg1, reg2Add reg2 to reg1
subreg1, reg2Subtract reg2 from reg1
mulreg1, reg2Multiply reg1 by reg2
divreg1, reg2Divide reg1 by reg2
idivreg1, reg2Divide reg1 by reg2 (signed)
remreg1, reg2Put the remainder of (reg1 % reg2) in reg1
iremreg1, reg2Put the remainder of (reg1 % reg2) in reg1 (signed)

Floating-point arithmetic instructions

All registers of these instructions need to be in qword (e.g r0q) mode. If a register with a smaller mode is specified, this will result in a garbage value.

NameArgumentsDescription
faddreg1, reg2Add reg2 to reg1
fsubreg1, reg2Subtract reg2 from reg1
fmulreg1, reg2Multiply reg1 by reg2
fdivreg1, reg2Divide reg1 by reg2
fremreg1, reg2Put the remainder of (reg1 % reg2) in reg1
fexpreg1, reg2Raise reg1 to the power of reg2

Floating-point comparison instructions

NameArgumentsDescription
fltreg1, reg2Set flags zero bit, if reg1 is less than reg2
fgtreg1, reg2Set flags zero bit, if reg1 is greater than reg2

Integer comparison instructions

NameArgumentsDescription
cmpreg1, reg2Set flags zero bit, if reg1 and reg2 are equal
ltreg1, reg2Set flags zero bit, if reg1 is less than reg2
gtreg1, reg2Set flags zero bit, if reg1 is greater than reg2
ultreg1, reg2Set flags zero bit, if reg1 is less than reg2 (unsigned)
ugtreg1, reg2Set flags zero bit, if reg1 is greater than reg2 (unsigned)

Bitwise instructions

NameArgumentsDescription
shrreg1, reg2Right-Shift reg1 reg2 times
shlreg1, reg2Left-Shift reg1 reg2 times
andreg1, reg2Perform bitwise reg1 & reg2
xorreg1, reg2Perform bitwise reg1 ^ reg2
orreg1, reg2Perform bitwise `reg1
notreg1Perform bitwise ~reg1

Casting instructions

NameArgumentsDescription
inttofpregConvert reg from int to float
sinttofpregConvert reg from signed int to float
fptointregConvert reg from float to signed int

Stack instructions

NameArgumentsDescription
loadreg, offsetRead a reg.size value from fp + offset and store it in reg
loadrreg, offsetRead a reg.size value from fp + [offset] and store it in reg
loadstype, offsetRead a type value from fp + offset and push it onto the stack
loadsrtype, regRead a type value from fp + [reg] and push it onto the stack
storeoffset, regStore the contents of reg at fp + offset
pushtype, valuePush value onto the stack

Memory read / write

NameArgumentsDescription
readreg, addressRead reg.size bytes at [address] and store in reg
readcreg, addressRead reg.size bytes at address and store in reg
readstype, addressRead a type value from [address] and push it onto the stack
readcstype, addressRead a type value from address and push it onto the stack
writeaddress, regWrite the contents of reg to [address]
writecaddress, regWrite the contents of reg to address
writesaddress, typePop a type value from the stack and write it to [address]
writecsaddress, typePop a type value from the stack and write it to address
copytarget, type, sourceCopy a type value from [source] to [target]
copyctarget, type, sourceCopy a type value from source to target

Jump instructions

NameArgumentsDescription
jzoffsetJump to offset if the zero bit in the flags register is set
jzroffsetJump to [offset] if the zero bit in the flags register is set
jmpoffsetJump to offset
jmproffsetJump to [offset]
calloffsetPush a stack frame and jump to offset
callroffsetPush a stack frame and jump to [offset]
retReturn from the current stack frame

Miscellaneous instructions

NameDescription
nopDoes nothing
syscallVM syscall

Syscalls

Syscalls are subroutines implemented directly inside the machine that provide some useful functionality, such as doing IO or getting input from the user. To make a syscall, push any arguments first and the syscall id onto the stack. The syscall id is a word.

Available syscalls

NameOpcodeArgumentsDescription
exit0x00codeHalt the machine with code as the exit code (single byte)
sleep0x01secondsSleeps for seconds. seconds is a float64
write0x02address, countWrites count bytes from address into stdout
puts0x03regPrints the contents of reg
read0x04regReads one character from stdin and saves it to reg

Return values of syscalls are pushed onto the stack. Different syscalls may produce different return values.

License

The MIT License (MIT)

Copyright (c) 2017 Leonard Schuetz

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.