Operands

From Mill Computing Wiki
Jump to: navigation, search

Pretty much all operations take values from the belt as parameters. Those are the operands. There are also other kinds of arguments like immediate values, or special Registers, but the belt operands are the data values you care about and operate with in your programs. The belt can hold any kind of supported bit pattern and the connected Metadata like byte width and scalarity. But not all value types make sense for all operations. There are a lot of operations that fail when they encounter inappropriate data. And the type of the result values very often is completely dependent on the type of the input operands.

For this reason there is a matrix connected to each operation that defines which kinds of operands are accepted and which kinds of result they produce. The Compiler and [Specializer]] are aware of those restrictions and can act accordingly. And the hardware generates the appropriate NaR when it encounters inappropriate operands for some reason.

The Operand Matrix

Operand Value Types

The semantic interpretation of the bit patterns in a belt value is completely up to the operation itself. This is not relevant to the belt value type maintained in the Metadata. The only thing that matters is the byte width and the scalarity. Belt values can be 1, 2, 4 or 8 bytes wide on all Cores and also 16 on the higher end hardware. They can be a scalar value or a vector value. The vector size is fixed for a specific core, if a value is a vector it has always the same amount of elements of the given byte width. This means there are 10 possible operand types, the 5 scalar byte widths and the 5 vectored variants. Eight of those are available on all cores.

The Matrix

The common case for all operations is 2 operands one result. This means the matrix of possible operands and results for each operation is a 10×10 matrix for the operand types with the result types at the appropriate coordinates.
This is even expanded to operations with only one operand, where the one operand is used for both dimensions, and the result are at the diagonal, and for ganged operations with more operands, which either don't care about the values or the first two operands are enough.

The Abbreviated Matrix

This full 10×10 matrix is of course a little bit unwieldy to display for documentation, for this reason it is usually referred to by symbolic name, which usually is the name of the operation this matrix was initially created for. Often this name doesn't really explain anything though, so for purely documentary reasons there is an abbreviated format to show which kinds of operands are allowed/accepted and which kinds of results they produce.
For the simpler cases this should be pretty self explanatory, for the rare more complicated cases the exact semantics are explained in the respective operation page.

   :    - separates the operands from the result
   []   - everything in square brackets can be a vector or a scalar value
   dfpx - lower case operands are the widths possible of the respective domain
          (x is any integer)
          what is important is that all widths of the domain are the same within the operation
   DFPX - upper case must be vectors of the domain
   ½    - half width of the operands, until lowest possible for domain
   2    - double width of the operands, up to maximum possible on core
   i    - bit index/count, can be any width, and width is independent of other operand
   n    - vector element index, can be any width too and is independent of other operand