SIRTX VM

Information on the SIRTX VM

The SIRTX VM is a part of SIRTX that is used to run code that not part of the image nor interpreted command line (see line command interpreter).

2929 (* 0) "SIRTX VM" ~>

VM v0 assembler syntax

The SIRTX VM supports code in its own optimised format. This special format natively supports the SIRTX API and therefor can be used to compile to a small binary size. The following outlines the syntax for the reference assembler.

The syntax follows many standard assembler patterns. However, opcodes may be different from other architecturs.

Each line of the file may contain comments. A comment starts with ;, //, or # and extends the rest of the line. If the line contains any directive there must be at least one space in between.

Every line may start with any number of whitespaces, end with them. Those are ignored. Between values there must be at least one whitespace or a comma or both.

Each directive may have zero or more values. A value can be of different types, depending on the directive. The first one is normally the destination, output, or target, and the second one the source or input.

It is possible to mark each opcode with a bang (!) to select autodie mode. This will set the autodie flag of the opcode (if any) or insert a autodie directive right after the opcode (if it has no autodie on its own).

Types

BOOL: Boolean
true or false.
INT: Integer
Each integer might be in format 123 for decimal, 0xabc for hex, 0123 for octal, or 0b0101 for binary. Also, each value can be prefixed with a + or - to make it relative. What it is relative to depends on the opcode.
STRING: String
A string is in form "..." or U+1234 (single character Unicode string). If in double quotes, backslashes are used to escape. \\ escapes single backslash, \0 escapes single 0-byte, \n escapes LF/new line (U+000A), \t escapes HT/horizontal tab (U+0009), \e escapes ESC/escape (U+001B). Also, the form \xAB can be used to escape any byte, note that in most cases those most form correct UTF-8 strings. For example U+00FC is correctly escaped \xC3\xBC, not \xFC.
LREG: Logical register
Logical registers must be given as rN with N being 0 to 7.
PREG: Physical registers
Physical registers are given by their full name, e.g. user7 or program_text.
REG: General register syntax
Most cases where a register is given, both a logical and a physical register name can be used. Unless automapping is active, physical names can often only used if they are currently mapped to a logical register. See map.
ID: Identifier
Identifiers are constants that are given using a type and a value seperated by a colon. Common are identifiers with a type of sni, e.g. sni:80. Only numerical values are currently supported. Some values from the raes space are however automatically converted to raen.
VAR: Variable
Variables are used to allow more symbolic programming. They can be set to any other kind of type from this list. Variable names contain a $, author defined ones start with it.

Index

Directives and opcodes

Below is a list of directives and opcodes. Note that directives and opcodes may generate a variable amount of actual code depending on their parameters and context.

.align

.align INT

Aligns the current location to at least INT bytes

Example
.align 8

.byte

.align INT [, INT [, INT [, ...]]]

Outputs the given bytes.

Example
.bytes 0x56, 0x4D

.cat

.cat STRING [, STRING [, STRING [, ...]]]

Includes files as-is into the output. No translation is performed when including file files. This is mostly useful to include large binary objects (blobs).

Example
.cat "help.txt"

.cold

.cold PREG [, PREG [, PREG [, ...]]]

Mark a given physical register as cold. Cold registers are unlikely to be used/referenced. This allows the assembler to optimise better.

Example
.cold arg

.endsection

.endsection

Ends a section started with .section

Example
.endsection

.hot

.hot PREG [, PREG [, PREG [, ...]]]

Marks a given physical register as hot. Hot registers are likely to be used frequently. This allows the assembler to optimise better.

Example
.hot user3, out

.include

.include STRING [, STRING [, STRING [, ...]]]

Includes source files and translates them. The .include directive does not create a new context of any kind. The files are included as if their content were in the main file.

Example
.include "lib.vmv0-asm"

.lukewarm

.lukewarm PREG [, PREG [, PREG [, ...]]]

Marks physical registers as lukewarm. This tells the assmeber that they are not specically hot nor cold. This is the default temperature for registers.

Example
.lukewarm user2, error

.map

.map LREG, PREG

Marks a logical register to be mapped to a physical register in the assembler's internal state without actually emitting an opcode. This is useful to set a correct state e.g. after a jump when the assembler can no longer know the actual mapping. To actually emit an opcode use map.

Example
.map r0 user0

.mine

.mine REG [, REG [, REG [, ...]]]

This marks registers as owned by the author. If a register is owned by the authour the assembler will not try to use it for automatic code generation (such as auto mapping). This is the default for registers.

Example
.mine r0, r1, r2, out

.org

