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, henceforth referred to H5VM, is a specified execution engine for programs.
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.
0b00
=m
, 0b01
=i
,
0b10
=p
, 0b11
=s
), the
register cell (8 bits), and the operand (16 bits)jmp
, skpz
,
skmz
, func
, ret
,
call
.skpz
or an
skmz
, the program counter also just increases by one as
usual)_X
/X_
, where its
register code is X
and has the case indicated in the memory
layout section. If it is irrelevant, it is labelled as __
in the opcode guide. Note __
does not stand for a space,
but for two literal underscode characters.
’. The following combinations are accepted in assembly, in
which case the non present data will be taken to be all zeroes: opcode,
opcode + addressing mode, opcode + addressing mode + register cell,
opcode + addressing mode + register cell + two-digit operand, opcode +
addressing mode + register cell + four-digit operand:
’;
in a line, if present, to the end of the line, and they
are ignored by the assembler.Each opcode is numbered with its corresponding decimal number. It corresponds to the representation used in the opcode.
Opcodes 0
through to 3
conform the
control flow group
Opcodes 4
through to to 8
conform the
subroutine group
Opcodes 9
through to 12
conform the
memory management group
m
:i
:p
:s
:__
OP
- Jump
m
: Set program counter to the value of
address OP
.i
: Set program counter to the immediate
value OP
.p
: Set program counter to by dereference
of OP
.s
: Not supported.__
OP
- Skip plus if zero
m
: Same as i
.i
: If the zero flag is set to low, add
to the program counter the immediate value OP
, plus one.
Else, do nothing.p
: Not supported.s
: Not supported.__
OP
- Skip minus if zero
m
: Same as i
.i
: If the zero flag is set to low,
substract from the program counter [the immediate value OP
,
minus one] (pay attention to bracket positioning). Else, do
nothing.p
: Not supported.s
: Not supported._X
OP
- Register subroutine
m
: Same as i
.i
: Set the jumptable address
OP
to the current program counter plus one.p
: Not supported.s
: Set the jumptable address [value
of address OP
] to the value of register
X
.__
OP
- Call subroutine
m
: Same as i
i
: Set the address pointed to by the
stack pointer to the current program counter plus one. This is known as
the return program counter. Then set the program counter to the value of
jumptable address OP
.p
: Not supported.s
: Set the address pointed to by the stack
pointer to the current program counter plus one. This is known as the
return program counter. Then set the program counter to the value of
(normal, not jumptable!) address OP
._X
OP
- Memory load
m
: Copy value of address OP
to register X
i
: Copy immediate value OP
to register X
p
: Copy dereference of OP
to
register X
s
: Copy register OP
to
register X
_X
OP
- Variable load
m
: Copy register X
to the
local variable address obtained by adding [the value of address
OP
] to the current stack pointer value.i
: Copy register X
to the
local variable address obtained by adding [immediate value
OP
] to the current stack pointer value.p
: Unsupported modes
: Unsupported mode_X
OP
- Memory store
m
: Copy register X
to address
OP
i
: Unsupported modep
: Copy register X
to the
address pointed to by OP
s
: Unsupported mode_X
OP
- Variable store
m
: Copy the value of [the local variable
address obtained by adding [the value of address OP
] to the
current stack pointer value] to register X
.i
: Copy the value of [the local variable
address obtained by adding [immediate value OP
] to the
current stack pointer value] to register X
.p
: Unsupported modes
: Unsupported mode__
OP
- Set flag
OP
(starting with the least
significant bit) of the flag register to high.__
OP
- Delete flag
OP
(starting with the least
significant bit) of the flag register to low.__
OP
- Flip flag
OP
(starting with the least
significant bit) of the flag register to low if it is currently high,
and to high if it is currently low.MLOD
, but:MLOD
, but:MLOD
, but:MLOD
, but:MLOD
, but:MLOD
, but:BSUB
, but merely sets the flags
and doesn’t actually modify any other place in memory or the registers,
discarding the result.