All arithmetic computation in Milan is based on five simple
mini-instructions: NEGATE, ADD, SIGNUM
,
MULTIPLY, and DIVIDE. Any computation which can be expressed
as a subset of these commands in this order will execute in a
single cycle. For instance: negation, addition, signum,
multiplication, division, identity (no operation), subtraction
(negation and addition), decrement (negation and addition),
increment (addition), absolute value (signum and multiplication),
comparison (negation, addition, and signum), rounding to nearest
multiple (division and multiplication) all take unit time.
These arithmetic functions can be combined with memory indirection to create a host of addressing modes. We chose to have four possible indirections in each cycle:
This allows a possibility of 16 different addressing modes for dyadic operations in a single cycle. For monadic operations, there are an additional 48 addressing modes. This is a result of the fact that the third indirection above occurs immediately following the ADD in the cycle. This allows indexed operand indirection (for instance, referring to locations relative to the stack pointer) in a single cycle. Similarly, we add an INDEX mini-instruction following the fourth indirection which adds the second operand to the result pointer. This allows information to be stored relative to the contents of a location (like the stack pointer) in one cycle.
Using one and zero for true and false, we can express the fundamental boolean functions as follows:
Since the instruction pointer is represented as a machine location, control flow is easily expressed in terms of these primitives. Subroutines and unconditional jumps amount to adding values to the instruction pointer and perhaps manipulating the stack. A conditional jump is slightly more tricky in that some boolean value must be multiplied by an offset before it is added to the instruction pointer.
Thus, the simplicity and regularity of the instruction set allows a single ADD mini-instruction to be active simultaneously in add, subtract, compare, boolean and jump instructions.
Computational functions that cannot be expressed using the primitives discussed so far are handled by triggering an ``exception''. An exception is a mini-instruction which causes the interpreter to suspend the cycle so as to execute a command stored in the excep location of the processor that signaled the exception. Multiple exceptions occurring in the same cycle are serialized. Input, output, and expensive mathematical operations such as logarithms are supported through the EXCEP mini-instruction (a summary of available exceptions can be found in Table 2).