.org INT

Seeks the output to the given position. If the value is relative moves relative to the current position

Example
.org 0x100

.popname

.popname VAR [, VAR [, VAR [, ...]]]

Pops a name of the name stack. See .pushname for details.

Example
.popname $x, $y

.pushname

.pushname VAR = VALUE [, VAR = VALUE [, VAR = VALUE [, ...]]]

Pushes name-value-pairs onto the name stack. Each name must start with a single $. The value can be any value (register, constant, ...) but another name. This mechanism can be used to assign more memorable names to registers or other constants. Those names can be used at any point. Names are pushed onto the stack, meaning if a name becomes pushed again it shadows the old content. The old content will be come visible again after .popname.

Example
.pushname $x = 5, $y = user7

quit

.quit

Quits the assembler, the rest of the file is ignored.

Example
.quit

.regmap_auto

.regmap_auto BOOL

Enables or disables automatic register mapping by the assembler. In order to work as expected some logical registers must be declared .yours. The number of registers that should be declared .yours depend on the code. A general starting point would be three or four.

Example
.regmap_auto true

.section

.section SECTIONTYPE

Starts a section of the given type. If another section is already open it first needs to be ended with .endsection.

Example
.section header

.theirs

.theirs REG [, REG [, REG [, ...]]]

Marks a register as owned not by the author nor the assambler. This can be useful if it is for example owned by a library or other module.

Example
.theirs deep, user4

.utf8

.utf8 STRING [, STRING, [, ...]]]

Writes the given strings as-is to the output. No final null-byte is inserted. However it can be manually added using \0. Any escaped characters within must be valid UTF-8.

Note that the source file must be in UTF-8 (it always must). If it is not, strange things might happen.

Example
.utf8 "Hello World\n", "Good afternoon!\0", U+1F981

.yours

.yours REG [, REG [, REG [, ...]]]

Marks a register as owned by the assembler. The assembler is free to use it however it sees fit. The author should avoid using those registers after being declared yours.

Example
.yours r4, r5, r6, r7

autodie

autodie

Dies with the error in error if error is not undef and not RoarAudio error code 0 (none).

Example
autodie

byte_transfer

byte_transfer! REG, REG, INT
byte_transfer REG, REG, INT

Transfers the given number of bytes from the source to the destination register. Optionally dies if the number of bytes actually transferred is less than the number of bytes requested. The transferred length is stored in out.

Example
byte_transfer! r0, r2, 15

control

control REG, REG
control REG, REG, REG
control REG, sni:NNN
control REG, sni:NNN, REG
control REG, sni:NNN, sni:MMM
control REG, sni:NNN, INT

Performs a control call on the target register. The second argument is the command, the third is in if any. arg is taken from the arg register. And out is always the out register.

Example
control! user0, sni:31, user1

die

die REG

Dies with the error in the given register. The value is stored in the error register.

Example
die r0

exit

exit REG

Exits the program (not just returns the function). Stores the value from the given register in out

Example
exit r0

jump

jump REG

Jumps to the given position.

Example
jump r0

magic

magic

Writes a format specific magic. Normally this is used as the very first opcode for format detection. If it is encountered anywhere in the code it is equivalent to a noop.

Example
magic

map

map LREG, PREG

Maps a logical register to a physical register.

Example
map r0 user0

move

move REG, REG

Moves a value from one register to another. The source register becomes undef by the move. To copy a value (like many assembler langauges do with mov) use replace.

Example
move r0, r1

noop

noop

Does nothing (no operation).

Example
noop

open

open REG, INT
open REG, ID

Opens a handle and stores the value in the given register

Example
open r0, 7
open user3, sni:80

replace

replace REG, REG

Replaces a value in a register with the value of another register. The source register is unchanged.

Example
replace r0, r2

return

return
return REG

Examples
return
return user4

rewind

rewind REG

Rewinds (seeks to the beginning) the handle in the given register.

Example
rewind r0

seek

seek REG, REG

Seeks the value in the left register to the positon in the right register.

Example
seek r0, r1

substr

substr REG, REG, INT, INT

Opens a substring of the input register in the output register. The offset and end is given. If the end is given as a relative integer it is understood as the length.

Example
substr rodata, program_text, 0x100, +13

tell

tell REG, REG

Stores the current position of the input register in the output register.

Example
tell r0, r3

transfer

transfer REG, REG

Transfers the subject/object from the source register to the target register.

Example
transfer r0, r2

undef

undef REG

Undefines the given register.

Example
undef r3
7422 (* 0) "VM v0 assembler syntax" ~>