This document describes the bytecode format used by the Sharemind Virtual machine.
The bytecode consists of 8-byte (64-bit) blocks. Each 8-byte block represents an instruction code, or argument data. The block size of 64 bits was chosen to be wide enough to be used for immediate values and pointers of the underlying hardware architecture. This is needed to implement direct-threaded code.
Bit notation is big-endian, e.g. 0x2d
is denoted as 00101101
.
Symbol | Description |
---|---|
0 |
unset bit |
1 |
set bit |
. |
undefined up to this point, might not be part of any instruction, 0 by convention |
The instruction format base specifies a base layout for all instructions. It only uses the 2 first bytes of the 8-byte block to denote the instruction type. The last 6 bytes are instruction-specific.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 |
---|---|---|---|---|---|---|---|
NNNNNNNN |
TTTTTTTT |
........ |
........ |
........ |
........ |
........ |
........ |
NNNNNNNN
- namespace of instructionTTTTTTTT
- namespace-specific type of instruction- 6 bytes of instruction subtype
An instruction may be followed by a fixed number of 8-byte blocks containing the instruction arguments depending on the specific instruction.
The data type byte defines a data type of the virtual machine. The first 4 bits of the data type byte define the format of type and the last 3 bits define the width of its values. The 5th bit of the data type byte is currently reserved.
Name | Value | Description |
---|---|---|
uint | 0x00 | unsigned integer |
int | 0x10 | signed integer |
float | 0x20 | IEEE 754 floating-point |
FUTURE fixed-point number types can be added here. For examples, see: http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1169.pdf.
Name | Value | Description | In use? |
---|---|---|---|
variable | 0x00 |
variable width | Reserved |
fixed8 | 0x01 |
1 byte (8 bits) | Yes |
fixed16 | 0x02 |
2 byte (16 bits) | Yes |
fixed32 | 0x03 |
4 byte (32 bits) | Yes |
fixed64 | 0x04 |
8 byte (64 bits) | Yes |
0x05 |
16 byte (128 bits) | Reserved for IEEE 754 quadruple? | |
0x06 |
Reserved | ||
0x07 |
Reserved |
Alias | Type | Width | Value |
---|---|---|---|
uint8 | uint | fixed8 | 0x01 |
uint16 | uint | fixed16 | 0x02 |
uint32 | uint | fixed32 | 0x03 |
uint64 | uint | fixed64 | 0x04 |
int8 | int | fixed8 | 0x11 |
int16 | int | fixed16 | 0x12 |
int32 | int | fixed32 | 0x13 |
int64 | int | fixed64 | 0x14 |
float32 | float | fixed32 | 0x23 |
float64 | float | fixed64 | 0x24 |
The operand location byte denotes where the actual data of the operand resides.
Name | Value | Used by |
---|---|---|
imm | 0x01 |
Most instructions |
reg | 0x02 |
Most instructions |
stack | 0x04 |
Most instructions |
ref | 0x08 |
common.proc reference pushing instructions and common.mov |
cref | 0x10 |
common.proc reference pushing instructions and common.mov |
mem_imm | 0x20 |
common.proc reference pushing instructions and common.mov |
mem_reg | 0x40 |
common.proc reference pushing instructions and common.mov |
mem_stack | 0x80 |
common.proc reference pushing instructions and common.mov |
Most instructions only use imm, reg and stack to keep the total number of instructions reasonable.
Instructions in the "arith", "bitwise" and "logical" namespaces have one, two or three arguments. Byte 1 of each instruction specifies the type of the instruction in each namespace. The two higher bits of byte 1 (also named the bit prefix) denote its class and specify the number of arguments for the instruction. The six lower bits of byte 1 specify the rest of the type for the instruction. The class can be one of the following:
Value in base 2 | Description | Style |
---|---|---|
00 |
unary instructions: | dest := op(dest) |
01 |
binary instructions: | dest := op(src) |
10 |
binary instructions: | dest := op(dest, src) |
11 |
trinary instructions: | dest := op(src1, src2) |
The format of the instructions in these namespaces is the following, for one, two and three arguments respectively:
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | arg 3 |
---|---|---|---|---|---|---|---|---|---|---|
NNNNNNNN |
00TTTTTT |
DTB | OLBdest | ........ |
........ |
........ |
........ |
dest | ||
NNNNNNNN |
01TTTTTT |
DTB | OLBdest | OLBsrc | ........ |
........ |
........ |
dest | src | |
NNNNNNNN |
10TTTTTT |
DTB | OLBdest | OLBsrc+ | ........ |
........ |
........ |
dest | src | |
NNNNNNNN |
11TTTTTT |
DTB | OLBdest | OLBsrc1 | OLBsrc2 | ........ |
........ |
dest | src1 | src2 |
NNNNNNNN
- namespace of instructionTTTTTT
- type of instruction- DTB - data type of all arguments
- OLBdest - operand location (reg or stack) of the first argument (dest).
- OLBsrc - operand location (reg or stack) of the second argument (src).
- OLBsrc+ - operand location (imm, reg or stack) of the second argument (src).
- OLBsrc1 - operand location (imm, reg or stack) of the second argument (src1).
- OLBsrc2 - operand location (reg or stack; or imm, if the OLBsrc1 is not imm) of the third argument (src2).
The first argument (dest) specifies write-only or read-write data. Other arguments (src, src1 and src2) specify read-only data.
Operations on floating point (float32 and float64) values are handled by the software or hardware floating point unit (FPU). The FPU is controlled by the virtual machines FPU state register which can be read and set using the common.fpu.getstate and common.fpu.setstate instructions. The bits of this 64-bit register from lowest (0) to highest (63) are used as follows:
Bit(s) | Description | Value | Value description |
---|---|---|---|
0 | Underflow detection mode | 0x00 | Detect underflow tininess after rounding (default) |
0 | Underflow detection mode | 0x01 | Detect underflow tininess before rounding |
1-2 | Rounding mode | 0x00 << 1 | Round to nearest even number (default) |
1-2 | Rounding mode | 0x01 << 1 | Round to zero |
1-2 | Rounding mode | 0x02 << 1 | Round to down |
1-2 | Rounding mode | 0x03 << 1 | Round to up |
3 | Fatal exceptions flags | 0x01 << 3 | Crash on inexact result (default is not set) |
4 | Fatal exceptions flags | 0x02 << 3 | Crash on underflow (default is not set) |
5 | Fatal exceptions flags | 0x04 << 3 | Crash on overflow (default is not set) |
6 | Fatal exceptions flags | 0x08 << 3 | Crash on divide by zero (default is not set) |
7 | Fatal exceptions flags | 0x10 << 3 | Crash on invalid operation (default is not set) |
8 | Active exception flags | 0x01 << 8 | Inexact result (default is not set) |
9 | Active exception flags | 0x02 << 8 | Underflow (default is not set) |
10 | Active exception flags | 0x04 << 8 | Overflow (default is not set) |
11 | Active exception flags | 0x08 << 8 | Divide by zero (default is not set) |
12 | Active exception flags | 0x10 << 8 | Invalid operation (default is not set) |
13-63 | Unused |
Floating point operations may generate exceptions. If an exception occurs and the FPU state register has the "Crash on ..." bit set for that exception, the execution of the process terminates with that exception. Otherwise just the active exception flag for that exception is set in the FPU state register. The virtual machine never clears the active exception flags. It is the responsibility of the process to clear the active exception flags when desired. By default, the "Crash on ..." bits are not set and all raised exceptions are effectively ignored (this replicates AMD64 default behaviour).
Name | Value | Description |
---|---|---|
common | 0x00 |
common instructions |
arith | 0x01 |
arithmetic instructions |
bitwise | 0x02 |
bitwise instructions |
logical | 0x03 |
logical instructions |
jump | 0x04 |
jump instructions |
Instruction | Prefix | Description | Implemented? |
---|---|---|---|
common.nop | 0x000000 |
no operation | Yes |
common.trap | 0x000001 |
trap | Yes |
common.mov | 0x0001 |
move value | Yes |
common.proc.call | 0x000200 |
call a procedure from the current code segment | Yes |
common.proc.lnkcall | 0x000201 |
call a procedure from another linked code segment | No |
common.proc.syscall | 0x000202 |
call a system procedure | Yes |
common.proc.return | 0x000203 |
return from the current proceure | Yes |
common.proc.push | 0x000204 |
push a value onto the next procedure stack | Yes |
common.proc.pushref | 0x000205 |
push a reference onto the next procedure reference stack | Yes |
common.proc.pushrefpart | 0x000206 |
push a partial reference onto the next procedure reference stack | Yes |
common.proc.pushcref | 0x000207 |
push a constant reference onto the next procedure constant reference stack | Yes |
common.proc.pushcrefpart | 0x000208 |
push a partial constant reference onto the next procedure constant reference stack | Yes |
common.proc.clrstack | 0x000209 |
clears all the next procedure stacks | Yes |
common.proc.resizestack | 0x00020a |
resizes the current stack frame | Yes |
common.proc.getrefsize | 0x00020c |
gets the size of the given mutable reference in bytes | Yes |
common.proc.getcrefsize | 0x00020d |
gets the size of the given constant reference in bytes | Yes |
common.mem.alloc | 0x000300 |
allocates memory | Yes |
common.mem.free | 0x000301 |
frees allocated memory | Yes |
common.mem.getmemsize | 0x000302 |
gets the size of the given memory area in bytes | Yes |
common.mem.getnrefs | 0x000303 |
gets the number of references the given memory area has | No |
common.mem.dup | 0x000304 |
duplicates the given memory | No |
common.convert | 0x0004 |
converts between values | Yes |
common.fpu.getstate | 0x000500 |
reads the state of the FPU | Yes |
common.fpu.setstate | 0x000501 |
sets the state of the FPU | Yes |
common.halt | 0x00ff00 |
ends program execution | Yes |
common.except | 0x00ff0100 |
throws an user exception (deprecated) | Yes |
common.user_except | 0x00ff0101 |
throws an user exception | Yes |
Does nothing, except increment the instruction pointer.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 |
---|---|---|---|---|---|---|---|
00000000 |
00000000 |
00000000 |
........ |
........ |
........ |
........ |
........ |
No arguments.
Generates a trap signal for the debugger.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 |
---|---|---|---|---|---|---|---|
00000000 |
00000000 |
00000001 |
........ |
........ |
........ |
........ |
........ |
No arguments.
Moves values from a register or a memory slot to another register or memory slot, i.e.
for (0 <= w <= W) d[w] := s[w]
where W
is the number of bytes to move, d
is the destination and s
is the
source of the data.
If the source or destination of the data is a global register or stack register,
then the data is moved to/from the beginning of the the respective register
(i.e. affecting only the W
first bytes, the least-significant bytes).
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | arg 3 | arg 4 | arg 5 | notes |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00000000 |
00000001 |
OLBsrc | 00000000 |
OLBdest | 00000000 |
00000000 |
........ |
src | dest | if {OLB<sub>src</sub>} ∪ {OLB<sub>dest</sub>} ⊂ { imm, reg, stack } |
|||
00000000 |
00000001 |
OLBsrc | 00000000 |
OLBdest | OLBdestOffset | OLBnbytes | ........ |
src | dest | destOffset | nbytes | if (OLB<sub>src</sub> ∈ { imm, reg, stack }) ∧ (OLB<sub>dest</sub> ∉ { imm, reg, stack }) |
|
00000000 |
00000001 |
OLBsrc | OLBsrcOffset | OLBdest | 00000000 |
OLBnbytes | ........ |
src | srcOffset | dest | nbytes | if (OLB<sub>src</sub> ∉ { imm, reg, stack }) ∧ (OLB<sub>dest</sub> ∈ { imm, reg, stack }) |
|
00000000 |
00000001 |
OLBsrc | OLBsrcOffset | OLBdest | OLBdestOffset | OLBnbytes | ........ |
src | srcOffset | dest | destOffset | nbytes | if (OLB<sub>src</sub> ∉ { imm, reg, stack }) ∧ (OLB<sub>dest</sub> ∉ { imm, reg, stack }) |
00000000
- namespace "common"00000001
- instruction type "move value"- OLBsrc - operand location for source
- OLBdest - operand location for destination (reg, stack, ref or mem_*)
- OLBsrcOffset - operand location for source offset (imm, reg or stack)
- OLBdestOffset - operand location for destination offset (imm, reg or stack)
- OLBnbytes - operand location for number of bytes to copy (imm, reg or stack)
Arguments:
- src - The source operand
- srcOffset - The source operand offset
- dest - The destination operand
- destOffset - The destination operand offset
- nbytes - The number of bytes to copy (uint64). Must be greater than 0 if OLBnbytes is imm.
Calls the given procedure from the current code segment.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | notes |
---|---|---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00000000 |
OLBproc | OLBret | ........ |
........ |
........ |
proc | if OLB<sub>ret</sub> = imm |
|
00000000 |
00000010 |
00000000 |
OLBproc | OLBret | ........ |
........ |
........ |
proc | ret | if OLB<sub>ret</sub> ≠ imm |
- OLBproc - the operand location (imm, reg or stack) of the procedure address.
- OLBret - the operand location (imm, reg or stack) for the return value.
Arguments:
- A 64-bit address (index of the 64-bit block containing the first instruction of the called process).
- if the operand location for the return value is reg or stack, the index of the register or stack where the return value should be written. Otherwise, if operand location of the return value is imm, the second argument is omitted, i.e. the return value is discarded.
Calls the given procedure from the given code segment.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | arg 3 | notes |
---|---|---|---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00000001 |
OLBlunit | OLBproc | OLBret | ........ |
........ |
lunit | proc | if OLB<sub>ret</sub> = imm |
|
00000000 |
00000010 |
00000001 |
OLBlunit | OLBproc | OLBret | ........ |
........ |
lunit | proc | ret | if OLB<sub>ret</sub> ≠ imm |
- OLBlunit - the operand location (imm, reg or stack) of the code segment index.
- OLBproc - the operand location (imm, reg or stack) of the procedure address.
- OLBret - the operand location (imm, reg or stack) for the return value.
Arguments:
- A 64-bit index of the code segment containing the procedure to be called.
- A 64-bit address (index of the 64-bit block containing the first instruction of the called process).
- if the operand location for the return value is reg or stack, the index of the register or stack where the return value should be written. Otherwise, if operand location of the return value is imm, the third argument is omitted, i.e. the return value is discarded.
Calls the given system call.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | notes |
---|---|---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00000010 |
OLBproc | OLBret | ........ |
........ |
........ |
proc | if OLB<sub>ret</sub> = imm |
|
00000000 |
00000010 |
00000010 |
OLBproc | OLBret | ........ |
........ |
........ |
proc | ret | if OLB<sub>ret</sub> ≠ imm |
- OLBproc - the operand location (imm, reg or stack) of the system call index.
- OLBret - the operand location (imm, reg or stack) for the return value.
Arguments:
- The 64-bit index of the system call to call.
- if the OLBret is reg or stack, the index of the register or stack where the return value should be written. Otherwise, if OLBret is imm, the second argument is omitted, i.e. the return value is discarded.
Frees the next procedure stack and returns from the current procedure.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00000011 |
OLBretval | ........ |
........ |
........ |
........ |
retval |
- OLBretval - the operand location (imm, reg or stack) of the return value.
Arguments:
- a 64-bit return value. Procedures with no return values in higher-level languages should by convention return (uint64) 0.
Pushes a 64-bit value to the next procedure stack.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00000100 |
OLBvalue | ........ |
........ |
........ |
........ |
value |
- OLBvalue - the operand location (imm, reg or stack) of the value to push.
Arguments:
- The 64-bit value to push, depending on OLBvalue.
Pushes a mutable reference to the next procedure stack. The reference created references the whole of the given data.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00000101 |
OLBindex | ........ |
........ |
........ |
........ |
index |
- OLBindex - the operand location (all except imm and cref) of the value to reference.
Arguments:
- The 64-bit unsigned register index, stack register index, memory handle index or mutable reference index.
Pushes a partial reference to the next procedure stack.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | arg 3 |
---|---|---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00000110 |
OLBindex | OLBoffset | OLBlength | ........ |
........ |
index | offset | length |
- OLBindex - the operand location (all except imm and cref) of the value to reference.
- OLBoffset - the operand location (imm, reg or stack) of the offset in bytes in the value to reference.
- OLBlength - the operand location (imm, reg or stack) of the number of bytes to reference.
Arguments:
- The 64-bit unsigned register index, stack register index, memory handle index or mutable reference index.
- The 64-bit unsigned offset in bytes in the value to reference.
- The 64-bit unsigned amount of bytes to reference.
Pushes a constant reference to the next procedure stack. The constant reference created references the whole of the given data.
| byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
|----------|----------|----------|----------|----------|----------|----------|----------|---------|---------|---------|
|00000000
|00000010
|00000111
|OLBindex|........
|........
|........
|........
| index |
- OLBindex - the operand location (imm, reg, stack, cref, ref, mem_reg, mem_stack) of the value to reference.
Arguments:
- The 64-bit unsigned immediate, register index, stack register index, memory handle index, mutable reference index or constant reference index.
Pushes a partial constant reference to the next procedure stack.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | arg 3 |
---|---|---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00001000 |
OLBindex | OLBoffset | OLBlength | ........ |
........ |
index | offset | length |
- OLBindex - the operand location of the value to reference.
- OLBoffset - the operand location (imm, reg or stack) of the offset in bytes in the value to reference.
- OLBlength - the operand location (imm, reg or stack) of the number of bytes to reference.
Arguments:
- The 64-bit unsigned immediate, register index, stack register index, memory handle index, mutable reference index or constant reference index.
- The 64-bit unsigned offset in bytes in the value to reference.
- The 64-bit unsigned amount of bytes to reference (64-bit value).
Clears the next procedure stack.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 |
---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00001001 |
........ |
........ |
........ |
........ |
........ |
No arguments.
Resizes the container for the current stack frame.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00001010 |
........ |
........ |
........ |
........ |
........ |
nregs |
When starting a program (entering a stack frame), no global (stack) registers are available. Use this command to allocate registers.
Registers can also be reallocated using this instruction. During reallocation, existing registers retain their indexes and contents. If the number of registers to be allocated is greater than the number of registers currently allocated, new uninitialized registers are added. If the number of registers to be allocated is less than the number of registers currently allocated, registers with indexes greater or equal than the number of registers to be allocated will not be accessible after this instructions. Note that this does not ensure secure deletion of the contents of registers which were made inaccessible by the reallocation, since their memory might later be reused for newly allocated uninitialized data.
Arguments:
- The 64-bit unsigned number of (global or stack) registers to be present after executing this instruction.
Retrieves the size of the mutable reference in bytes.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 |
---|---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00001100 |
OLBref | OLBsizedest | ........ |
........ |
........ |
ref | sizedest |
- OLBref - the operand location (imm, reg or stack) of the mutable reference.
- OLBsizedest - the operand location (reg or stack) where to store the size of bytes held by the mutable reference.
Arguments:
- The 64-bit unsigned index of the mutable reference or the index of the register or stack slot where the index is held.
- The 64-bit unsigned index of the register or stack slot where to store the number of bytes held by the reference.
Retrieves the size of the constant reference in bytes.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 |
---|---|---|---|---|---|---|---|---|---|
00000000 |
00000010 |
00001101 |
OLBcref | OLBsizedest | ........ |
........ |
........ |
cref | sizedest |
- OLBcref - the operand location (imm, reg or stack) of the constant reference.
- OLBsizedest - the operand location (reg or stack) where to store the size of bytes held by the constant reference.
Arguments:
- The 64-bit unsigned index of the constant reference or the index of the register or stack slot where the index is held.
- The 64-bit unsigned index of the register or stack slot where to store the number of bytes held by the reference.
Allocates dynamic memory, and retrieves a 64-bit unsigned memory handle, or 0 if allocation fails.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 |
---|---|---|---|---|---|---|---|---|---|
00000000 |
00000011 |
00000000 |
OLBhandleDest | OLBnbytes | ........ |
........ |
........ |
handleDest | nbytes |
- OLBhandleDest - the operand location (reg or stack) where to store the memory handle.
- OLBnbytes - the operand location (imm, reg or stack) of the number of bytes to allocate.
Arguments:
- The 64-bit unsigned register or stack slot index to write the retrieved memory handle index to.
- The 64-bit unsigned number of bytes to allocate (64-bit value).
Frees dynamic memory.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
00000011 |
00000001 |
OLBhandle | ........ |
........ |
........ |
........ |
handle |
- OLBhandle - the operand location (reg or stack) of the memory handle.
Arguments:
- The 64-bit unsigned index of the register or stack slot where to read the memory handle from.
Retrieves the size of the allocated memory in bytes.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 |
---|---|---|---|---|---|---|---|---|---|
00000000 |
00000011 |
00000010 |
OLBhandle | OLBsizedest | ........ |
........ |
........ |
handle | sizedest |
- OLBhandle - the operand location (imm, reg or stack) of the memory handle.
- OLBsizedest - the operand location (reg or stack) where to store the size of bytes held by the memory handle.
Arguments:
- The 64-bit unsigned index of the register or stack slot where to read the memory handle from.
- The 64-bit unsigned index of the register or stack slot where to store the number of bytes to allocate.
Converts between register values.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 |
---|---|---|---|---|---|---|---|---|---|
00000000 |
00000100 |
DTBsrc | OLBsrc | DTBdest | OLBdest | ........ |
........ |
src | dest |
- DTBsrc - the data type of the source value.
- OLBsrc - the operand location (reg or stack) of the source value.
- DTBdest - the data type of the destination value (must be different from DTBsrc).
- OLBdest - the operand location (reg or stack) of the destination value.
Arguments:
- The 64-bit unsigned index of the source register or stack slot where to read the value from.
- The 64-bit unsigned index of the destination register or stack slot where to store the converted value.
Reads the state of the FPU.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
00000101 |
00000000 |
OLBdest | ........ |
........ |
........ |
........ |
dest |
- OLBdest - the operand location (reg or stack) where to write the contents of the FPU state register.
Arguments:
- The 64-bit unsigned index of the destination register or stack slot where to write the contents of the FPU state register.
Sets the state of the FPU.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
00000101 |
00000000 |
OLBsrc | ........ |
........ |
........ |
........ |
src |
- OLBsrc - the operand location (imm, reg or stack) where to read the contents of the FPU state register from.
Arguments:
- If OLBsrc ⊂ { reg, stack }, the 64-bit unsigned index of the destination register or stack slot where to read the contents of the FPU state register from. Otherwise, if OLBsrc = imm, the immediate value to set the FPU state register to.
Halts program execution.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
11111111 |
00000000 |
OLBretval | ........ |
........ |
........ |
........ |
retval |
- OLBretval - The operand location (imm, reg or stack) of the return value.
Arguments:
- The 64-bit signed return value (try to use values less than 232-1)
Halts program execution with an user exception. This system call is deprecated, use common.user_except instead.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000000 |
11111111 |
00000001 |
00000000 |
........ |
........ |
........ |
........ |
errnum |
Arguments:
- An user exception code.
Halts program execution with an user exception given a custom message contained on the top of the constant reference stack. If there constant reference stack is empty, then errors.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 |
---|---|---|---|---|---|---|---|
00000000 |
11111111 |
00000001 |
00000001 |
........ |
........ |
........ |
........ |
Arguments: None.
For a short explanation on the format of this section, see here.
Instruction | Value | Description | Implemented? |
---|---|---|---|
arith.uneg | 0x0100 |
d := -d | Yes |
arith.uinc | 0x0101 |
d := d + 1 | Yes |
arith.udec | 0x0102 |
d := d - 1 | Yes |
Instruction | Value | Description | Implemented? |
---|---|---|---|
arith.bneg | 0x0140 |
d := -s | Yes |
arith.binc | 0x0141 |
d := s + 1 | Yes |
arith.bdec | 0x0142 |
d := s - 1 | Yes |
Instruction | Value | Description | Implemented? |
---|---|---|---|
arith.badd | 0x0180 |
d := d + s | Yes |
arith.bsub | 0x0181 |
d := d - s | Yes |
arith.bsub2 | 0x0182 |
d := s - d | Yes |
arith.bmul | 0x0183 |
d := d * s | Yes |
arith.bdiv | 0x0184 |
d := d / s | Yes |
arith.bdiv2 | 0x0185 |
d := s / d | Yes |
arith.bmod | 0x0186 |
d := d % s | Yes |
arith.bmod2 | 0x0187 |
d := s % d | Yes |
arith.bpow | 0x0188 |
d := d raised to the s-th power | No |
arith.bpow2 | 0x0189 |
d := s raised to the d-th power | No |
arith.blog | 0x018a |
d := logarithm of d to base s | No |
arith.blog2 | 0x018b |
d := logarithm of s to base d | No |
arith.broot | 0x018c |
d := s-th root of d | No |
arith.broot2 | 0x018d |
d := d-th root of s | No |
Instruction | Value | Description | Implemented? |
---|---|---|---|
arith.tadd | 0x01c0 |
d := s1 + s2 | Yes |
arith.tsub | 0x01c1 |
d := s1 - s2 | Yes |
0x01c2 |
RESERVED | ||
arith.tmul | 0x01c3 |
d := s1 * s2 | Yes |
arith.tdiv | 0x01c4 |
d := s1 / s2 | Yes |
0x01c5 |
RESERVED | ||
arith.tmod | 0x01c6 |
d := s1 % s2 | Yes |
0x01c7 |
RESERVED | ||
arith.tpow | 0x01c8 |
d := s1 raised to the s2-th power | No |
0x01c9 |
RESERVED | ||
arith.tlog | 0x01ca |
d := logarithm of s1 to base s2 | No |
0x01cb |
RESERVED | ||
arith.troot | 0x01cc |
d := s2-th root of s1 | No |
0x01cd |
RESERVED |
For a short explanation on the format of this section, see here.
The instructions in the bitwise namespace only accept operands of type uint.
Instruction | Value | Description | Implemented? |
---|---|---|---|
bitwise.uinv | 0x0200 |
d := ~d | Yes |
0x0201 |
RESERVED | ||
bitwise.urtl | 0x0202 |
d := bitwise rotate left of d by 1 bit | Yes |
bitwise.urtr | 0x0203 |
d := bitwise rotate right of d by 1 bit | Yes |
bitwise.ushl0 | 0x0204 |
d := bitwise shift left of d by 1 bit, add unset (0) bit | Yes |
bitwise.ushl1 | 0x0205 |
d := bitwise shift left of d by 1 bit, add set (1) bit | Yes |
bitwise.ushr0 | 0x0206 |
d := bitwise shift right of d by 1 bit, add unset (0) bit | Yes |
bitwise.ushr1 | 0x0207 |
d := bitwise shift right of d by 1 bit, add set (1) bit | Yes |
bitwise.ushl | 0x0208 |
d := bitwise shift left of d by 1 bit, extend last bit | Yes |
bitwise.ushr | 0x0209 |
d := bitwise shift right of d by 1 bit, extend first bit | Yes |
Instruction | Value | Description | Implemented? |
---|---|---|---|
bitwise.binv | 0x0240 |
d := ~s | Yes |
0x0241 |
RESERVED | ||
bitwise.b1rtl | 0x0242 |
d := bitwise rotate left of s by 1 bit | Yes |
bitwise.b1rtr | 0x0243 |
d := bitwise rotate right of s by 1 bit | Yes |
bitwise.b1shl0 | 0x0244 |
d := bitwise shift left of s by 1 bit, add unset (0) bit | Yes |
bitwise.b1shl1 | 0x0245 |
d := bitwise shift left of s by 1 bit, add set (1) bit | Yes |
bitwise.b1shr0 | 0x0246 |
d := bitwise shift right of s by 1 bit, add unset (0) bit | Yes |
bitwise.b1shr1 | 0x0247 |
d := bitwise shift right of s by 1 bit, add set (1) bit | Yes |
bitwise.b1shl | 0x0248 |
d := bitwise shift left of s by 1 bit, extend last bit | Yes |
bitwise.b1shr | 0x0249 |
d := bitwise shift right of s by 1 bit, extend first bit | Yes |
Instruction | Value | Description | Implemented? |
---|---|---|---|
bitwise.bb_0000 | 0x0280 |
d := d AND (NOT d) | RESERVED |
bitwise.bband | 0x0281 |
d := d AND s | Yes |
bitwise.bbabj | 0x0282 |
d := d AND (NOT s) | Yes |
bitwise.bb_0011 | 0x0283 |
d := d | RESERVED |
bitwise.bbcni | 0x0284 |
d := (NOT d) AND s | Yes |
bitwise.bb_0101 | 0x0285 |
d := s | RESERVED |
bitwise.bbxor | 0x0286 |
d := d XOR s | Yes |
bitwise.bbor | 0x0287 |
d := d OR s | Yes |
bitwise.bbbnor | 0x0288 |
d := NOT (d OR s) | Yes |
bitwise.bbxnor | 0x0289 |
d := NOT (d XOR s) | Yes |
bitwise.bb_1010 | 0x028a |
d := NOT s | RESERVED |
bitwise.bbci | 0x028b |
d := d OR (NOT s) | Yes |
bitwise.bb_1100 | 0x028c |
d := NOT d | RESERVED |
bitwise.bbimp | 0x028d |
d := (NOT d) OR s | Yes |
bitwise.bbnand | 0x028e |
d := NOT (d AND s) | Yes |
bitwise.bb_1111 | 0x028f |
d := d OR (NOT d) | RESERVED |
bitwise.brtl | 0x0290 |
d := bitwise rotate left of d by s bits | Yes |
bitwise.brtr | 0x0291 |
d := bitwise rotate right of d by s bits | Yes |
bitwise.bshl0 | 0x0292 |
d := bitwise shift left of d by s bits, add unset (0) bits | Yes |
bitwise.bshl1 | 0x0293 |
d := bitwise shift left of d by s bits, add set (1) bits | Yes |
bitwise.bshr0 | 0x0294 |
d := bitwise shift right of d by s bits, add unset (0) bits | Yes |
bitwise.bshr1 | 0x0295 |
d := bitwise shift right of d by s bits, add set (1) bits | Yes |
bitwise.bshl | 0x0296 |
d := bitwise shift left of d by s bits, extend last bit | Yes |
bitwise.bshr | 0x0297 |
d := bitwise shift right of d by s bits, extend first bit | Yes |
Instruction | Value | Description | Implemented? |
---|---|---|---|
bitwise.bt_0000 | 0x02c0 |
d := d AND (NOT d) | RESERVED |
bitwise.btand | 0x02c1 |
d := s1 AND s2 | Yes |
bitwise.btabj | 0x02c2 |
d := s1 AND (NOT s2) | Yes |
bitwise.bt_0011 | 0x02c3 |
d := s1 | RESERVED |
bitwise.btcni | 0x02c4 |
same as bitwise.tabj | RESERVED |
bitwise.bt_0101 | 0x02c5 |
d := s2 | RESERVED |
bitwise.btxor | 0x02c6 |
d := s1 XOR s2 | Yes |
bitwise.btor | 0x02c7 |
d := s1 OR s2 | Yes |
bitwise.btbnor | 0x02c8 |
d := NOT (s1 OR s2) | Yes |
bitwise.btxnor | 0x02c9 |
d := NOT (s1 XOR s2) | Yes |
bitwise.bt_1010 | 0x02ca |
d := NOT s2 | RESERVED |
bitwise.btci | 0x02cb |
same as bitwise.btimp with operators swapped | RESERVED |
bitwise.bt_1100 | 0x02cc |
d := NOT s1 | RESERVED |
bitwise.btimp | 0x02cd |
d := s1 OR (NOT s2) | Yes |
bitwise.btnand | 0x02ce |
d := NOT (s1 AND s2) | Yes |
bitwise.bt_1111 | 0x02cf |
d := d OR (NOT d) | RESERVED |
bitwise.trtl | 0x02d0 |
d := bitwise rotate left of s1 by s2 bits | Yes |
bitwise.trtr | 0x02d1 |
d := bitwise rotate right of s1 by s2 bits | Yes |
bitwise.tshl0 | 0x02d2 |
d := bitwise shift left of s1 by s2 bits, add unset (0) bits | Yes |
bitwise.tshl1 | 0x02d3 |
d := bitwise shift left of s1 by s2 bits, add set (1) bits | Yes |
bitwise.tshr0 | 0x02d4 |
d := bitwise shift right of s1 by s2 bits, add unset (0) bits | Yes |
bitwise.tshr1 | 0x02d5 |
d := bitwise shift right of s1 by s2 bits, add set (1) bits | Yes |
bitwise.tshl | 0x02d6 |
d := bitwise shift left of s1 by s2 bits, extend last bit | Yes |
bitwise.tshr | 0x02d7 |
d := bitwise shift right of s1 by s2 bits, extend first bit | Yes |
For a short explanation on the format of this section, see here.
Note that most of the instructions only operate on uints. The result of all these expressions is either 1 (true) or 0 (false) and is written as an uint64 to the 64-bit register dreg previously occupied operand d.
Instruction | Value | Description | Input data types | Implemented? |
---|---|---|---|---|
logical.unot | 0x0300 |
dreg := ¬d | Only uint's | Yes |
Instruction | Value | Description | Input data types | Implemented? |
---|---|---|---|---|
logical.bnot | 0x0340 |
dreg := ¬s | Only uint's | Yes |
Instruction | Value | Description | Input data types | Implemented? |
---|---|---|---|---|
logical.lb_0000 | 0x0380 |
dreg := false | RESERVED | |
logical.lband | 0x0381 |
dreg := d ∧ s | Only uint's | Yes |
logical.lbabj | 0x0382 |
dreg := d ∧ ¬s | Only uint's | Yes |
logical.lb_0011 | 0x0383 |
dreg := d | RESERVED | |
logical.lbcni | 0x0384 |
dreg := ¬d ∧ s | Only uint's | Yes |
logical.lb_0101 | 0x0385 |
dreg := s | RESERVED | |
logical.lbxor | 0x0386 |
dreg := d ⊻ s | Only uint's | Yes |
logical.lbor | 0x0387 |
dreg := d ∨ s | Only uint's | Yes |
logical.lbbnor | 0x0388 |
dreg := ¬(d ∨ s) | Only uint's | Yes |
logical.lbxnor | 0x0389 |
dreg := ¬(d ⊻ s) | Only uint's | Yes |
logical.lb_1010 | 0x038a |
dreg := ¬s | RESERVED | |
logical.lbci | 0x038b |
dreg := d ∨ ¬s | Only uint's | Yes |
logical.lb_1100 | 0x038c |
dreg := ¬d | RESERVED | |
logical.lbimp | 0x038d |
dreg := ¬d ∨ s | Only uint's | Yes |
logical.lbnand | 0x038e |
dreg := ¬(d ∧ s) | Only uint's | Yes |
logical.lb_1111 | 0x038f |
dreg := true | RESERVED | |
logical.beq | 0x0390 |
dreg := d = s | All types | Yes |
logical.bne | 0x0391 |
dreg := d ≠ s | All types | Yes |
logical.blt | 0x0392 |
dreg := d < s | All types | Yes |
logical.ble | 0x0393 |
dreg := d ≤ s | All types | Yes |
logical.bge | 0x0394 |
dreg := d ≥ s | All types | Yes |
logical.bgt | 0x0395 |
dreg := d > s | All types | Yes |
Instruction | Value | Description | Input data types | Implemented? |
---|---|---|---|---|
logical.lt_0000 | 0x03c0 |
dreg := false | RESERVED | |
logical.ltand | 0x03c1 |
dreg := s1 ∧ s2 | Only uint's | Yes |
logical.ltabj | 0x03c2 |
dreg := s1 ∧ ¬s2 | Only uint's | Yes |
logical.lt_0011 | 0x03c3 |
dreg := s1 | RESERVED | |
logical.ltcni | 0x03c4 |
same as logical.tabj with operators swapped | RESERVED | |
logical.lt_0101 | 0x03c5 |
dreg := s2 | RESERVED | |
logical.ltxor | 0x03c6 |
dreg := s1 ⊻ s2 | Only uint's | Yes |
logical.ltor | 0x03c7 |
dreg := s1 ∨ s2 | Only uint's | Yes |
logical.ltbnor | 0x03c8 |
dreg := ¬(s1 ∨ s2) | Only uint's | Yes |
logical.ltxnor | 0x03c9 |
dreg := ¬(s1 ⊻ s2) | Only uint's | Yes |
logical.lt_1010 | 0x03ca |
dreg := ¬s2 | RESERVED | |
logical.ltci | 0x03cb |
same as logical.ltimp with operators swapped | RESERVED | |
logical.lt_1100 | 0x03cc |
dreg := ¬s1 | RESERVED | |
logical.ltimp | 0x03cd |
dreg := ¬s1 ∨ s2 | Only uint's | Yes |
logical.ltnand | 0x03ce |
dreg := ¬(s1 ∧ s2) | Only uint's | Yes |
logical.lt_1111 | 0x03cf |
dreg := true | RESERVED | |
logical.teq | 0x03d0 |
dreg := s1 = s2 | All types | Yes |
logical.tne | 0x03d1 |
dreg := s1 ≠ s2 | All types | Yes |
logical.tlt | 0x03d2 |
dreg := s1 < s2 | All types | Yes |
logical.tle | 0x03d3 |
dreg := s1 ≤ s2 | All types | Yes |
logical.tge | 0x03d4 |
dreg := s1 ≥ s2 | All types | Yes |
logical.tgt | 0x03d5 |
dreg := s1 > s2 | All types | Yes |
All jumps are relative.
Instruction | Value | Description | Implemented? |
---|---|---|---|
jump.jmp | 0x0400 |
unconditional jump | Yes |
jump.jz | 0x0401 |
jump if zero / false | Yes |
jump.jnz | 0x0402 |
jump if non-zero / true | Yes |
jump.dnjz | 0x0403 |
decrease and jump if zero / false | Yes |
jump.dnjnz | 0x0404 |
decrease and jump if non-zero / true | Yes |
jump.jeq | 0x0405 |
jump if equal | Yes |
jump.jne | 0x0406 |
jump if not equal | Yes |
jump.jge | 0x0407 |
jump if greater or equal | Yes |
jump.jgt | 0x0408 |
jump if greater | Yes |
jump.jle | 0x0409 |
jump if less or equal | Yes |
jump.jlt | 0x040a |
jump if less | Yes |
Jumps to the given relative address.
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 |
---|---|---|---|---|---|---|---|---|
00000100 |
00000000 |
OLBtarget | ........ |
........ |
........ |
........ |
........ |
target |
- OLBtarget - operand location (imm, reg or stack) of jump target.
Arguments:
- relative jump target (signed 64-bit integer).
Tests whether the second argument is zero (0 for integers or 0.0 for floating point numbers) and jumps to the relative address provided by the first argument if:
- for jump.jz the second argument tested as zero
- for jump.jnz the second argument tested as not zero
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 |
---|---|---|---|---|---|---|---|---|---|
00000100 |
000000TT |
OLBtarget | DTBcond | OLBcond | ........ |
........ |
........ |
target | cond |
TT
-01
for jump.jz and10
for jump.jnz.- OLBtarget - operand location (imm, reg or stack) of jump target.
- DTBcond - data type of argument to test (uint8, uint16, uint32 or uint64; int* types are covered by the respective uint* types because of two's complement).
- OLBcond - operand location (reg or stack) of argument to test.
Arguments:
- relative jump target (signed 64-bit integer).
- argument to test for being zero.
Decreases the second argument by one and tests whether the second argument is zero (0 for integers or 0.0 for floating point numbers) and jumps to the relative address provided by the first argument if:
- for jump.dnjz the first argument tested as zero
- for jump.dnjnz the first argument tested as not zero
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 |
---|---|---|---|---|---|---|---|---|---|
00000100 |
00000TTT |
OLBtarget | DTBcond | OLBcond | ........ |
........ |
........ |
target | cond |
TTT
-011
for jump.dnjz and100
for jump.dnjnz.- OLBtarget - operand location (imm, reg or stack) of jump target.
- DTBcond - data type of argument to test (uint8, uint16, uint32 or uint64; int* types are covered by the respective uint* types because of two's complement).
- OLBcond - operand location (reg or stack) of argument to test.
Arguments:
- relative jump target (signed 64-bit integer).
- argument to test for being zero.
jump.jeq (0x0405), jump.jne (0x0406), jump.jge (0x0407), jump.jgt (0x0408), jump.jle (0x0409), jump.jlt (0x040a)
Compares the second and third argument and jumps to the relative address provided by the first argument, if:
- for jump.je the arguments are equal
- for jump.jne the arguments are not equal
- for jump.jge the second argument is greater or equal than the third argument
- for jump.jgt the second argument is greater than the third argument
- for jump.jle the second argument is less or equal than the third argument
- for jump.jlt the second argument is less than the third argument
byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | byte 7 | arg 1 | arg 2 | arg 3 |
---|---|---|---|---|---|---|---|---|---|---|
00000100 |
0000TTTT |
OLBtarget | DTBops | OLBop1 | OLBop2 | ........ |
........ |
target | op1 | op2 |
TTTT
0101
for jump.je,0110
for jump.jne,0111
for jump.jge,1000
for jump.jgt,1001
for jump.jle,1010
for jump.jlt
- OLBtarget - operand location (imm, reg or stack) of jump target.
- DTBops - the data type for the arguments.
- OLBop1 - operand location (imm, reg or stack) for the second argument.
- OLBop2 - operand location (reg or stack) for the third argument.
Arguments:
- relative jump target (signed 64-bit integer).
- first comparison operand.
- second comparison operand.