next up previous
Next: Computation Optimizations Up: The Milan Virtual Machine Previous: Instruction Format

Computation Mini-Instructions

In this section, we describe the ten mini-instructions which (when used in combination) are responsible for arithmetic computation, addressing-modes, boolean arithmetic, and program flow. We demonstrate the ability of these mini-instructions to express a large number of useful functions and describe simple optimizations which can be performed to speed up the instruction cycle.

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:

1.
Indirect the first operand.
2.
Indirect the second operand.
3.
Indirect the first operand again.
4.
Indirect the result pointer.

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).


next up previous
Next: Computation Optimizations Up: The Milan Virtual Machine Previous: Instruction Format
Back to Chris Metcalf's home page