An Illustrative Architecture

Originally, although an example architecture based on a fundamental unit of 12 bits was sketched out on the preceding page, I had declined to explore the possibility in detail. Now I will examine how a useful architecture might be built around instructions that are 12 and 24 bits in length.

The floating-point data formats that it will use would be the following:

The extended-precision floating-point numbers would be 96 bits in length, and this would also be a possible width for the data bus in this architecture; thus, some forms of data would face alignment restrictions based on power-of-two multiples of the fundamental unit.

The basic instruction formats would be the following:

Addresses, in this architecture, point to consecutive individual 12-bit units of memory.

This is based on organizing the registers of the machine as follows:

Thus, in a register-to-register instruction, to allow six bits for the opcode, and a bit to distinguish these instructions from memory-reference instructions, only the first four of the eight registers in each set can be used as the destination.

Note that this means that there will be a register-to-register form of the store instructions.

In the memory-to-register instructions, the destination register will always be register 0. As the base register field is only one bit wide, it indicates if register 6 or register 7 is used as the base register; zero does not turn off the use of a base register, but indicates register 6 instead. The index register field is two bits wide; 0 does indicate that an instruction is not indexed; 1, 2, or 3 indicates the integer register used as the index register.

Given that sizes of 36 bits and 60 bits are used for floating-point numbers, the opportunity for making use of alignment restrictions to conserve opcode space is limited. But as 24-bit and 48-bit integers, as well as 48-bit floating-point numbers, are used, some opportunity does exist, which is why the opcode field of the memory-reference instructions is only five bits long, while that of the register-to-register instructions is six bits long.

The basic register-to-register and memory reference instructons are as follows:

Register-to-   Memory
Register       Reference

000000         00000 ...    0  SW     Swap
000001         00001 ...    0  C      Compare
000010         00010 ...    0  L      Load
000011         00011 ...    0  ST     Store
000100         00100 ...    0  A      Add
000101         00101 ...    0  S      Subtract
000110         00110 ...    0  M      Multiply
000111         00111 ...    0  D      Divide

001000         01000 ...    0  I      Insert
001001         01001 ...    0  UC     Unsigned Compare
001010         01010 ...    0  UL     Unsigned Load
001011         01011 ...    0  X      XOR
001100         01100 ...    0  N      AND
001101         01101 ...    0  O      OR
001110         01110 ...    0  ME     Multiply Extensibly
001111         01111 ...    0  DE     Divide Extensibly

010000         00000 ...   01  SWL    Swap Long
010001         00001 ...   01  CL     Compare Long
010010         00010 ...   01  LL     Load Long
010011         00011 ...   01  STL    Store Long
010100         00100 ...   01  AL     Add Long
010101         00101 ...   01  SL     Subtract Long
010110         00110 ...   01  ML     Multiply Long
010111         00111 ...   01  DL     Divide Long

011001         01001 ...   01  UCL    Unsigned Compare Long
011010         01010 ...   01  ULL    Unsigned Load Long
011011         01011 ...   01  XL     XOR Long
011100         01100 ...   01  NL     AND Long
011101         01101 ...   01  OL     OR Long
011110         01110 ...   01  MEL    Multiply Extensibly Long
011111         01111 ...   01  DEL    Divide Extensibly Long

100000         00000 ...  011  SWE    Swap Extended
100001         00001 ...  011  CE     Compare Extended
100010         00010 ...  011  LE     Load Extended
100011         00011 ...  011  STE    Store Extended
100100         00100 ...  011  AE     Add Extended
100101         00101 ...  011  SE     Subtract Extended
100110         00110 ...  011  ME     Multiply Extended
100111         00111 ...  011  DE     Divide Extended

101000         01000 ...  011  MEUE   Muliply Extensibly Unnormalized Extended
101001         01001 ...  011  DEUE   Divide Extensibly Unnormalized Extended
101010         01010 ...  011  LUE    Load Unnormalized Extended
101011         01011 ...  011  STUE   Store Unnormalized Extended
101100         01100 ...  011  AUE    Add Unnormalized Extended
101101         01101 ...  011  SUE    Subtract Unnormalized Extended
101110         01110 ...  011  MUE    Multiply Unnormalized Extended
101111         01111 ...  011  DUE    Divide Unnormalized Extended

110000         10000           SWF    Swap Floating
110001         10001           CF     Compare Floating
110010         10010           LF     Load Floating
110011         10011           STF    Store Floating
110100         10100           AF     Add Floating
110101         10101           SF     Subtract Floating
110110         10110           MF     Multiply Floating
110111         10111           DF     Divide Floating

111000         11000           SWD    Swap Double
111001         11001           CD     Compare Double
111010         11010           LD     Load Double
111011         11011           STD    Store Double
111100         11100           AD     Add Double
111101         11101           SD     Subtract Double
111110         11110           MD     Multiply Double
111111         11111           DD     Divide Double

Because the extended format does not have a hidden first bit, unnormalized operate instructions are available for that format.

For integers, the Load instruction performs sign extension when the register is not filled; the Unsigned Load instruction zeroes the part of the register that is not filled, and the Insert instruction leaves that part of the register unaffected.

The Divide Extensibly instruction treats the destination register as a 48-bit quantity; that is divided by the 24-bit source operand, and the 48-bit result is placed in the destination register. The 24-bit remainder is loaded into the register at the next higher location - and the destination register for this instruction must be an even-numbered register.

The Divide Extensibly Long instruction can only have register zero as its destination register. Registers 0 and 1 together form a 96-bit integer (the most significant part of which is in register 0) which is divided by the 48-bit source operand. The 96-bit quotient is placed in registers 0 and 1, and the 48-bit remainder is placed in register 2 (not register 3, as a strict analogy with the Divide Extensibly instruction might suggest).

