Halfive Virtual Machine Specification

Copyright Nomagno 2021-2023

Copying and distribution of this work, with or without modification, are permitted in any medium without royalty, provided the copyright notice and this notice are preserved. This work is offered as-is, without any warranty.

H5VM assembly is identified by the MIME type text/x-h5asm, extension “.h5asm”

H5VM machine code sequences or “executables” are identified by the MIME type application/x-h5bin, extension “.h5bin”

H5VM drives are identified by the MIME type application/x-h5drive, extension “.h5drive”

The Halfive virtual machine

The Halfive virtual machine, henceforth referred to H5VM, is a specified execution engine for programs.


H5VM Memory layout (Code memory and data memory)

Following Harvard architecture principles, H5VM loads code and data separately into two different ‘members’. The machine code is loaded into the code member, while the data member contains almost all information that is manipulated during the program execution itself. Both members are big-endian.

The code member is read-only.

The data member has addresses (16-bit unsigned memory cells indexed from 0 to 0xFFFF). Address 0x00 is known as the zero address, and is reserved. While the rest of the memory is completely free to use so long as it is mapped to a physical device, addresses 0x01 through 0xFD are likely to be used for the jumptable. Reads from address 0xFE may prompt the user for input, and writes to address 0xFF may display the written data to the user. “Jumptable address foo” is a shorthand for the memory cell with index jumptable_offset + 1. jumptable_offset has value 0x01 which can not be changed.

There is additionally a register member, which has currently multiple defined registers: - Flag register (0x00) (F): This register has multiple flags that are defined later on. Starting from the LEAST significant bit, the meaning of each zero-indexed bit position is: * 0 = Zero Flag - Set by arithmetic group operations. If the result is zero, it is set to low, else it is set to high. * 1 = Overflow Flag - Set by wraparound group operations. If the operation results in wraparound, set it to high, else set it to low. * 2 through 7 - Reserved * 8 trough 15 - Implementation-defined - Program counter register (0x01) (P): Holds the actual program counter value used to drive the processor. Please modify through the appropiate control flow group and subroutine group operations only. - Stack pointer register (0x02) (S): holds the stack pointer, used by multiple operations. It can be modified directly, but using the subroutine group operations STKI and STKD is highly recommended unless there is a special need. - Stack size register (0x03) (R): holds the size of each stack frame, in memory cells. - General purpose registers A, B, C, D, W, X, Y, Z (0x04 through to 0x0B): Can be written or read from for any purpose, at any time.

Machine code format:

Assembly format:

Opcodes

  1. HALT
  2. JUMP __ OP - Jump
  3. SKPZ __ OP - Skip plus if zero
  4. SKMZ __ OP - Skip minus if zero
  5. STKI
  6. STKD
  7. FUNC _X OP - Register subroutine
  8. BACK - End of subroutine
  9. CALL __ OP - Call subroutine
  10. MLOD _X OP - Memory load
  11. VLOD _X OP - Variable load
  12. MSTR _X OP - Memory store
  13. VSTR _X OP - Variable store
  14. FSET __ OP - Set flag
  15. FDEL __ OP - Delete flag
  16. FFLP __ OP - Flip flag
  17. BADD - Unsigned addition
  18. BSUB - Unsigned substraction
  19. BAND - Bitwise and
  20. INOR - Inclusive or
  21. EXOR - Exclusive or
  22. SHFT - Shift bits
  23. COMP - Comparison