VIUA-OPS(7) Viua VM Manual VIUA-OPS(7)
NAME viua-ops - Viua VM opcodes and instructions SYNOPSIS The following style is used in the instruction descriptions: ┌────────┬─────────────────┬──────────────────────────────────────────┐ │ symbol │ example │ meaning │ ├────────┼─────────────────┼──────────────────────────────────────────┤ │ op move │ an instruction │ ├────────┼─────────────────┼──────────────────────────────────────────┤ │ void │ │ the special register void │ ├────────┼─────────────────┼──────────────────────────────────────────┤ │ zero │ │ the special register zero │ ├────────┼─────────────────┼──────────────────────────────────────────┤ │ $reg │ $0.a │ a general-purpose register │ ├────────┼─────────────────┼──────────────────────────────────────────┤ │ $reg.x │ $1.p │ a general-purpose register in a specific │ │ │ │ register set │ ├────────┼─────────────────┼──────────────────────────────────────────┤ │ imm │ -1, 42u, 3.14 │ an immediate value of an arithmetic type │ ├────────┼─────────────────┼──────────────────────────────────────────┤ │ "str" │ "Hello, World!" │ an immediate value of a string type │ └────────┴─────────────────┴──────────────────────────────────────────┘ DESCRIPTION In Viua VM's ISA design the emphasis is put on reliability of the pro‐ grams, performance begin a secondary consideration--the guiding idea being that an answer delivered quickly is useless if it is wrong; or that a program that runs fast but crashes often is less useful than one that works correctly. ENVIRONMENT The instructions controlling the execution environment. noop No operation. The instruction does nothing at all. halt Halt the process. The instruction stops execution immediately. ebreak Environment break. By default dumps the state of the process. earithmeticwidth $dst|void, $src|zero earithmeticwidth $dst, void Manipulates the earw (arithmetic width) environment register. Stores its current value in $dst (if not void), and replaces it with the value from $src. If void is supplied instead of $src, the current value is not re‐ placed. If zero is supplied instead of $src, the current value is set to the default value. REGISTER MANAGEMENT These instructions allow direct management of register contents. copy $dst, $src Copy bits from $src to $dst, preserving $src. move $dst, $src move void, $src Move bits from $src to $dst, preserving $src. swap $dst, $src Swap bits between $src and $dst. delete $dst (pseudoinstruction) Erase the $dst register. ARITHMETIC Instructions marked with [.native] accept style flags; instructions not marked so do not accept style flags. The .native flag can be stated ex‐ plicitly, but is the implicit default in the absence of any other style flag. Style flags are explained in Arithmetic styles. Base arithmetic instructions For base arithmetic instructions the type of the output value depends on the type of the value in the $lhs register, and so neither zero nor void can be used for the $lhs operand. add[.native] $dst, $lhs, $rhs Add $rhs to $lhs, and store the output in $dst. sub[.native] $dst, $lhs, $rhs Subtract $rhs from $lhs, and store the output in $dst. mul[.native] $dst, $lhs, $rhs Multiply $lhs by $rhs, and store the output in $dst. div[.native] $dst, $lhs, $rhs Divide $lhs by $rhs, and store the output in $dst. mod dst, lhs, rhs Calculate ($lhs modulo $rhs), and store the output in $dst. Arithmetic with an immediate value These instructions are similar to the base arithmetic instructions, but instead of $rhs they take an immediate value; and they can take a zero as the $lhs value, while the base instructions could not. If zero is used instead of $lhs the output type is the same as the type of the immediate operand. For example: addiu $2.l, zero, 0 luiu $2.l, 0 creates an unsigned integer (note the u after the number zero), because the immediate operand is unsigned; while addi $2.l, zero, 0 lui $2.l, 0 creates a signed integer. The unsigned versions are not directly available to programmers, though, and must be accessed through the pseudoinstructions that infer the desired sign of the output from the sign of the immediate. A few examples to show the idea: addi $2.l, zero, 1 addi $2.l, zero, 1u In general, all of the above should be handed off to the assembler and the programmers should only rely on the li pseudoinstruction. lui $dst, immediate Create a signed integer with its highest 32 bits set to immediate, and store the result in $dst. Use addi or addiu to fill the lower 32 bits. luiu $dst, immediate Create an usigned integer with its highest 32 bits set to immedi‐ ate, and store the result in $dst. Use addi or addiu to fill the lower 32 bits. addi $dst, $lhs|zero, immediate Add immediate to $lhs (or zero), and store the output in $dst. subi $dst, $lhs|zero, immediate Subtract immediate from $lhs (or zero), and store the output in $dst. muli $dst, $lhs|zero, immediate Multiply $lhs (or zero) by immediate, and store the output in $dst. Using zero in place of $lhs does not make much sense, but is legal. divi $dst, $lhs|zero, immediate Divide $lhs (or zero) by immediate, and store the output in $dst. Using zero in place of $lhs does not make much sense, but is legal. Arithmetic styles Viua offers several styles of arithmetic: ┌────────────┬────────────────────────────────────────────────────────┐ │ style flag │ style description │ ├────────────┼────────────────────────────────────────────────────────┤ │ .native │ fast, works on floating point and integer types │ ├────────────┼────────────────────────────────────────────────────────┤ │ .wrap │ wraps on overflow, only works on integer types │ ├────────────┼────────────────────────────────────────────────────────┤ │ .trap │ traps on overflow, only works on integer types │ ├────────────┼────────────────────────────────────────────────────────┤ │ .saturate │ saturates on overflow, only works on integer types │ └────────────┴────────────────────────────────────────────────────────┘ A style flag can be appended to an arithmetic instruction to enable the specific style. For example, to execute saturating addition one would write: add.saturate $4.l, $2.l, $3.l Styles other than .native take into account the state of the earw envi‐ ronment register (manipulated using the earithmeticwidth instruction), and can be made to work on integers of specific width; eg, on 8-bit or 42-bit integers (the width does not have to be a multiple of 8). Floating-point constructors double $reg Use the unsigned integer in $reg as offset into the strings table, load a double, and store the result back in $reg. float $dst, immediate Store the immediate of type float in $dst. LOGIC Logic instructions. eq $dst, $lhs, $rhs Compare $lhs with $rhs; store 1 in $dst if both values are equal, store 0 otherwise. If the value in $rhs cannot be interpreted as a value of the type of $lhs the instruction aborts execution. Output is always a signed integer. lt $dst, $lhs, $rhs Compare $lhs less-than $rhs; store 1 in $dst if the comparison is true, store 0 otherwise. If the value in $rhs cannot be interpreted as a value of the type of $lhs the instruction aborts execution. Output is always a signed integer. gt $dst, $lhs, $rhs Compare $lhs greater-than $rhs; store 1 in $dst if the comparison is true, store 0 otherwise. If the value in $rhs cannot be interpreted as a value of the type of $lhs the instruction aborts execution. Output is always a signed integer. cmp $dst, $lhs, $rhs Compare $lhs with $rhs, and store result in $dst according to the following table: If the value in $rhs cannot be interpreted as a value of the type of $lhs the instruction aborts execution. Output is always a signed integer. ┌──────┬────────────────────────┐ │ $dst │ condition │ ├──────┼────────────────────────┤ │ -1 │ left-hand < right-hand │ ├──────┼────────────────────────┤ │ 0 │ left-hand = right-hand │ ├──────┼────────────────────────┤ │ 1 │ left-hand > right-hand │ └──────┴────────────────────────┘ and $dst, $lhs, $rhs Execute $lhs logical-and $rhs, and store the result in $dst. Inputs are interpreted as the bool type by the instruction. Output is always an unsigned integer. or $dst, $lhs, $rhs Execute $lhs logical-or $rhs, and store the result in $dst. Inputs are interpreted as the bool type by the instruction. Output is always an unsigned integer. not $dst, $src Store the logical negation of $src in $dst. Inputs are interpreted as the bool type by the instruction. Output is always an unsigned integer. BIT ARITHMETIC Bitwise operations require an unsigned integer value in their $src or $lhs operands, and will attempt to cast the value in $shift or $rhs to an unsigned integer. The instructions will abort execution unless both of the aforementioned conditions are satisified. NOTE: The earw register has no effect on the bit arithmetic instruc‐ tions; they always work on full-width values. Shifts bitshl $dst, $src, $shift Shift the value from $src left by $shift bits, and store the result in $dst. The result is filled with zeroes on the right. bitshr $dst, $src, $shift Shift the value from $src right by $shift bits, and store the re‐ sult in $dst. The result is filled with zeroes on the left. bitashr $dst, $src, $shift Shift the value from $src right by $shift bits, and store the re‐ sult in $dst. The result is filled with the highest bit of the in‐ put on the left; bitashr is the arithmetic right bit shift ie, it preserves the sign of the input. Rotations bitrol $dst, $src, $shift Rotate the value from $src to the left by $shift bits, and store the result in $dst. The bits "shifted out" from the input ie, its highest bits, are "shifted in" as the lowest bits of the output. For example, if bitrol was applied to 0b1100'0100 with a shift value of 2, the result would be 0b0001'0011. bitror $dst, $src, $shift Rotate the value from $src to the right by $shift bits, and store the result in $dst. The bits "shifted out" from the input ie, its lowest bits, are "shifted in" as the highest bits of the output. For example, if bitror was applied to 0b1100'0100 with a shift value of 2, the result would be 0b0011'0001. Masks bitand $dst, $lhs, $rhs Perform $lhs bitwise-and $rhs, and store the result in $dst. bitor $dst, $lhs, $rhs Perform $lhs bitwise-or $rhs, and store the result in $dst. bitxor $dst, $lhs, $rhs Perform $lhs bitwise-xor $rhs, and store the result in $dst. bitnot $dst, $src Invert the bits of $src, and store the result in $dst. CONTROL FLOW Control flow instructions. if $condition|void, $address Jump to $address if the $condition is true; perform an uncondi‐ tional jump if the operand is the void register. If the $condition operand is non-void, the operation will attempt to cast it as a boolean value. The operation aborts execution if this is not possible. See the description of the atxtp instruction to learn how to create a pointer usable as the $address operand. frame $argcount.a frame $argcount.l Allocate a frame. If the $argcount.a form is used ie, the count is taken as-if from the arguments register set, the number of allocated argument/para‐ meter registers (see the REGISTERS chapter of viua-isa(7) for the distinction) is equal to the argcount value, as if it were an imme‐ diate value. If the $argcount.l form is used ie, the count is taken from the lo‐ cal register set, the number of allocated argument/parameter regis‐ ters is equal to the value in $argcount.l register. That value must be an unsigned integer, or the operation will abort execution. call $retval|void, $address Use a previously allocated frame (see the description of the frame instruction above) to perform a call to the address. After control returns from the callee, the result of the call is stored in $retval (or discarded if the operand was void). If a non-void $retval operand is provided and the callee does re‐ turn a value, the operation aborts execution. Execution is aborted after the call finishes, not before. The callee receives a fresh local register set, and has no access to the caller's frame. The only fully open communication channel between the caller and the callee are the registers in the arguments/parameters register set, and the value moved from the callee to the caller with the re‐ turn instruction. See the MEMORY chapter of viua-isa(7) to learn about the restrictions on memory access between frames. See the description of the atxtp instruction to learn how to create a pointer usable as the $address operand. return $retval|void Return control to the caller frame. If the current frame is the only frame on the stack, the execution of the whole actor ends. If the current actor was the only one, the execution of the whole pro‐ gram ends. If the $retval operand is a non-void register, return the value contained in it. The operation aborts execution if a non-void register is supplied that is empty. Return nothing requires explicitly supplying the void register for the $retval operand. MEMORY The unit operand of memory instructions is not symbolic, but given as the number of bits the 1u value should be shifted left. Its legal range is 0 (a byte) to 7 (a duotrigesimal-word). The effective address is the result of the following calculation: $addr + (offset * (1u << unit)) For example, if the unit is 2 (a word), the offset 42 the effective ad‐ dress would be: $addr + (42 * (1u << 2)) = $addr + (42 * 4) = $addr + 168 For an extended discussion about loads and stores, refer to the M-FOR‐ MAT chapter of viua-isa(7). Constructors The "current module" used in the descriptions of constructor instruc‐ tions means the module at which the program counter is pointing. This can usually be thought of as a static-linked ELF emitted by an in‐ vocation of viua-ld(1). In case of dynamic linking, the .got must be used to get pointers to objects in other modules. arodp $dst, offset Create a pointer pointing at offset bytes into the .rodata section of the current module, and store the result in $dst. If the offset is invalid the operation aborts execution. atxtp $dst, offset Create a pointer pointing at offset bytes into the .text section of the current module, and store the result in $dst. If the offset is invalid the operation aborts execution. atom $reg Use the unsigned integer in $reg as offset into the strings table, load an atom, and store the result back in $reg. cast $reg, type Interpret an undefined value contained in $reg as type. Refer to chapter FUNDAMENTAL TYPES of viua-isa(7) to learn what symbols are available for the type operand. Loads and stores For lm and sm instructions only unit values up to 4 (a quad-word) are useful, since Viua registers can only hold 128 bits. lm unit, $reg, $addr, offset Load a unit of memory eg, a word, from the effective address into $reg. sm unit, $reg, $addr, offset Store a unit of memory eg, a word, from $reg at the effective ad‐ dress. Allocation For aa and ad instructions all unit values are useful. aa unit, $ptr, $count Allocate an amount of automatic (stack) memory equal to $count times unit. ad unit, $ptr, $count (!!! NOT IMPLEMENTED !!!) Allocate an amount of dynamic (heap) memory equal to $count times unit. PSEUDOINSTRUCTIONS atom $dst, atom Store the atom in $dst. double $dst, immediate Store the immediate of type double in $dst. lb $reg, $addr, offset lh $reg, $addr, offset lw $reg, $addr, offset ld $reg, $addr, offset lq $reg, $addr, offset Load a value from memory and into $reg. See discussion of the lm instruction for more detailed information. sb $reg, $addr, offset sh $reg, $addr, offset sw $reg, $addr, offset sd $reg, $addr, offset sq $reg, $addr, offset Store a value from $reg in memory. See discussion of the lm in‐ struction for more detailed information. amba $ptr, $size, 0 amha $ptr, $size, 0 amwa $ptr, $size, 0 amda $ptr, $size, 0 amqa $ptr, $size, 0 amoa $ptr, $size, 0 amxa $ptr, $size, 0 amua $ptr, $size, 0 Allocate automatic memory. See discussion of the aa instruction for more detailed information. call $retval|void, symbol Call a symbol defined by a .symbol directive. See discussion of the call instruction for more detailed information. if $condition, label Jump to a label defined by a .label directive. See discussion of the if instruction for more detailed information. li $reg, immediate Load an immediate integer value into $reg. The immediate must be representable on 64 bits, and its signedness is inferred by the as‐ sembler. By default, signed integers are loaded: li $2.l, 1 Use the u suffix may be used to force unsigned integers: li $3.l, 1u Use the special -1u case to load maximal value of an unsigned inte‐ ger: li #4.l, -1u SEE ALSO viua-asm(5), viua-isa(7). Patterson, David A. and Waterman, Andrew. The RISC-V Reader. Strawberry Canyon LLC, 2017. ISBN 978-09-9924-911-6 Web site ‹https://viuavm.org› Source code repository ‹https://git.sr.ht/~maelkum/viuavmVIUA VM Part of the viua(1) toolchain.