The Multiply Extensibly instruction multiplies the 24-bit source operand and the 24-bit destination operand, and puts their 48-bit product in the destination register.

The Multiply Extensibly Long instruction multiplies the 48-bit source operand and the 48-bit destination operand, and puts their 96-bit product in the destination register (which must be an even-numbered register) and the one following, with the most significant part being placed in the destination register.

The Multiply Extensibly Unnormalized Extended instruction places the most significant part of the product of its extended-precision floating-point operands in the destination register, which must be an even-numbered register, and the least-significant part of a double-width mantissa in the register following. The contents of the exponent field in that register are undefined, and should be ignored.

The Divide Extensibly Unnormalized Extended instruction divides a floating-point number with a double-length mantissa spread over two registers by the source operand; a quotient is produced as though the mantissas of the two operands were integers, replacing the source operand, and the remainder from this division is placed, in unnormalized form and with the correct exponent, in the second register following the source register.

The codes that would indicate an instruction operating on an aligned operand 192 bits in length or greater are instead used to permit additional instructions, both register to register and memory-reference.

In order to increase the size of the opcode field to eight bits for the memory-reference instructions, it was not possible to increase the size of the index register or base register fields in the instruction; this seemed reasonable, as making additional base registers available just for the extended-format instructions would have been of limited utility. However, a full three-bit destination register field was provided, as is the case for the extended register-to-register instructions.

In the register-to-register instructions, the opcode field is expanded to nine bits, rather than eleven, allowing additional instruction format options.

Seven bits are all that is required for the basic memory-reference and register-to-register instructions. These opcodes follow this pattern:

000nnnn  (8 bits) Byte
001nnnn (12 bits) Small
010nnnn (24 bits) Integer
011nnnn (36 bits) Alternate Integer
100nnnn (48 bits) Long
101nnnn (96 bits) Extended
1100nnn (36 bits) Floating
1101nnn (48 bits) Medium
1110nnn (60 bits) Double

The types before Extended are fixed-point types. Multiply, Divide, Multiply Extensibly, and Divide Extensibly instructions are not provided for the 8 bit long Byte type.

The types after Extended are floating-point types with a hidden first bit, so no unnormalized floating-point instructions are provided for them.

Extended, on the other hand, is a floating-point type without a hidden first bit, so all the instructions shown above are available.

The extended memory-reference instructions are not required to be properly aligned. Alignment is still recommended, however, Thus, for Integer instructions, the last bit of the displacement should be zero; for Long and Medium instructions, the last two bits; and for Extended instructions, the last three bits.

It is envisaged that the data bus to main memory will be at least 96 bits wide, and, if longer, some power-of-two multiple of 96 bits.

To avoid crossing the boundaries of memory words with Floating (or Alternate Integer) numbers or Double numbers, one technique that is available would be to store them at a regular spacing of 96 bits, where each 96-bit memory word would contain one Floating number (36 bits long) and one Double number (60 bits long) in either order. Elaborations of this basic technique for computer architectures with different basic word lengths will be discussed later in this section, on this page.

The basic unit of memory in this machine is 12 bits long. Two of those units are 24 bits long, and three 8-bit bytes will fit into 24 bits. Thus, Byte instructions are regarded as aligned when the last bit of the address field is zero.

Only the first of three bytes in a 24-bit word can be addressed by such a memory-reference instruction in the absence of indexing. Note that a register-to-register Byte instruction operates on the least significant 8 bits of the registers involved, while a memory-reference Byte instruction operates on the byte in memory immediately at the address provided, thus in the most significant 8 bits of the 24-bit quantity addressed. This follows the general pattern of memory-reference instructions, since 12-bit and 24-bit quantities addressed by memory-reference instructions begin with the 12-bit memory cell actually addressed, rather than being in the last 12 bits or the last 24 bits of a 48-bit expanse of memory, in order to imitate the width of an integer register.

When an index register, 1, 2, or 3, is specified to be used with a Byte instruction, instead of providing a normal displacement in units of 12 bits, the displacement is in 8-bit bytes.

However, one byte in every 33 bytes is skipped in order to avoid the need to divide the index register contents by three in order to produce a conventional memory address that points to a 12-bit memory cell, or (after being shifted right three places) a 96-bit memory word.

33 bytes occupy eleven 24-bit words. If only 32 of them are used, then address generation can proceed as follows: the last five bits of the index register contents are used, basically, as an index into a table which indicates which byte of which 24-bit word is to be used, and the remainder of the index register contents are first shifted right five bits, and then multiplied by eleven to obtain a displacement in normal units of 24 bits (which can then be shifted left one bit to obtain a standard address in units of 12-bit memory cells, or shifted right two bits to obtain a physical address in units of 96-bit memory words).

This basic technique, as applied to putting 36-bit and 51-bit floating-point numbers in a 256-bit memory word, or as applied in the general case, will be discussed later in this section on this page.

There is enough opcode space to permit providing for other important types of instruction:

The prefixed instructions are designed to minimize the overhead of using types, such as 48-bit floating-point, not provided for in the basic register-to-register or memory-reference instructions; instead of lengthening each instruction by 12 bits, a single 24-bit prefix can provide for a large number of instructions.

Each instruction within the group of instructions so prefixed has a 4-bit opcode, indicating the operation it performs, and one bit to indicate which of two data types, A or B, applies. The first bit of the instruction distinguishes between 12-bit register-to-register instructions and 24-bit memory-reference instructions. The second bit is always zero, except in the last instruction in the sequence of prefixed instructions, indicated by it being a one. Because the normal opcode in a 24-bit memory-reference instruction is only five bits long, the choice of which base register to use for all memory-reference instructions in the sequence of prefixed instructions is made in the prefix.