These are the possible valid instructions in LMNT and their meaning. Any arguments not mentioned in an instruction's definition or described as reserved are unused by that function and can be assumed to contain an indeterminate value.
Note that these are currently subject to change at any time.
- Scalar (S): a single value occupying one stack location
- Vector (V): a 4-wide array of values occupying four contiguous stack locations
- Immediate (I): a value encoded in the instruction, either as an integer (II) or a binary value (IB)
- Reference (R): a single value occupying one stack location whose value (cast to integer) is another location, either on the stack or in another table
- Stack Loc: an integer representing a location on the function's stack
- Immediate: a value encoded into the argument itself
- Stack Ref: an integer location on the stack, the value contained in which (cast to integer) is the stack location to act upon
- Data Ref: an integer location on the stack, the value contained in which (cast to integer) is the index to act upon in a separately-specified data section
- Def Pointer: an integer offset into the archive's defs table, representing a function
- Code Index: an integer index into the current function's code entry, effectively pointing to an instruction
These assumptions apply to all instructions unless otherwise noted.
- Safety: in an archive which has passed validation, instructions cannot cause access violations or otherwise fail.
- Halting: the program can be assumed to halt in a predictable amount of time.
- Dependencies: instructions are not directly dependent on each other.
- Aliasing: input and output stack locations may be aliased. For vector operations, the aliasing must be aligned - i.e. the output location must be the same as the input location(s) or they must not overlap at all.
- Rounding: all rounding uses default IEEE754 behaviour.
- NaNs: any operation involving one or more NaNs will produce a result of NaN. For memberwise vector operations, other lanes of the operation must not be affected.
Takes no action.
Implementations may choose to elide this operation when executing, but must respect its position in the function (e.g. when calculating branch targets).
Returns from the current function immediately.
Takes a scalar value from the input stack location and writes it to another stack location ("move" in assembly parlance).
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Stack location to read value from |
3 | Output | Stack Loc | Scalar | Stack location to write value to |
stack[arg3] = stack[arg1]
Takes a vector value from a 4-wide set of input stack locations and writes it to another 4-wide set of stack locations ("move" in assembly parlance).
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First stack location to read value from (read occurs from arg1+0..arg1+3 ) |
3 | Output | Stack Loc | Vector | First stack location to write value to (write occurs from arg3+0..arg3+3 ) |
for (i=0..3)
stack[arg3+i] = stack[arg1+i]
Takes a vector value from a single stack location and broadcasts it to a 4-wide set of stack locations.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Stack location to read value from |
3 | Output | Stack Loc | Vector | Stack location to write value to |
for (i=0..3)
stack[arg3+i] = stack[arg1]
Takes a binary-encoded value and writes that value to a stack location.
Note: use of this instruction requires that sizeof(arg1) + sizeof(arg2) == sizeof(lmnt_value)
.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Immediate | LO(lmnt_value) | Low bits of encoded raw value |
2 | Input | Immediate | HI(lmnt_value) | High bits of encoded raw value |
3 | Output | Stack Loc | Scalar | Stack location to write to |
stack[arg3] = bit_cast(arg1 | (arg2 << sizeof(arg1)))
Takes a binary-encoded value and writes that value to a 4-wide set of stack locations.
Note: use of this instruction requires that sizeof(arg1) + sizeof(arg2) == sizeof(lmnt_value)
.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Immediate | LO(lmnt_value) | Low bits of encoded raw value |
2 | Input | Immediate | HI(lmnt_value) | High bits of encoded raw value |
3 | Output | Stack Loc | Vector | First stack location to write to |
for (i=0..3)
stack[arg3+i] = bit_cast(arg1 | (arg2 << sizeof(arg1)))
Reads a constant from the specified data section and index and writes it to a stack location.
This instruction has a limit on the indexes accessible to it, due to the argument size. DLOADIRS
can be used to read from the end of larger sections.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Immediate | UInt16 | Index of data section to read from |
2 | Input | Immediate | UInt16 | Index of data element in section to read |
3 | Output | Stack Loc | Scalar | Stack location to write value to |
stack[arg3] = data[arg1][arg2]
Reads a 4-wide vector of constants from the specified data section and index and writes them to four stack locations.
This instruction has a limit on the indexes accessible to it, due to the argument size. DLOADIRV
can be used to read from the end of larger sections.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Immediate | UInt16 | Index of data section to read from |
2 | Input | Immediate | UInt16 | Index of data element in section to read |
3 | Output | Stack Loc | Vector | First stack location to write value to |
for (i=0..3)
stack[arg3+i] = data[arg1][arg2+i]
Reads a constant from the specified data section, using an index sourced from a stack location, and writes it to a stack location.
Safety: this instruction allows for dynamically choosing a location to read from in a data section; as a result it is possible for this instruction to cause an access violation error (which will result in the function immediately returning with the LMNT_ERROR_ACCESS_VIOLATION
code).
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Immediate | UInt16 | Index of data section to read from |
2 | Input | Data Ref | Scalar | Stack location to read data index from |
3 | Output | Stack Loc | Scalar | Stack location to write value to |
data_index = (int32)(stack[arg2])
if (data_index < 0 || data_index + 1 > len(data[arg1])) error(LMNT_ERROR_ACCESS_VIOLATION)
stack[arg3] = data[arg1][data_index]
Reads a 4-wide vector of constants from the specified data section and index and writes them to four stack locations.
Safety: this instruction allows for dynamically choosing a location to read from in a data section; as a result it is possible for this instruction to cause an access violation error (which will result in the function immediately returning with the LMNT_ERROR_ACCESS_VIOLATION
code).
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Immediate | UInt16 | Index of data section to read from |
2 | Input | Data Ref | UInt16 | Stack location to read first data index from |
3 | Output | Stack Loc | Vector | First stack location to write value to |
data_index = (int32)(stack[arg2])
if (data_index < 0 || data_index + 4 > len(data[arg1])) error(LMNT_ERROR_ACCESS_VIOLATION)
for (i=0..3)
stack[arg3+i] = data[arg1][data_index+i]
Writes the length, in entries, of the specified data section to a stack location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Immediate | UInt16 | Index of data section to query |
3 | Output | Stack Loc | Scalar | Stack location to write value to |
stack[arg3] = (lmnt_value)(len(data[arg1]))
Adds two scalar values and writes the result to a third scalar.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of first value to operate on |
2 | Input | Stack Loc | Scalar | Location of second value to operate on |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = stack[arg1] + stack[arg2]
Memberwise adds two vector values and writes the result to a third vector.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first values to operate on |
2 | Input | Stack Loc | Vector | First location of second values to operate on |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = stack[arg1+i] + stack[arg2+i]
Subtracts one scalar value from another and writes the result to a third scalar.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of first value to operate on |
2 | Input | Stack Loc | Scalar | Location of second value to operate on |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = stack[arg1] - stack[arg2]
Memberwise subtracts two vector values and writes the result to a third vector.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first values to operate on |
2 | Input | Stack Loc | Vector | First location of second values to operate on |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = stack[arg1+i] - stack[arg2+i]
Multiplies one scalar value with another and writes the result to a third scalar.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of first value to operate on |
2 | Input | Stack Loc | Scalar | Location of second value to operate on |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = stack[arg1] * stack[arg2]
Memberwise multiplies two vector values and writes the result to a third vector.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first values to operate on |
2 | Input | Stack Loc | Vector | First location of second values to operate on |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = stack[arg1+i] * stack[arg2+i]
Divides one scalar value by another and writes the result to a third scalar.
Division by zero results in the appropriate infinity for floating-point value types, and is undefined for integer value types.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of first value to operate on |
2 | Input | Stack Loc | Scalar | Location of second value to operate on |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = stack[arg1] / stack[arg2]
Memberwise divides two vector values and writes the result to a third vector.
Division by zero results in the appropriate infinity for floating-point value types, and is undefined for integer value types. Occurrences of this must have no impact on the other lanes of the operation.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first values to operate on |
2 | Input | Stack Loc | Vector | First location of second values to operate on |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = stack[arg1+i] / stack[arg2+i]
Performs a remainder operation with two scalar values and writes the result to a third scalar.
Note that different programming languages have differing interpretations of modulo or remainder; the definition in LMNT is as below.
If the denominator value is 0
, the result will be NaN
.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of first value to operate on |
2 | Input | Stack Loc | Scalar | Location of second value to operate on |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = stack[arg1] - floor(stack[arg1] / stack[arg2]) * stack[arg2]
Memberwise performs a remainder operation on two vector values and writes the result to a third vector.
Note that different programming languages have differing interpretations of modulo and remainder; the definition in LMNT is as below.
If a denominator value is 0
, the result will be NaN
. Occurrences of this must have no impact on the other lanes of the operation.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first values to operate on |
2 | Input | Stack Loc | Vector | First location of second values to operate on |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = stack[arg1+i] - floor(stack[arg1+i] / stack[arg2+i]) * stack[arg2+i]
Performs the sine trigonometric operation on the input value and writes the result to another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the input to the sine operation |
3 | Output | Stack Loc | Scalar | Stack location to write the result to |
stack[arg3] = sin(stack[arg1])
Performs the cosine trigonometric operation on the input value and writes the result to another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the input to the cosine operation |
3 | Output | Stack Loc | Scalar | Stack location to write the result to |
stack[arg3] = cos(stack[arg1])
Performs the tangent trigonometric operation on the input value and writes the result to another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the input to the tangent operation |
3 | Output | Stack Loc | Scalar | Stack location to write the result to |
stack[arg3] = tan(stack[arg1])
Performs the arcsine trigonometric operation on the input value and writes the result to another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the input to the arcsine operation |
3 | Output | Stack Loc | Scalar | Stack location to write the result to |
stack[arg3] = asin(stack[arg1])
Performs the arccosine trigonometric operation on the input value and writes the result to another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the input to the arccosine operation |
3 | Output | Stack Loc | Scalar | Stack location to write the result to |
stack[arg3] = acos(stack[arg1])
Performs the arctangent trigonometric operation on the input value and writes the result to another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the input to the arctangent operation |
3 | Output | Stack Loc | Scalar | Stack location to write the result to |
stack[arg3] = atan(stack[arg1])
Performs the two-argument arctangent trigonometric operation on the input value and writes the result to another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the "y" input to the arctangent operation |
1 | Input | Stack Loc | Scalar | Location of the "x" input to the arctangent operation |
3 | Output | Stack Loc | Scalar | Stack location to write the result to |
stack[arg3] = atan2(stack[arg1], stack[arg2])
Performs both sine and cosine calculations as a single operation. If both are required, some implementations may be able to use optimised routines to perform the operations faster.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the input to the sine/cosine operations |
2 | Output | Stack Loc | Scalar | Stack location to write the sine result to |
3 | Output | Stack Loc | Scalar | Stack location to write the cosine result to |
stack[arg2], stack[arg3] = sincos(stack[arg1])
Takes a value to the power of another value, and writes the result.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of base value |
2 | Input | Stack Loc | Scalar | Location of exponent value |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = pow(stack[arg1], stack[arg2])
Memberwise performs the power (exponent) operation on a vector of values by another vector, and writes the result to another vector.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of base values |
2 | Input | Stack Loc | Vector | First location of exponent values |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = pow(stack[arg1+i], stack[arg2+i])
Memberwise performs the power (exponent) operation on a vector of values by a scalar, and writes the result to another vector.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of base values |
2 | Input | Stack Loc | Scalar | Location of exponent value |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = pow(stack[arg1+i], stack[arg2])
Performs a square root operation on a value, and stores it in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of input value |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = sqrt(stack[arg1])
Performs a square root operation on each value in a 4-wide vector, and stores the results in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of input values |
3 | Output | Stack Loc | Vector | First stack location to write result to |
for (i=0..3)
stack[arg3+i] = sqrt(stack[arg1+i])
Takes the natural logarithm of an input value, and writes the result.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the logarithm input |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = ln(stack[arg1])
Takes the base-2 logarithm of an input value, and writes the result.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the logarithm input |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = log2(stack[arg1])
Takes the base-10 logarithm of an input value, and writes the result.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the logarithm input |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = log10(stack[arg1])
Calculates the absolute value of a value and stores the result in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of input value |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = abs(stack[arg1])
Calculates the absolute values of each of a 4-wide vector and stores the result in another vector.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of input values |
3 | Output | Stack Loc | Vector | First stack location to write result to |
for (i=0..3)
stack[arg3+i] = abs(stack[arg1+i])
Calculates the sum of a 4-wide vector of values, and stores the result as a scalar in another location.
- NaNs: if any of the input values are NaN, the result will be NaN.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of input values |
3 | Output | Stack Loc | Scalar | Stack location to write the sum to |
stack[arg3] = stack[arg1+0] + stack[arg1+1] + stack[arg1+2] + stack[arg1+3]
Given two values, stores the lower (more negative) of the two values in another location.
NaNs: the behaviour of this function if either operation is a NaN is undefined.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of first input |
2 | Input | Stack Loc | Scalar | Location of second input |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = min(stack[arg1], stack[arg2])
Given two vectors, stores the lower (more negative) of each lane's values in another location.
NaNs: the behaviour of a lane of this function is undefined if either input is NaN; other lanes must not be affected if this occurs.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first input |
2 | Input | Stack Loc | Vector | First location of second input |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = min(stack[arg1+i], stack[arg2+i])
Given two values, stores the higher (more positive) of the two values in another location.
NaNs: the behaviour of this function if either operation is a NaN is undefined.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of first input |
2 | Input | Stack Loc | Scalar | Location of second input |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = max(stack[arg1], stack[arg2])
Given two vectors, stores the higher (more positive) of each lane's values in another location.
NaNs: the behaviour of a lane of this function is undefined if either input is NaN; other lanes must not be affected if this occurs.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first input |
2 | Input | Stack Loc | Vector | First location of second input |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = max(stack[arg1+i], stack[arg2+i])
Given a vector and a scalar, stores the lower (more negative) of each lane of the vector and the scalar.
NaNs: the behaviour of a lane of this function is undefined if either input in that lane is NaN; other lanes must not be affected if this occurs.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first input |
2 | Input | Stack Loc | Scalar | Location of second input |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = min(stack[arg1+i], stack[arg2])
Given a vector and a scalar, stores the higher (more positive) of each lane of the vector and the scalar.
NaNs: the behaviour of a lane of this function is undefined if either input in that lane is NaN; other lanes must not be affected if this occurs.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of first input |
2 | Input | Stack Loc | Scalar | Location of second input |
3 | Output | Stack Loc | Vector | First stack location to write results to |
for (i=0..3)
stack[arg3+i] = max(stack[arg1+i], stack[arg2])
Takes the nearest integer below the given value, and stores it in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of input value |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = floor(stack[arg1])
Takes the nearest integer below the given value for each lane of a 4-wide vector, and stores the results in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of input values |
3 | Output | Stack Loc | Vector | First stack location to write result to |
for (i=0..3)
stack[arg3+i] = floor(stack[arg1+i])
Takes the closest integer to the given value, and stores it in another location.
Rounding: in the event of a tie (e.g. exactly X.5
) the result must be rounded to even.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of input value |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = round(stack[arg1])
Note: the C functions round
et al do not round to even on a tie; rint
and nearbyint
do when using the default rounding mode.
Takes the closest integer to the given value for each lane of a 4-wide vector, and stores the results in another location.
Rounding: in the event of a tie (e.g. exactly X.5
) the result must be rounded to even.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of input values |
3 | Output | Stack Loc | Vector | First stack location to write result to |
for (i=0..3)
stack[arg3+i] = round(stack[arg1+i])
Note: the C functions round
et al do not round to even on a tie; rint
and nearbyint
do when using the default rounding mode.
Takes the nearest integer above the given value, and stores it in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of input value |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = ceil(stack[arg1])
Takes the nearest integer above the given value for each lane of a 4-wide vector, and stores the results in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of input values |
3 | Output | Stack Loc | Vector | First stack location to write result to |
for (i=0..3)
stack[arg3+i] = ceil(stack[arg1+i])
Takes the next integer towards zero to the given value, and stores it in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of input value |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
stack[arg3] = trunc(stack[arg1])
Takes the next integer towards zero to the given value for each lane of a 4-wide vector, and stores the results in another location.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Vector | First location of input values |
3 | Output | Stack Loc | Vector | First stack location to write result to |
for (i=0..3)
stack[arg3+i] = trunc(stack[arg1+i])
Reads a value from the stack, adds a constant to it, and then reads from that stack index, writing it to another stack location.
Safety: this instruction allows for dynamically choosing a stack location to read from; as a result it is possible for this instruction to cause an access violation error (which will result in the function immediately returning with the LMNT_ERROR_ACCESS_VIOLATION
code).
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Ref | Scalar | Stack location of stack value representing index to read |
2 | Input | Immediate | UInt16 | Constant to add to retrieved index |
3 | Output | Stack Loc | Scalar | Stack location to write result to |
read_index = (int32)(stack[arg1]) + arg2
if (read_index < 0 || read_index >= len(stack)) error(LMNT_ERROR_ACCESS_VIOLATION)
stack[arg3] = stack[read_index]
Reads a value from the stack, adds a constant to it, and then reads from that stack index; then reads the output index from the stack, before writing it to that retrieved location.
Safety: this instruction allows for dynamically choosing a stack location to read from and write to; as a result it is possible for this instruction to cause an access violation error (which will result in the function immediately returning with the LMNT_ERROR_ACCESS_VIOLATION
code).
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Ref | Scalar | Stack location of stack value representing index to read |
2 | Input | Immediate | UInt16 | Constant to add to retrieved index |
3 | Input | Stack Ref | Scalar | Stack location of stack value representing index to store result |
read_index = (int32)(stack[arg1]) + arg2
write_index = (int32)(stack[arg3])
if (read_index < 0 || read_index >= len(stack)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (write_index < 0 || write_index >= len(stack)) error(LMNT_ERROR_ACCESS_VIOLATION)
stack[write_index] = stack[read_index]
Unconditionally branch to the given instruction; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
goto instructions[target]
Branch to the given instruction if the test argument is zero; the branch target is specified by its absolute index within the current function. Negative zero (-0.0
) is counted as zero.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
NaNs: if the test argument is NaN, the branch is not taken.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to test |
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (stack[arg1] == 0.0)
goto instructions[target]
Branch to the given instruction if the test argument is non-zero; the branch target is specified by its absolute index within the current function. Negative zero (-0.0
) is counted as zero.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
NaNs: if the test argument is NaN, the branch is not taken.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to test |
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (stack[arg1] != 0.0)
goto instructions[target]
Branch to the given instruction if the test argument is positive; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
NaNs: the branch will be taken if the test argument is a positive NaN.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to test |
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (signbit(stack[arg1]) == 0)
goto instructions[target]
Branch to the given instruction if the test argument is negative; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
NaNs: the branch will be taken if the test argument is a negative NaN.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to test |
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (signbit(stack[arg1]) == 1)
goto instructions[target]
Branch to the given instruction if the test argument is NaN
; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to test |
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (isnan(stack[arg1]))
goto instructions[target]
Compares the two specified inputs, and stores the result in an internal set of flags.
The flags stored are:
EQ
(equal): the first argument compares equal to the second argumentLT
(less-than): the first argument compares less than the second argumentGT
(greater-than): the first argument compares greater than the second argumentUN
(unordered): the comparison is unordered (i.e. at least one argument wasNaN
)
NaNs: if one or both arguments are NaN
, then UN
will be set and no other flags will.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the first input to compare |
2 | Input | Stack Loc | Scalar | Location of the second input to compare |
flags.EQ = (stack[arg1] == stack[arg2])
flags.LT = (stack[arg1] < stack[arg2])
flags.GT = (stack[arg1] > stack[arg2])
flags.UN = (isnan(stack[arg1]) || isnan(stack[arg2]))
Compares the specified input against zero, and stores the result in an internal set of flags.
The flags stored are:
EQ
(equal): the first argument compares equal to the second argumentLT
(less-than): the first argument compares less than the second argumentGT
(greater-than): the first argument compares greater than the second argumentUN
(unordered): the comparison is unordered (i.e. at least one argument wasNaN
)
NaNs: if one or both arguments are NaN
, then UN
will be set and no other flags will.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of the first input to compare |
flags.EQ = (stack[arg1] == 0.0)
flags.LT = (stack[arg1] < 0.0)
flags.GT = (stack[arg1] > 0.0)
flags.UN = (isnan(stack[arg1]))
Branch to the target instruction if the last CMP
or CMPZ
instruction produced an equal-to result; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (flags.EQ)
goto instructions[target]
Branch to the target instruction if the last CMP
or CMPZ
instruction produced a not-equal result; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
NaNs: if one or both of the prior comparison's arguments are NaN
, the branch will be taken (since EQ
will not be set)
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (!flags.EQ)
goto instructions[target]
Branch to the target instruction if the last CMP
or CMPZ
instruction produced a less-than result; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (flags.LT)
goto instructions[target]
Branch to the target instruction if the last CMP
or CMPZ
instruction produced a less-than or equal-to result; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (flags.LT || flags.EQ)
goto instructions[target]
Branch to the target instruction if the last CMP
or CMPZ
instruction produced a greater-than result; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (flags.GT)
goto instructions[target]
Branch to the target instruction if the last CMP
or CMPZ
instruction produced a greater-than or equal-to result; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (flags.GT || flags.EQ)
goto instructions[target]
Branch to the target instruction if the last CMP
or CMPZ
instruction produced an unordered result; the branch target is specified by its absolute index within the current function.
Note that the branch target is permitted to be equal to the instruction count (i.e. "one past the end"); this is effectively equivalent to a RETURN
.
Halting: if a branch's target is not later than the branch instruction in the function, halting cannot be guaranteed and execution time cannot be easily predicted.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Reserved | ||
2 | Input | Code Index | LO(UInt32) | Low half of the target instruction index |
3 | Input | Code Index | HI(UInt32) | High half of the target instruction index |
target = (arg2 | (arg3 << sizeof(arg2)))
if (target > len(instructions)) error(LMNT_ERROR_ACCESS_VIOLATION)
if (flags.UN)
goto instructions[target]
Assign to the target stack location one of two values, depending on whether the last CMP
or CMPZ
instruction produced an equal result.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to assign if comparison is true |
2 | Input | Stack Loc | Scalar | Location of value to assign if comparison is false |
3 | Output | Stack Loc | Scalar | Stack location to assign the result to |
if (flags.EQ)
stack[arg3] = stack[arg1]
else
stack[arg3] = stack[arg2]
Assign to the target stack location one of two values, depending on whether the last CMP
or CMPZ
instruction produced a not-equal result.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to assign if comparison is true |
2 | Input | Stack Loc | Scalar | Location of value to assign if comparison is false |
3 | Output | Stack Loc | Scalar | Stack location to assign the result to |
if (!flags.EQ)
stack[arg3] = stack[arg1]
else
stack[arg3] = stack[arg2]
Assign to the target stack location one of two values, depending on whether the last CMP
or CMPZ
instruction produced a less-than result.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to assign if comparison is true |
2 | Input | Stack Loc | Scalar | Location of value to assign if comparison is false |
3 | Output | Stack Loc | Scalar | Stack location to assign the result to |
if (flags.LT)
stack[arg3] = stack[arg1]
else
stack[arg3] = stack[arg2]
Assign to the target stack location one of two values, depending on whether the last CMP
or CMPZ
instruction produced a less-than or equal result.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to assign if comparison is true |
2 | Input | Stack Loc | Scalar | Location of value to assign if comparison is false |
3 | Output | Stack Loc | Scalar | Stack location to assign the result to |
if (flags.LT || flags.EQ)
stack[arg3] = stack[arg1]
else
stack[arg3] = stack[arg2]
Assign to the target stack location one of two values, depending on whether the last CMP
or CMPZ
instruction produced a greater-than result.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to assign if comparison is true |
2 | Input | Stack Loc | Scalar | Location of value to assign if comparison is false |
3 | Input | Stack Loc | Scalar | Stack location to assign the result to |
if (flags.GT)
stack[arg3] = stack[arg1]
else
stack[arg3] = stack[arg2]
Assign to the target stack location one of two values, depending on whether the last CMP
or CMPZ
instruction produced a greater-than or equal result.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to assign if comparison is true |
2 | Input | Stack Loc | Scalar | Location of value to assign if comparison is false |
3 | Input | Stack Loc | Scalar | Stack location to assign the result to |
if (flags.GT || flags.EQ)
stack[arg3] = stack[arg1]
else
stack[arg3] = stack[arg2]
Assign to the target stack location one of two values, depending on whether the last CMP
or CMPZ
instruction produced an unordered result.
Dependencies: this instruction is only guaranteed to perform as expected if it is immediately preceded by a comparison function (CMP
or CMPZ
), or if the only intervening instructions are other BRANCHCxx
or ASSIGNCxx
instructions.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Stack Loc | Scalar | Location of value to assign if comparison is true |
2 | Input | Stack Loc | Scalar | Location of value to assign if comparison is false |
3 | Input | Stack Loc | Scalar | Stack location to assign the result to |
if (flags.UN)
stack[arg3] = stack[arg1]
else
stack[arg3] = stack[arg2]
Calls out to a runtime-defined function, specified via an address into the archive's defs
table. This allows specific runtimes to add functionality not normally available using LMNT, at the cost of non-portability.
Any archive containing an external def with a name and signature which does not match those known to the runtime will also fail to validate. This mechanism can also be disabled entirely at compile-time; in this instance, any archive containing any defs marked as external will fail to validate.
Summarily: this functionality is discouraged in most cases, but can allow for a wider range of functionality without otherwise compromising the guarantees of the system.
Halting: since this instruction calls out to platform-controlled code, there is no guarantee that said code will halt and thus the same is true of this instruction.
Arg | Direction | Type | Size | Meaning |
---|---|---|---|---|
1 | Input | Def Pointer | LO(UInt32) | Low half of the extcall's def address |
2 | Input | Def Pointer | HI(UInt32) | High half of the extcall's def address |
3 | Output | Stack Loc | Scalar | First stack location of the arguments + return values |
def_address = (arg1 | (arg2 << sizeof(arg1)))
def = find_extern(def_address)
if (!def.function) error(LMNT_ERROR_NOT_FOUND)
args = stack + arg3
rvals = stack + arg3 + def.args_count
def.function(args, def.args_count, rvals, def.rvals_count)