In this chapter, we give a detailed description of the instruction set of the MIX computer. This description considers the detailed specifications of the execution of each instruction. Much of assembly language programming is concerned with the small details of the computer organization and instruction set. Thus, it is necessary to be very familiar with the exact meaning of each instruction.
Before we can give a complete explanation of what the MIX instruction set is, we need to first look at how a program is executed by the computer. This is followed by a consideration of the common features of the execution of a large class of instructions -- the memory reference instructions. Finally, we examine the complete instruction set.
How does the MIX computer actually execute instructions? What does it do at what time and why? To answer these questions, it is necessary to look beneath the description of the MIX computer as a computer with 4000 words of memory and nine registers, an overflow toggle, comparison indicator, and I/O devices. We know that the basic instruction execution cycle is composed of the following four steps:
Figure 3.1 gives a block diagram of the internal structure of the MIX computer. Notice that the four basic components (memory, ALU, control unit, and I/O system) are present. There are also a number of registers which we did not tell you about in our earlier description of the MIX computer. These are the internal registers and are not directly accessible by the programmer. They are registers which have been used by the computer designers to build the MIX machine and are dedicated to specific internal functions; they are not meant to be used by the programmer. In fact, there are no instructions in the instruction set of the MIX machine which would allow them to be used.
Specifically the internal registers are,
The instruction execution cycle for the MIX computer is quite simple. When the machine is started, the following steps are executed over and over again, until the computer executes a halt instruction, or someone presses the STOP button on the MIX console.
There are two main types of instructions: those which specify an operand and those which need no operand. Instructions such as, HLT (halt the computer), NUM (convert the AX register from character code to numeric in the A register), NOP (no operation), and others need no operand. These instructions, determined by their opcode (C field, byte 5) and opcode modifier (F field, byte 4) are executed immediately, and the control unit returns to step 1 to fetch the next instruction (unless the instruction was a HLT, of course).
For operations with an operand, the operand must be determined. The operand is specified by the address field (bytes 0, 1, and 2) as modified by the I field (byte 3) of the instruction. The modification of the address field by the I field is called the effective operand calculation and is described in Section 3.2. This produces the effective operand, m. The effective operand is used in two ways. For immediate operations, jumps, and I/O instructions, the effective operand is the operand, a two-byte-plus-sign integer number. For memory reference instructions (the loading, storing, arithmetic, and comparison operations), the effective operand is the address of the operand. For these instructions, the control unit copies the effective operand into the MAR and fetches the contents of the addressed memory location into the MDR. This full-word (five bytes plus sign) quantity is then used as the operand.
In either case, memory reference or non-memory reference, the instruction is executed once the operand is obtained. Fetching an operand from memory for a memory reference instruction means that these instructions take longer to execute than the operations which use the effective address as their operand. Once the execution is complete the control unit returns to step 1 to repeat this sequence for the next instruction.
Most of the instructions for the MIX computer specify an operand in the address field (bytes 0 through 2) of the instruction. This operand is modified according to the contents of the I field (byte 3) of the instruction. Many, but not all, instructions use the resulting operand as an address. The immediate and the shift instructions treat the operand as an integer number. However, the load, store, compare, jump, arithmetic, and (some) I/O instructions treat the operand which results from the original operand and the modification specified by byte 3 as an address, the effective address. Because these instructions are more common, the standard terminology refers to the operand as an address. (Hence, bytes 0, 1, and 2 are called the address field instead of the operand field.) Thus, although we are concerned with the calculation of the effective operand and the operand is only used as an address most of the time, we present our discussion in terms of an effective address calculation. We denote the effective operand (or effective address) by m.
The I field of an instruction determines the mode of the effective address calculation. The simplest mode is direct addressing. Direct addressing is indicated by a zero value for the I field. In this case the effective address is equal to the address given in the instruction. No modification is needed. This is the most common and useful addressing mode.
The other addressing mode of every MIX computer is an indexed addressing mode. If the value of the I field is between 1 and 6 (inclusive) then the effective address is the sum of the contents of the address field of the instruction and the contents of the index register whose number is given in the I field. Letting AA be the contents of the address field, and i be the number given in the I field, then m = AA + contents of index register i.
As an example, let the index registers have the (octal) values
Instruction | Effective address | ||||||
AA | I | F | C | m | |||
+0013 | 00 | 05 | 10 | +0013 | no indexing (direct) | ||
+1472 | 00 | 05 | 10 | +1472 | no indexing | ||
+1472 | 01 | 05 | 10 | +1572 | indexing by I1 | ||
+0001 | 02 | 05 | 10 | +0201 | indexing by I2 | ||
+0014 | 03 | 05 | 10 | +0013 | indexing by I3 | ||
+0000 | 04 | 05 | 10 | +0001 | indexing by I4 |
Notice, however, that the indexing field is one byte (six bits) in size, and we have only specified the addressing mode for the values of the index field equal to 0, 1, 2, 3, 4, 5, 6. Many owners of MIX computers have bought an option for the CPU which increases the number and kind of addressing modes. This additional unit treats the index field as a pair of octal digits: ab. Each of these two digits specifies an addressing mode. The effective address calculation is performed by first modifying the address by the addressing mode specified by a and then using this effective address as the address to be modified by the addressing mode given by b. Since we have 3 bits per octal digit, we have 8 values for each of a and b, and 64 possible combination addressing modes. The interpretation of the addressing modes for each of the octal digits of the indexing field is
Digit | Mode |
---|---|
0 | direct addressing (no modification) |
1 | indexing by I1 |
2 | indexing by I2 |
3 | indexing by I3 |
4 | indexing by I4 |
5 | indexing by I5 |
6 | indexing by I6 |
7 | indirect addressing |
The first seven addressing modes have already been discussed. Indirect addressing (a = 7 or b =7) is another addressing technique which is a common addressing mode for computers. With indirect addressing, the address which we already have (initially the address field of the instruction, AA) is not the effective address (as in direct addressing) but the address of a word in memory which contains (in its address field) the effective address.
Consider for a minute the difference between an immediate instruction and a memory reference instruction. If the address were +0100 for an immediate instruction, then the operand for the instruction is +0100. For a memory reference instruction, the operand is not +0100 but the contents of location +0100 in memory. For an indirect addressing mode, the operand is not +0100, nor is it the contents of location +0100. Rather, for indirect addressing, it is the contents of the memory location whose address is the contents of location +0100. Thus, in order for the MIX computer to execute the instruction, it requires either 0, 1, or 2 memory references:
(0) For an immediate instruction, the effective address is calculated and the instruction is executed immediately, using this number as operand.
(1) For a memory reference instruction, the effective address is calculated. This address is sent to the memory unit and the instruction is executed on the contents of the location addressed by the effective address.
(2) For a memory reference instruction with indirect addressing, the effective address is calculated first. This address is sent to the memory unit (first memory reference). The resulting word which is read from memory is not the operand but the address of the operand, so the contents of the fetched location are given back to the memory unit as an address, and this new location is read out (second memory reference). The instruction is then executed on the contents of this memory location.
The presence of two address modifier digits (a and b) in each instruction allows for three classes of effective addresses:
I1 | = | +0143 |
I2 | = | +0010 |
I3 | = | -1000 |
Instruction | Effective address | |
+0040 12 05 10 | +0040 + 0143 + 0010 = +0213 | |
+1000 32 05 10 | +1000 - 1000 + 0010 = +0010 | |
+3000 33 05 10 | +3000 - 1000 - 1000 = +1000 |
One major aspect of MIX indirect addressing has not been mentioned yet. Remember that there are 4000 memory locations in the MIX memory, addressed from 0000 to 7637. Thus, an address can be specified in two bytes. The address field of the instruction allows for two bytes plus a sign, while a word in memory is five bytes plus sign.
Which bytes of a memory word are used to specify an indirect address? There are two reasonable ways to specify a two-byte address in a five-byte memory word. One would be to use the lower two bytes (bytes 4 and 5) of the memory word, ignoring the high order bytes, or requiring them to be zero. The other method would be to interpret the memory word as if it were an instruction and use the upper two bytes (the address field of the instruction) as the indirectly specified address. This approach also makes it reasonable to allow the I field of the indirect word to modify the address field. This is the approach to indirect addressing taken by the MIX computer. The indirect address is used to fetch a word from memory. The effective address is then the result of applying the effective address calculation to this memory word. This may, of course, involve further indirection and/or indexing.
For example, assume that the (octal) contents of the following memory locations are
Location | Contents |
1013 | +0017 00 00 00 |
1014 | +0200 01 00 00 |
1015 | +0000 21 00 00 |
1016 | +1013 07 00 00 |
1017 | -0001 17 00 00 |
1020 | +1017 71 00 00 |
For an instruction, +1013 07 05 10, indirection has been specified (b = 7). To calculate the effective address for this instruction, we must calculate the effective address of location 1013 of memory. The effective address of 1013 is an unmodified +0017 (since no modification is specified in byte 3 of location 1013). Thus, the effective address for the instruction is +0017. For an instruction +1014 07 05 10, we indirect through location +1014. This specifies an address of +0200 indexed by register I1, so the effective address is +0200 + 1017 = 1217. An indirect reference to location 1015 results in double indexing to give an effective address of +0000 + (I2) + (I1) = +1024.
For an instruction +1016 07 05 10, we have indirection through location 1016, so the effective address is the effective address of location 1016. The effective address of location 1016 specifies another level of indirection, through location 1013, so the effective address is +0017.
Consider the effective address calculation of the instruction +0000 17 05 10. This instruction does indexing first by I1 (a = 1). This gives a partially computed address of +0000 + (I1) = +1017. Then indirection occurs (b = 7), so we fetch location 1017 and apply the effective address calculation to it. Location 1017 specifies preindexing of -0001 by I1, and then indirection again. The partially computed address is -0001 + (I1) = +1016. Going indirect through 1016 will take us (indirectly) to 1013 giving a final effective address of +0017 after three levels of indirection and two indexing operations.
An instruction like +1013 27 05 10 will result in four levels of indirection with both preindexing and postindexing, resulting eventually in an effective address of +1036.
The effective address calculation for the MIX computer can seem quite complex. It is based on the two simple techniques of indexing and indirection, which are used in many computers. The more complex forms of the effective address calculation seldom occur in programming. Most addresses are either direct or indexed with an occasional double indexing or simple one-level indirection. The other forms of effective address calculation must be used with great care, but can be quite useful in special circumstances. It is most important that you understand the effective address calculation procedure thoroughly in order to be able to read and write good MIX programs.
For immediate instructions, the effective address calculation produces the operand which is to be used for the instruction. For memory reference instructions, however, the effective address is only the address of the operand and the operand must now be fetched from this location in memory. The contents of the addressed location is, of course, five bytes plus sign. Sometimes it is desirable to operate not on the entire memory word, but only on a part of a word (particularly when characters are being manipulated). To allow this, the F field (byte 4) of memory reference instructions is used to give a field specification which describes which part of the addressed memory location is to be used by the memory reference instruction.
A field specification specifies two byte numbers, which are the left and right byte numbers of the field. The field is the left byte and the right byte and all bytes in between. These are encoded into one byte in the same way that the I field (byte 3) encodes both a and b, as the two octal digits of a byte. If the F field is the two octal digits LR then L is the left byte number and R is the right byte number. Since the bytes are numbered 0 through 5, we must have 0 ≤ L ≤ R ≤5 to specify a valid field. The following list gives some examples of partial fields.
F Field | Partial field specified | |
---|---|---|
05 | the whole word | |
00 | the sign bit only | |
02 | the first two bytes plus sign | |
15 | the whole word except the sign | |
45 | bytes 4 and 5 | |
55 | byte 5 only |
To make it easier to specify partial fields, we use the colon (":") to separate the left and right byte numbers of a partial field, as in 0:5, 0:0, 0:2, 1:5, 4:5, 5:5, and L:R.
Being able to specify only a part of a word of memory can be very useful, but it requires that the description of the instructions which can use partial fields be more complex, in order to describe how the partial fields are used. There are three ways that partial fields are used.
As examples, consider a MIX memory with the contents of location 0452 = +1122334455 and 0453 = -0102030405. Then an instruction +0452 00 24 10 will load into the A register (opcode = 10) from the contents of the effective address 0452 (no modification, since byte 3 is zero). A partial field is specified by byte 4 (= 2:4), so bytes 2, 3, and 4 of location 0452 will be copied into bytes 3, 4, and 5, respectively, of the A register. Bytes 1 and 2 of A will be set to zero, and the sign byte will be set "+". Thus, the A register will be +0000223344. If we then execute the instruction +0453 00 02 30, we will store (opcode = 30) the sign plus bytes 4 and 5 of the A register into the sign and bytes 1 and 2 (partial field specification in byte 4 of instruction = 0:2) of location 0453 (the effective address resulting from bytes 0:3 of the instruction), changing location 0453 from -0102030405 to +3344030405. The A register is not changed by the store.
For non-memory reference instructions, the F field is not used to specify partial fields but is used to distinguish between instructions with the same numeric opcode in the C field. For example, an opcode of 64 specifies an immediate operation on register 4. The F field determines whether the instruction is an INC4 (F = 00), a DEC4 (F = 01), an ENT4 (F = 02), or an ENN4 (F = 03). For jump instructions, the F field determines which conditions will be tested for the jump. The F field specifies the I/O device unit number for I/O instructions.
Also, some field specifications which do not specify partial fields are used for memory reference instructions of special kinds. For example, a field of 06 is used with opcodes 01, 02, 03, and 04 (ADD, SUB, MUL, and DIV) to designate a floating point operation (FADD, FSUB, FMUL, FDIV). This allows the same opcode to be used for both integer and floating point operands, with the F field specifying which type of operand is meant.
This completes our description of the instruction execution steps for the MIX computer. We have presented the main ideas of a common instruction execution cycle, effective address calculation, and partial field specification. We now present a detailed description of the operation performed by each instruction.
There are two kinds of loading operators in the MIX computer, the load (LD*) instruction and the load negative (LD*N) instruction. For both of these instructions, * specifies the register into which the new value will be loaded, and can be either A, 1, 2, 3, 4, 5, 6, or X, to refer to the appropriate register. The register is first set to zero with a positive sign. Then the bytes specified by the partial field specification in the F field are loaded into the register. In the case of the LD*N instructions, the sign is complemented (+ to -, - to +) after the loading operation. The contents of the memory location addressed by the effective address of the instruction are not changed. The previous value of the register is lost.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
10 | * | LDA | load A with (m) |
11 | * | LD1 | load I1 with (m) |
12 | * | LD2 | load I2 with (m) |
13 | * | LD3 | load I3 with (m) |
14 | * | LD4 | load I4 with (m) |
15 | * | LD5 | load I5 with (m) |
16 | * | LD6 | load I6 with (m) |
17 | * | LDX | load X with (m) |
20 | * | LDAN | load A with negative of (m) |
21 | * | LD1N | load I1 with negative of (m) |
22 | * | LD2N | load I2 with negative of (m) |
23 | * | LD3N | load I3 with negative of (m) |
24 | * | LD4N | load I4 with negative of (m) |
25 | * | LD5N | load I5 with negative of (m) |
26 | * | LD6N | load I6 with negative of (m) |
27 | * | LDXN | load X with negative of (m) |
The index registers are only two bytes plus sign. The two bytes correspond to bytes 4 and 5 of a five-byte MIX word; bytes 1, 2, and 3 are missing. If an attempt is made to load non-zero information into these bytes, an error exists and the MIX machine will halt. To prevent this, it is wise to use a partial field specification for loading index registers, which results in only a two-byte-plus-sign field.
Partial field specifications for load instructions may or may not include the sign byte (byte 0). If it is included in the partial field specification, the sign of the memory word is loaded into the sign of the register; if not, the sign of the register is set to "+". The remaining bytes (non-sign) are loaded into the low-order bytes of the register being loaded. So, if L is not zero, the L:R bytes of memory location m are copied to the L-R + 5:5 bytes of the destination register.
For the load negative (LD*N) instructions, the sign is complemented after the above load has been performed. Thus, if the field specification includes the sign byte of the memory word, the sign of the register will be the opposite. If the field specification does not include the sign, then the sign of the register will be "-".
The storing operators are almost the inverses of the loading operators. The store instructions are named ST*, where * = A, 1, 2, 3, 4, 5, 6, X specifies the register to be stored into the memory location specified by the effective address, m. The contents of the register are left unchanged.
If a partial field specification is used, only those bytes of the memory location addressed by the effective address are changed. If the sign byte is included in the partial field specification, the sign byte of the register is stored in the sign byte of the memory location. For 1 ≤ L ≤ R ≤ 5, the 5-R+L:5 bytes of the register are stored in the L:R bytes of the memory location. That is, the low order bytes of the register are stored into the partial field specified by the instruction. If a partial field specification for storing an index register includes bytes 1, 2, or 3 of the index register, zeros are stored for these bytes.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
30 | * | STA | store A into location m |
31 | * | ST1 | store I1 into location m |
32 | * | ST2 | store I2 into location m |
33 | * | ST3 | store I3 into location m |
34 | * | ST4 | store I4 into location m |
35 | * | ST5 | store I5 into location m |
36 | * | ST6 | store I6 into location m |
37 | * | STX | store X into location m |
40 | * | STJ | store J register into location m |
41 | * | STZ | store zero into location m |
In addition to store instructions for the arithmetic (A, X) and index registers, two special store instructions are available in the MIX instruction repertoire. STJ stores the J register into a memory location. The J register is always treated as having a positive sign, and bytes 1, 2, and 3 are zero. Partial fields can be used as with any of the other store instructions.
Since zero is an important value in computers, a special store instruction, STZ, can be used to store a (positive) zero in a memory location. Partial field specifications can be used to zero only selected bytes and to set sign bits to "+".
For ADD (and SUB), the partial field of the memory location specified by the effective address of the instruction is added to (or subtracted from) the contents of the A register. The contents of the memory location are unchanged.
If the result of an ADD or SUB instruction is too large to be stored in the A register, then overflow occurs, and the overflow toggle is turned on. The result in the A register is the lower five bytes of the result (plus the correct sign). Overflow occurs if the magnitude (either positive or negative) of the result is greater than 1,073,741,823. Since the largest numbers which could be added (or subtracted) would be 1,073,741,823 + 1,073,741,823 (or -1,073,741,823 - 1,073,741,823), the result can never be greater in magnitude than 2,147,483,646. So, only one bit is unable to fit into the A register. The value of this bit can be determined by testing the overflow toggle.
The MIX computer also provides integer multiplication and division operations. MUL multiplies the contents of the A register by the partial field contents of the memory location addressed by the effective address and places the result back in the A and X registers. The low-order five bytes are in the X register, and the high-order 5 bytes are in the A register. Both signs are set to the sign of the product.
The double register result is produced, since if two n-bit numbers are multiplied, the result can require 2 × n bits. Thus, for any two 30-bit numbers on the MIX machine, the product could be up to 60 bits long. The X register has been added to the MIX machine for this specific purpose. When a multiply instruction is executed, the contents of the A register are multiplied by the contents of the addressed memory location and the result is placed in both register A and register X. The low-order bytes are put into the X register, and the high-order bytes are put into the A register. If the product of two numbers should never be too great to store in one word of MIX memory, then the A register should always be zero, after the multiplication.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
01 | * | ADD | add (m) to register A |
02 | * | SUB | subtract (m) from A |
03 | * | MUL | multiply (m) by A, giving AX |
04 | * | DIV | divide (m) into AX, giving A (quotient) and X (remainder) |
Division is the inverse of multiplication, and so it expects a double register dividend in register A and register X (high-order bytes in the A register; low-order bytes in the X register; sign of A is used; sign of X is ignored) and returns both an integer quotient (in the A register) and an integer remainder (in the X register). If the dividend is only one word, the A register must be set to zero, and the dividend loaded into the X register, with the proper sign in the A register.
If the quotient is more than five bytes in magnitude (or the divisor is zero), the contents of A and X are undefined and the overflow toggle is turned on. The sign of the X register is the same as the original sign of the dividend (in the A register). The sign of the quotient (in the A register) is positive if both divisor and dividend had the same sign and negative if they did not. If we let AX be the 10-byte dividend and C be the divisor, then the new contents of the A and X registers are related by
The MIX computer instruction set provides for five floating point arithmetic instructions (FADD, FSUB, FMUL, FDIV, and FLOT). Floating point operators are similar to the integer operations in that the A register is used as an accumulator. The overflow toggle is also set if exponent overflow or underflow occurs. Because of the nature of floating point numbers, however, multiplication and division do not result in, or require, more bits in the fractional part of the floating point, but only an adjustment in the exponent. Thus, the X register is not used for floating point instructions. The floating point hardware works best on normalized numbers, and always returns a normalized result. The operator FLOT converts an integer number in the A register into the corresponding floating point representation and leaves this floating point number in the A register.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
01 | 06 | FADD | add (m) to A as floating point numbers |
02 | 06 | FSUB | subtract (m) from A as floating point numbers |
03 | 06 | FMUL | floating point multiply of (m) by A; result in A |
04 | 06 | FDIV | floating point divide of (m) into A; quotient in A |
56 | 06 | FCMP | compare A and (m); set condition indicator |
05 | 06 | FLOT | convert the integer in A to floating point representation |
Most of our work in this text will deal with integer arithmetic, since (almost) all computers provide integer arithmetic operators, while floating point hardware is often not provided for the MIX machine. In fact, the floating point hardware for the MIX machine is not provided with the basic MIX 1009 computer but is an option available at extra cost. The instruction set has been defined with floating point operators included, however. If these instructions are included in a program which is run on a MIX computer without the floating point hardware option, they are treated as illegal instructions and will cause the MIX machine to halt.
The comparison operators, CMP*, allow * to specify any of the eight registers A, 1, 2, 3, 4, 5, 6, X to be compared against the partial field in the memory location specified by the effective address. The same bytes of the register and memory are always compared. Thus, a CMPA with field specification 1:3 will compare bytes 1:3 of the A register to bytes 1:3 of memory. The values of any other bytes in memory or the register are not important. If the sign bit is not included, a positive sign is used.
The register is compared to memory and the comparison indicator is set to either GREATER, EQUAL, or LESS as,
GREATER | The register is greater than the memory location | |
EQUAL | The register is equal to the memory location | |
LESS | The register is less than the memory location |
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
70 | L:R | CMPA | compare A and (m), set comparison indicator |
71 | L:R | CMP1 | compare I1 and (m), set comparison indicator |
72 | L:R | CMP2 | compare I2 and (m), set comparison indicator |
73 | L:R | CMP3 | compare I3 and (m), set comparison indicator |
74 | L:R | CMP4 | compare I4 and (m), set comparison indicator |
75 | L:R | CMP5 | compare I5 and (m), set comparison indicator |
76 | L:R | CMP6 | compare I6 and (m), set comparison indicator |
77 | L:R | CMPX | compare X and (m), set comparison indicator |
The comparison operators are used to set the comparison indicator. The results of a comparison can be used to affect the flow of control in a program by a jump. Jump instructions will change the value of the program counter to the effective address if the test condition is satisfied. The following jump instructions test the current value of the comparison indicator.
JG | Jump if comparison indicator is GREATER | |
JE | Jump if comparison indicator is EQUAL | |
JL | Jump if comparison indicator is LESS | |
JLE | Jump if comparison indicator is LESS or EQUAL | |
JNE | Jump if comparison indicator is LESS or GREATER | |
JGE | Jump if comparison indicator is GREATER or EQUAL |
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
47 | 00 | JMP | jump to m |
47 | 01 | JSJ | jump to m (but do not change register J) |
47 | 02 | JOV | jump to m if overflow on, turn overflow off |
47 | 03 | JNOV | jump to m if overflow off, turn overflow off anyway |
47 | 04 | JL | jump to m if comparison indicator is less |
47 | 05 | JE | jump to m if comparison indicator is equal |
47 | 06 | JG | jump to m if comparison indicator is greater |
47 | 07 | JGE | jump to m if comparison indicator is greater or equal |
47 | 10 | JNE | jump to m if comparison indicator is not equal |
47 | 11 | JLE | jump to m if comparison indicator is less or equal |
5* | 00 | J*N | jump to m if * is negative |
5* | 01 | J*Z | jump to m if * is zero |
5* | 02 | J*P | jump to m if * is positive |
5* | 03 | J*NN | jump to m if * is non-negative |
5* | 04 | J*NZ | jump to m if * is non-zero |
5* | 05 | J*NP | jump to m if * is non-positive |
In addition, programs can test the state of the A register, X register, or index registers directly and transfer control without the use of a comparison instruction by the following jumps, where * may be A, 1, 2, 3, 4, 5, 6, or X to specify the register being tested.
J*N | Jump if register * is negative (but not negative zero) | |
J*Z | Jump if register * is zero (positive zero or negative zero) | |
J*P | Jump if register * is positive (but not positive zero) | |
J*NN | Jump if register * is non-negative (positive or zero) | |
J*NZ | Jump if register * is non-zero (positive or negative) | |
J*NP | Jump if register * is non-positive (zero or negative) |
In all these tests, negative zero and positive zero are zero, and are not considered to be positive or negative numbers.
JOV and JNOV will transfer control to the effective address if the overflow toggle is on (overflow) or off (no overflow), respectively. In either case, for both of these instructions, the overflow toggle is turned off after the instruction is executed.
JMP is an unconditional jump. It always transfers control to the effective address.
In all these cases, the J register is always set to the value of the program counter before the program counter is set to the effective address if the condition is satisfied and the jump occurs. (If the jump does not occur, both the J and P registers are unchanged.) Since the program counter is already advanced to point to the next instruction, the J register will always contain the address of the instruction which follows the most recent successful jump.
In certain cases this may not be desired. The JSJ instruction is an unconditional jump, but the value of the J register is not changed.
The load, store, arithmetic, comparison and jump instructions all treat the effective address as an address of a location in memory. The immediate operators do not treat the effective address as an address but as a signed integer. This signed integer can be entered (placed, loaded) into a register (ENT*), added to a register (INC*), subtracted from a register (DEC*), or its negative entered into a register (ENN*). In any of these instructions, the register involved can be A, X, or any of the index registers.
The ENT* and ENN* instructions are directly analogous to the LD* and LD*N instructions allowing any register to be loaded with a small constant (in the range -4095 to +4095) directly from the instruction without needing to load from memory. Bytes 1 to 3 are always zero after an enter or enter negative instruction. The increment and decrement are similar to ADD and SUB but can affect any of the eight central registers by the addition or subtraction of a small constant (-4095 to +4095) without fetching it from memory. Overflow may occur and will cause the overflow toggle to be set, in the case of the A or X register. The index registers cannot be set outside the range of -4095 to +4095 (two bytes plus sign). An attempt to increment or decrement an index register outside this range is an error and will halt the computer.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
60 | 00 | INCA | increment A by m |
60 | 01 | DECA | decrement A by m |
60 | 02 | ENTA | enter m into A |
60 | 03 | ENNA | enter negative of m into A |
61 | 00 | INC1 | increment I1 by m |
61 | 01 | DEC1 | decrement I1 by m |
61 | 02 | ENT1 | enter m into I1 |
61 | 03 | ENN1 | enter negative of m into I1 |
62 | 00 | INC2 | increment I2 by m |
62 | 01 | DEC2 | decrement I2 by m |
62 | 02 | ENT2 | enter m into I2 |
62 | 03 | ENN2 | enter negative of m into I2 |
63 | 00 | INC3 | increment I3 by m |
63 | 01 | DEC3 | decrement I3 by m |
63 | 02 | ENT3 | enter m into I3 |
63 | 03 | ENN3 | enter negative of m into I3 |
64 | 00 | INC4 | increment I4 by m |
64 | 01 | DEC4 | decrement I4 by m |
64 | 02 | ENT4 | enter m into I4 |
64 | 03 | ENN4 | enter negative of m into I4 |
65 | 00 | INC5 | increment I5 by m |
65 | 01 | DEC5 | decrement I5 by m |
65 | 02 | ENT5 | enter m into I5 |
65 | 03 | ENN5 | enter negative of m into I5 |
66 | 00 | INC6 | increment I6 by m |
66 | 01 | DEC6 | decrement I6 by m |
66 | 02 | ENT6 | enter m into I6 |
66 | 03 | ENN6 | enter negative of m into I6 |
67 | 00 | INCX | increment X by m |
67 | 01 | DECX | decrement X by m |
67 | 02 | ENTX | enter m into X |
67 | 03 | ENNX | enter negative of m into X |
The input/output system for the MIX machine is quite simple and uses only three instructions (IN, OUT, IOC). Byte 4 of the instruction specifies the device which is being used with the instruction.
The IN instruction starts the input of information from an input device. The address given as the operand of the instruction is the address of the first location of a group of contiguous memory words into which information from the device will be read. Each device always reads a fixed amount of information. Each of these items is called a record. For example, a record for a card reader is one card, or 80 characters. At 5 characters per word (one character per byte), a card reader record is 16 words long. The record length is 16 words. The record length for tape, disk, and drum units is 100 words.
When an IN instruction is executed, the device (specified in byte 4) is notified that it should read one record and put it in memory, starting at the memory location given by the effective address, m.
Most I/O devices are very slow relative to the central processing unit (CPU). The fastest card reader still takes about 50 milliseconds to read a card, while the CPU takes on the order of microseconds to execute an instruction. Thus, the IN instruction only starts to read the card and then it continues to the next instruction. The device will become busy for as long as it takes to input a record and then will again become ready (idle), waiting for the next IN instruction. Before the CPU can use the information which is being read in, it must be certain that the IN instruction which started the reading is complete. This will happen when the device becomes ready (not busy) again. To test this, two jump instructions exist. JBUS (jump if device is busy) will jump if the device (whose device number is in byte 4) is busy. If the device is not busy, execution continues to the next instruction. The JRED (jump if ready) will jump if the device is ready, that is, not doing anything now and ready to perform an I/O operation if so instructed. Both of these instructions will change the J register if the jump occurs; otherwise, execution continues at the next instruction.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
42 | N | JBUS | jump to location m if unit N is busy |
43 | N | IOC | issue I/O control signal to unit N |
44 | N | IN | start input transfer from unit N |
45 | N | OUT | start output transfer from unit N |
46 | N | JRED | jump to location m if unit N is ready |
The OUT instruction is very similar to the IN. The device is requested to begin outputting information from the block of memory beginning at the memory location specified by the effective address. As with the IN instruction, the amount of information which is transferred is always exactly one record, the length of a record depending on the device. The line printer, for example, has 120 characters per line and a record length therefore of 24 words. The card punch has a record of 16 words.
Also, as with the IN instruction, the transfer of information caused by the OUT instruction is only started by the OUT instruction. It cannot be considered complete until a JBUS or JRED instruction indicates that the device is ready for another instruction. This is true with one exception. For both the IN and OUT instructions, if an I/O instruction occurs for a busy device (busy because of a previous I/O instruction which is not yet complete), then the CPU waits until the previous operation is complete before starting the new I/O operation and going on to the next instruction.
The IOC (Input/Output Control) instruction is provided in MIX to allow different I/O devices to be controlled. Each I/O device is unique in how it operates and although the basic functions which they perform are those of Input and Output, some devices can also do other functions. The IOC instruction instructs the I/O device to begin one of these additional functions. If the device is busy, the CPU waits until it is ready before executing the instruction and continuing. The effective address is a parameter to the device.
The greatest use of IOC comes with magnetic tapes. The IOC command is used to position a tape. The effective address, m, specifies how. If m = 0, the tape is rewound. If m > 0, the tape skips forward m records; if m < 0 then the tape skips backwards -m records (or to the beginning of the tape, whichever comes first). For other devices, the effect of the IOC command depends on the device.
Six shift instructions are provided to shift information in the A and X registers. Three shift instructions shift left, and three shift right. The effective address specifies the number of bytes to shift. SLA and SRA are end-off shifts which affect only the A register, while SLAX and SRAX shift the A and X registers as one large 10-byte double register. (A is the high-order 5 bytes; X is the low-order 5 bytes.) Zeros are shifted in from the left (for a SRA or SRAX) or from the right (for an SLA or SLAX), since these are end-off shifts. The SRC and SLC shift the A and X registers (again as a double register) circularly with the bytes which are shifted off one end being shifted back in at the other end. The signs of the A and X registers are not changed by any shift instruction.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
06 | 00 | SLA | shift A m bytes left, end-off |
06 | 01 | SRA | shift A m bytes right, end-off |
06 | 02 | SLAX | shift AX m bytes left, end-off |
06 | 03 | SRAX | shift AX m bytes right, end-off |
06 | 04 | SLC | shift AX m bytes left, circular |
06 | 05 | SRC | shift AX m bytes right, circular |
A number of commands do not fit easily into the categories of instructions presented above. These miscellaneous commands perform various important tasks.
The HLT instruction stops the computer. The computer can be restarted only by pushing the BEGIN button on the MIX console.
NOP is an instruction which does nothing. It is similar to a CONTINUE statement in Fortran.
MOVE is a very complicated but useful instruction. It copies the contents of a block of memory locations into another block of memory locations, effecting a memory-to-memory transfer capability. Byte 4 specifies the number of words to move, while the effective address specifies the address from which the contents should be copied. Index register 1 contains the address where the contents should be copied to. The copy is done one word at a time, and I1 is increased as the copy is executed, so that at the end of the move, I1 has been increased by the number of words moved. Words are moved one at a time, and the blocks of words being copied to and from can overlap.
The input/output system has many devices which treat information as alphabetic characters, not as numeric quantities, while the CPU operates only on numeric data, of course. To simplify the conversion between binary and character code, two conversion instructions, NUM and CHAR, are included in the MIX instruction set. The NUM operator converts the contents of the A and X register, considered as one large 10-byte register (A is high-order; X is low order), from a 10-character character code representation of an integer number (right justified, zero filled) to the binary representation of that number, and puts the numeric representation into the A register. The X register and the sign bytes of both registers remain unchanged. Each byte of the A and X register is the character code for one digit of the number. The digit specified by a byte is the remainder of the byte divided by 10. Thus, 00, 10, 20, …, 60 all are converted to the digit 0; 01, 11, 21, …, 61 convert to the digit 1; and 09, 19, 29, …, 59 convert to 9. Since the largest number which can be stored in one word is 1,073,741,823, there are (ten-character) numbers which cannot be converted to binary, and overflow results in these cases.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
05 | 00 | NUM | 10-byte decimal in AX converted to binary in A |
05 | 01 | CHAR | A is converted to 10-byte decimal characters in AX |
05 | 02 | HLT | halt the MIX machine |
00 | 00 | NOP | no operation |
07 | N | MOVE | move N words starting from m to (I1), add N to I1 |
Conversion in the other direction, from numeric binary to character code is performed by the CHAR instruction. When the CHAR instruction is executed, the contents of the A register are converted from numeric binary into a 10 digit (decimal) character code (with leading zeros if necessary). The high-order 5 characters are put into the A register, and the low-order five characters are put into the X register. The signs of the A and X register are unchanged.
For both the NUM and the CHAR instructions, the effective address (bytes 0:3) of the instruction is ignored.
As an option (at extra cost), purchasers of the binary MIX 1009B computer can have added to their instruction set several special instructions specifically designed for a binary machine. These instructions are only for binary computers and treat a MIX word not as 5 bytes plus sign, but as a word of 30 bits plus sign.
SRB and SLB shift the A and X register, treated as a double register, right or left the number of bits specified by the effective address. A shift left of one bit is equivalent to multiplying by two; a shift left by two bits, multiplying by four; and so on. These shifts are end-off, with zeros shifted in.
Opcode | Field | Mnemonic | Instruction |
---|---|---|---|
01 | 07 | ORR | inclusive-OR of (m) with A |
02 | 07 | XOR | exclusive-OR of (m) with A |
03 | 07 | AND | logical AND (m) into A |
06 | 06 | SLB | shift AX m bits left, end-off |
06 | 07 | SRB | shift AX m bits right, end-off |
50 | 06 | JAE | jump to m if A is even |
50 | 07 | JAO | jump to m if A is odd |
57 | 06 | JXE | jump to m if X is even |
57 | 07 | JXO | jump to m if X is odd |
The AND, ORR, and XOR operations are called boolean instructions. They perform the "logical", or Boolean, operations on the A register and the contents of the memory location addressed by the effective address. These operations are those of "and", "or", and "exclusive-OR". They are applied bitwise; so, for an AND instruction bit 0 of the A register is ANDed with bit 0 of memory and the result is put in bit 0 of the A register; bit 1 of the A register is ANDed with bit 1 of memory and put in bit 1 of the A register; and so on. The AND, ORR, and XOR functions on each of the four possible operand pairs (one from the A register, and the other from memory) are
Operand 1 | Operand 2 | AND | ORR | XOR |
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
One important property of a computer program is how long it takes to execute. This is determined to a large extent by the algorithm which the program uses, but also by which instructions it uses. Since arithmetic unit and control unit circuitry is electronic, it can operate at very high speeds, and so the time it takes to execute an instruction is determined mainly by how many memory references are made. The immediate, jump, NOP, NUM, and CHAR instructions all take one time unit, since only the instruction need be fetched from memory. The memory reference instructions (load, store, arithmetic, and compare instructions) need two memory references (one for the instruction and one for the operand), and so take two time units. MUL and DIV instructions are an exception, since they are so complex; MUL takes 10 time units and DIV takes 12. Shift instructions take two time units, even though they only reference memory once. The MOVE instruction requires 2 × n + 1 memory references to move n words, and so takes 2 × n + 1 time units (one for the instruction fetch, and one to load and one to store each of the n words).
Instructions | Time | |
---|---|---|
All load, store, compare, and shift instructions: | 2 units | |
The ADD and SUB arithmetic operations: | 2 units | |
The MUL arithmetic operation: | 10 units | |
The DIV arithmetic operation: | 12 units | |
The MOVE operation, to MOVE n words in memory: | 2×n + 1 units | |
All other instructions: | 1 unit |
The IN, OUT, and IOC instructions only take one unit plus any time they must wait because of a busy device. This extra time is called the interlock time and is often on the order of thousands of time units.
The actual length of a time unit varies according to the technology used to build the MIX computer. Old MIX machines may have time units of 3 or 4 microseconds, while the newer models, using semiconductor memory, have time units of 500 to 800 nanoseconds. Since we wish to discuss all MIX machines, we discuss all execution timings in terms of the memory cycle time of the MIX machine, which we call one time unit.
The MIX computer is a small general purpose computer whose design has been influenced by a number of contemporary computers. It has 4000 words of memory, with each memory location being composed of 5 bytes plus a sign. Registers include the A and X registers (five bytes plus sign), six index registers (two bytes plus sign), the J register (two bytes), overflow toggle (ON/OFF) and comparison indicator (GREATER/EQUAL/LESS). Instructions allow loading and storing registers, addition, subtraction, multiplication, division, shifts, immediate operations, compares, jumps, input/output, conversion between (decimal) character code and numeric binary, and a few miscellaneous commands. The operands for memory reference instructions may be partial fields of a memory location. The effective address may be given in the instruction with no modification, indexing, double indexing, indirection, preindexed indirection, or postindexed indirection. Binary MIX machines can be equipped with special binary instructions.
The MIX machine was originally defined by Knuth in the first volume of The Art of Computer Programming, Knuth (1968), and repeated in the second volume, Knuth (1969). A short paperback, entitled MIX, was published in 1970 to serve as a reference for the MIX system. This was a reprint of the defining pages of Knuth (1968). There may be a locally prepared manual or report which describes your particular MIX computer system; check with your instructor or computation center.