Contents copyright Tom Jennings 1999-2002




Operators Manual

for the

Universal Machine






(preliminary design draft)

15 December 2001





















Tom Jennings

World Power Systems

1 February 2001


CONTENTS


NOTES ON THE PRELIMINARY DRAFT 3


OPERATORS CONTROL PANEL 4

Indicators 4

Control switches 5

Examine circulator contents 6

Modify circulator contents 6

Examine drum sector 7

Modify drum sector 7

Stepping orders


THE VIRTUAL MACHINE 9

High speed storage 10

Drum organization 10

Optimum coding 13

Flip-flops Cy and Z 14

Order word format 14

Order execution 15

Order types 16


MACHINE ORDER DESCRIPTIONS 18

Drum operand orders 18

Literal orders 20

Other digit manipulation orders 22

Skip orders 23

Machine control orders 25


THE AUTOMATIC COMPILER 26

Teletype characters 27

Orders 29

Constants and numbers 29

Named variables 29

Meta-orders 30


PROGRAMMING CONVENTIONS 32


POWER CONTROL PANEL 33


LIBRARY ROUTINES 34

APPENDIX A: Order codes

APPENDIX B: Teletype characters 41

APPENDIX C: Powers of two 43

APPENDIX D: Initial orders 44

NOTES ON THE PRELIMINARY DRAFT.


This is the functional description of the logical machine. The peculiar writing style is entirely intentional; it is an unapologetically revisionist crib of Wilkes' 1951 Preparation of Programs for an Electronic Digital Computer, with a few major deviations, all of which are to take advantage of a half-century of computer culture and experience: logical and physical concepts are entirely separated; the modern notion of a 1970's-style "assembly language" is built-in; now-routine (pun intended) and natural-seeming linkage of subroutines are not treated as so dificult and abstract as they seemed in 1950. Wilkes' system is very hard to follow with modern eyes, since he has entangled his cobbled-up teletype code with machine definitions (of course this is no criticism of Wilkes' groundbreaking work of programming technique on the world's first fully-functional stored-program computer, though he did benefit from the organizational theft of Turing's work).


Also note that the cultural-assumption gulf from then til now is huge, for items small and large. With a few notable exceptions (eg. today a non-linear memory organization would get chapter to itself; in this machine the ramifications are barely hinted at; (the concept of a "character" vs. a teletype "letter", long since settled with character code standards), any anachronisms that cropped up were disposed of in favor of modern constructs, because it doesn't matter how nifty it is if no one can understand it.


The very existence of the "automatic compiler " (aka assembler) is an anachronism, as such things were not widely considered a good idea in 1955, even, and the two-pass assembler here is very1975.


Further, many of the sections are simply incomplete. This version is not intended to be complete, but only to impart the flavor of the final project, though it does in fact represent more or less what is currently the "final" design.


--tomj 20 June 2001

OPERATOR'S CONTROL PANEL


The control panel on the front of the Machine directs the initial and overall operation of the machine. The control panel is used to initiate program loading, both manually and from tape, into the main drum store, and may be used for manually examining and modifying drum contents, and for running programs one order at a time to isolate problems within a program.


The control panel contains switches with which the operator manipulates the workings of the machine, and indicators that respond to events and status within the machine, both manually instigated and during automatic operation.



INDICATORS


The RUN and STOP lamps indicate whether or not the Machine is executing orders. The Machine remains in the STOP state until the RUN switch is depressed (presumably a program has already been loaded, as described in later sections). Once running, the machine will stop when the STOP switch is depressed or a HALT order is encountered.


The LAMP REGISTER, containing 18 lamps corresponding to the 18 digits in a word, displays the contents of either circulator A, C or K, or the drum sector whose address is contained in circulator C, depending on the position of the LAMP REGISTER FUNCTION switch. (The latter is labeled "D" on the switch.)



Additional lamps indicate the internal state of the Machine during the operation of a program or routine. For every order encountered, the Machine passes through four discrete states in turn:


  1. FETCH:SEARCH The drum location containing the order is found.

  2. FETCH:LOAD The order is read from the drum and decoded.

  3. EXECUTE:SEARCH If required, drum location containing operand found.

  4. EXECUTE:RUN The order is executed.


The FETCH lamp is lit when the machine is in either of the first two states, when an order is being located on the drum or loaded into machine. (It will be lit more brightly when the machine is stopped.)


The EXECUTE lamp is lit when the machine is executing an order or locating a drum-stored operand, eg. when the machine is in the RUN state.


The MEMORY-SEARCH lamp lights during the first or third states, when the drum is searching for the order to execute or the operand possibly required by the previously-fetched order. The third state is skipped (more accurately, it becomes one digit-time in duration rather than one minor cycle in duration) if the most recently fetched order does not indicate a drum operand is required.



The CARRY and ZERO lamps directly display the current state of the Cy and Z flip-flops, respectively. The of these flip-flops are covered in other sections of this manual.


Each subassembly of the Machine has its own set of indicators that display more detailed status of program and machine operation that may be of use to the skilled operator, but these are outside the scope of this manual. Please refer to the Hardware Reference manuals for details.



CONTROL SWITCHES


Manual control switches provide direct manipulation of the Machine, sufficient to manually enter initial orders, provide input to running programs, or to examine and modify errant programs.


The STOP toggle switch, when raised, halts an executing program after the current order is complete, leaving the machine in the STOP state. Raising STOP does not modify the state of the machine nor any circulator contents, therefore, raising STOP switch can be considered an arbitrarily long pause in program execution, if followed by pressing the START switch. Raising the STOP switch has no effect if the machine is in the STOP state.


The START momentary switch initiates continuous program operation (if the STOP toggle is in the lowered position) or a single order is executed (STOP toggle in the raised position). In either case the first, or only, order executed is the drum location indicated by the contents of register C. If a running program was stopped with the STOP switch it may be restarted at any time with the START switch. Please note that if any changes were made to drum contents or any of the circulators it may not be possible to resume a paused program without manually restoring the contents of the A and C circulators.


The RESET switch, operable only when the machine is in the STOP state, clears all circulators to zeros, resets the Cy and Z flip-flops, sets the teletype output digit to the marking state, etc. It does not modify drum contents.



The SWITCH REGISTER FUNCTIONrotary determines what is displayed in the LAMP REGISTER, either register A, C, K, or the contents of the drum sectors whose address is the contents of C, labelled "D" on the front panel. This switch has no effect on the operation of the machine and may be changed at any time. The operator may find this less than useful while a program is running.


The SWITCH REGISTER consists of 18 switches which correspond to the 18 digits in a word. It can control execution of running programs with the use of the SWA order, or when the machine is in the STOP state, used to specify new contents for circulators A or C, or the drum sector whose address is contained in circulator C, when the STORE-A, STORE-C, STORE-D switches, respectively, are pressed. The most-significant 6 digits of the switch register are ignored when modifying register C.


When the SWITCH REGISTER is used as programmatic input, it is generally convenient to first execute a HALT order to stop the machine at the point at which it is desired to read the switch register; instructions to the operator then consist of making the appropriate settings on the switch register then pressing START.



EXAMINE CIRCULATOR


At any time the LAMP REGISTER FUNCTION rotary switch can be used to examine the contents of circulators A, C, or K, causing them to be written to the LAMP REGISTER. This is mostly useful when the machine is stopped.



MODIFY CIRCULATOR


The STORE-A, STORE-C, and STORE-D momentary switches cause the contents of the SWITCH REGISTER to be written into the circulator A or C, or D, the drum location specified by C. The machine must be in the STOP state for these switches to be functional. PLEASE NOTE that modifying D leaves circulator A in an indeterminate state; if the contents of A must be maintained it must be done so manually by the operator.


The INCREMENT-C momentary switch causes one to be added to the current contents of the C circulator, when the machine is in the STOP state. This is useful when examining or modifying sequential drum locations.


EXAMINE DRUM SECTOR


It is assumed that the machine is in the STOP state.



MODIFY DRUM SECTOR

 

It is assumed that the machine is in the STOP state.



PLEASE NOTE that this operation modifies the A circulator; if its contents must me maintained (eg. A program is being repaired before it is restarted) the contents of A must be recorded and restored manually.



STEPPING ORDERS


The high speed of program execution sometimes paradoxically interferes with identifying and repairing problems within programs. The control panel provides a single-order-step function to help with location logical problems within programs.


With the Machine in the STOP state:



With each pressing of the RUN switch thus, one order only will be executed. Registers and drum may be examined as necessary. Please note that the operator must restore the contents of any circulators modified, and the accumulator if drum contents are modified.


Additionally, the operator may find it useful to place HALT orders in strategic locations throughout a program under development; after examining registers and drum contents, and possibly modifying these, pressing the RUN switch will continue executing the program beginning with the order following the HALT order, unless otherwise modified.


A further technique might involve reading the SWITCH REGISTER with the SWA order, and conditionally executing the HALT order as above, or instead other orders convenient for testing.



THE OPERATOR'S VIRTUAL MACHINE


[This is an utter anachronism, this "virtualized" machine, a far too modern view of things, but really, without which the major point of this project (making the obscure more visible) would be incomplete.]


The basic machine organization is that of a single rotating magnetic drum comprising the sole store, and a logical control that executes orders stored on the drum. A teletype and paper tape reader and punch provide input/output facilities and program storage.


From the operator's point of view the machine consists of the following:




ONE ADDRESS ARCHITECTURE


This machine provides 26 unique orders that operate on the high-speed and main store and other machine facilities. The orders and their format is described in detail in the ORDER WORD FORMAT section.


This machine uses a one-address order code, and each order contains a 12-digit field that may refer to a drum store location. The location of the "next order" to execute is taken to be the current location plus one, unless directed to a different location by machine orders themselves. (The address of the current/next order is contained in the C circulator.)


Order execution is covered in more detail in later sections.


HIGH-SPEED STORAGE


There are three circulators and two flip-flops that provide high-speed storage for symbols, known by their single-letter names:


Most significant digit Least significant


A: |17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|


C: |11|10|09|08|07|06|05|04|03|02|01|00|


K: |11|10|09|08|07|06|05|04|03|02|01|00|


Z: |00|


Cy: |00|


The numbers indicate both the relative position of each digit in this document as well as the power-of-two exponent for that digit's position.


All of the machine orders operate upon one or more of these high-speed storage components, as described in the MACHINE ORDERS section below. The circulators have a maximum access time equal to the minor cycle time; there is no additional rotational latency incurred.


Please note that the K circulator is somewhat of an abstraction, being in fact the K field of the order code. It cannot be modified during order execution, though it can be modified while the encompassing order is stored on the drum, before it is executed, using the STA or STO orders.



DRUM ORGANIZATION


The sole store for orders and data is the rotating drum memory of [approximately 4096] 18-bit words, stored on N drum tracks. The drum rotates on its axis, and a row of electromagnetic read/write heads are fixed along the length of the drum. As the drum rotates, a circumferencial track of the drum passes under each fixed read/write head. This drum track is logically considered as 64 radial sectors, each of which contains one storage word. An index mark inscribed elsewhere on the drum determines the 0th sector on all tracks.


There are no "read-around" issues or other limitations on how the main store is accessed.

Drum track and sector comprise a unique address for each sector, and are packed into the address field of each order as follows:


12 0

M 0

T T T T T S S S S S S S

|<------constant----->|


T Specifies the track number, 0 - N

S Specifies the sector number, and runs 0 to 63


[NOTE: IF SECTORS PER TRACK IS NOT A POWER OF TWO:] Note that if the last sector of a track contains an order, that order must be a JUMP to another sector address, and the second-last order should not be a SKIP.


Sectors are not in fact numbered sequentially within each track, but with an increment of 4, so that sequential access to every sector within a given track, (eg. 0, 1, 2, 3, 4, ...63) requires 4 complete revolutions of the drum. The reason for this is that the minimum order execution time is three minor cycles to complete; therefore for those orders that do not refer to a drum-located operand, the "next" order (as indicated by the contents of the C circulator) is just reaching the drum read head in time for its execution. (One minor cycle is required for the address comparison, hence the skew factor is 4, not 3.)


However, for most practical purposes, the drum sectors can be considered as sequential with a location-to-location access time of 4 times the drum rotation time:


Minimum main store access time = 800 microseconds


This obviously implies that orders that refer to a drum operand incur additional delays locating the operand, which may in fact be placed anywhere on the drum's surface, at the convenience of the operator. The sector skew table in the OPTIMUM CODING section should be referred to to determine optimum coding locations.


The actual delay can be calculated as follows:


(|S - C + 1| * 800 uS + T) + (|C - S| * 800 uS + T)

where

C is the contents of the C circulator,

S is the contents of the operand field, sector adress

T is 0 if the operand is located in the same track as the current order,

else 20mS if the operand is contained in a different track.


Clearly it is in the operator's interest to keep frequently-accessed drum locations on the same track wherever possible. However rotational latency cannot be completely overcome, though it can be minimized through careful design.

OPTIMUM CODING


Due to the serial nature of the drum storage mechanism, unless the operator takes painstaking care in laying out his program around the drum, programs will execute quite slowly, with an average order execution time of ½ a drum revolution period. This can be objectionably slow but with care can be markedly improved with optimum coding.


Optimum coding is the technique of placing orders and temporary storage locations in strategic sectors within a track, and in general arranging orders to account for rotational latency. For example, the Gill Test for this Machine was improved by more than a factor of 20 in execution speed merely by placing variable storage in optimum sectors.


To facilitate these calculations, please refer to the following sector skew table. Many organizations of this table are possible; this one lists the logical sector numbers in physical order starting with the 0th sector (which is un-skewed). For example, for an order at location 24 (decimal) the "next" sector (mimimum latency) is sector 4; the next-least latency, 1000 uS, is sector 21, etc.



Skew table, 64x4, decimal

00: 0 16 32 48

04: 1 17 33 49

08: 2 18 34 50

12: 3 19 35 51

16: 4 20 36 52

20: 5 21 37 53

24: 6 22 38 54

28: 7 23 39 55

32: 8 24 40 56

36: 9 25 41 57

40: 10 26 42 58

44: 11 27 43 59

48: 12 28 44 60

52: 13 29 45 61

56: 14 30 46 62

60: 15 31 47 63

Skew table, 64x4, octal

00: 0 20 40 60

04: 1 21 41 61

10: 2 22 42 62

14: 3 23 43 63

20: 4 24 44 64

24: 5 25 45 65

30: 6 26 46 66

34: 7 27 47 67

40: 10 30 50 70

44: 11 31 51 71

50: 12 32 52 72

54: 13 33 53 73

60: 14 34 54 74

64: 15 35 55 75

70: 16 36 56 76

74: 17 37 57 77




[This section to be greatly expanded.]

FLIP-FLOPS CY AND Z


There are two flip-flops that can be used to direct order execution. Each is set (equal to value of 1) or reset (equal to a value of 0) by intentional side effects of certain arithmetical and logical orders. Other orders may then use the state of the flip-flops as implicit operands or to control the order execution order conditionally upon the value of either flip-flop.


The Z flip-flop is modified during the execution of certain arithmetical/logical orders such that it is set to "1" when all digits of A are zero, and reset to "0" if any one or more digits of A contain 1. It is specifically not modified by any other orders.


The CY flip-flop is modified similarly by the arithmetic orders, being set to "1" if there is arithmetic overflow during addition, or cleared to "0" otherwise. The RLC order shifts the most-significant digit of the accumulator into the CY flip-flop. CY is cleared to zero by certain other logical orders.



ORDER WORD FORMAT

17 11 0

W M 0

X O O O O O K K K K K K K K K K K K

|<order>| |<------constant----->|

or

17 11 0

W M 0

X O O O O O T T T T T T S S S S S S

|<order>| |<---drum location--->|



The order field is a 5-digit field that defines the order code, described below. The most-significant digit, 17, of an order is undefined and may take any value, 0 is generally is assumed.


The meaning of bits 0 through 11 depend on the particular order. They can contain a literal unsigned constant operand in the range of 0 through 4095, the drum address of the order's operand, or it may be undefined. When used as a drum address it is takes the form defined in the DRUM ORGANIZATIONsection. Orders that refer to an operand stored on the drum have a variable execution time, as the time needed to access the specified drum location depends on the current and desired drum addresses.


NUMBERS


When the contents of circulators and drum storage locations are treated as a numerical value, the following conventions are assumed, especially as they pertain to the arithmetical operations of the machine. These are of course only conventions for the convenience of discussion, and these assumptions can be modified in any way consistent with the operation of the machine.


All arithmetic operations assume operands to be positive, unsigned integers, with the least-significant digit to be the right-most digit when written on paper in the conventional manner. All machine operations on storage or circulator words begin with the least significant digit, proceeding to the most-significant, and during addition, propagating carry from the previous (lesser) digit's addition.


Subtraction and negative numbers in general can be done using two's-complement conventions. Addition of the two's-complement 'subtrahend' (made with the COM n order) effectively subtracts, with borrow indicated by the Cy flip-flop.



ORDER EXECUTION


Orders are executed sequentially as they are read from the drum unless the sequence is modified by orders themselves, as is often the case. The initial starting location is determined by manual setting of the machine's switch panel (see the OPERATOR'S CONTROL PANEL section), programs traditionally starting afresh from track 0 sector 0. Once a program is started, the program itself is in complete control of order execution (including unintentional errors).


The location of the 'next' order to execute is held in the C circulator. During the execution phase of each order, the contents of circulator C increases by one. There are orders that directly modify the contents of the C circulator.


When it is time to execute the next order, wherever it might be on the drum, the control circuitry selects the desired drum track (delaying as necessary for the control circuitry to catch up) and waits for the desired sector to rotate under the read/write head of that track. The amount of time required to locate the target sector depends on the angular distance from the current sector; it can be as little as four minor cycles (four word times), or nearly one major cycle, or one full drum revolution.


Therefore, order execution time depends on the distance the drum must rotate and is quite variable, and must be taken into account when designing time-sensitive programs. The use of per-track sector layout sheet (and a lot of practice) makes this task easier. Please refer to the OPTIMUM CODING section for more details.



ORDER TYPES


It is occasionally useful to group orders by the type of functions they perform. Note that many orders allow for side effects, intentional or otherwise, that can be exploited to achieve goals not necessarily defined here. [The subject of backwards compatibility and exploitation of "undocumented" effects actually deserves a paragraph unto itself, or even a whole history.]


Arithmetic and logical orders


Arithmetic and logical operations are performed on the accumulator and either a drum word or a literal operand contained in the order (K). The results of the operation are always placed in the accumulator, and may modify the Z or Cy flip-flops, depending on the particular order. When a drum location is the operand the drum track and sector specified in the order must be searched for; therefore the execution time of the order is dependent on the difference between the current track/sector and the desired location; as little as four minor cycles or nearly one major cycle. If the operand is literal then the order execution time is fixed at four minor cycles.



Skip and jump orders


Seven orders are provided that can be used to modify order execution sequence. The JUMP order modifies the contents of C and therefore causes orders to be next executed at a specified drum address. Six instructions modify order execution by incrementing the C circulator by one, thereby skipping the order immediately following the skip order: four dependent on the state of one of the Cy or Z flip-flops, and two dependent on the current state of the teletype input line.



Drum-access orders


The only way to modify drum contents under program control is with the STO or STA order, which write all 18 or the least-significant 12 bits of a drum location, respectively. Drum contents can be read, explicitly with the LDM order or implicitly with the xxxM arithmetical/logical orders.



Z and Cy flip-flops


The Z and Cy flip-flops are modified by the arithmetical and logical orders, and indicate the result the most-recently-performed arithmetical and logical order. Either flip-flop may be subsequently 'tested' with other orders and used to determine program execution, and in some cases their numeric value (0 or 1) can be incorporated into calculations directly. Z and Cy remain unchanged until the next arithmetical and logical order.


Z is set when the result of an arithmetical and logical order results in all digits of the A circulator equal to zero. Orders that modify program execution depending on the state of Z are SZ andSNZ. Orders SC and SNC can be used to modify program execution depending on the state of Cy, or Cy can be incorporated into calculations directly with the RLC, ADC, ADCM orders.


MACHINE ORDER DESCRIPTIONS


The following paragraphs define the individual machine orders, and provide a complete description of the effects and side-effects of each order.



DRUM OPERAND ORDERS


For the following orders digits 0 through 11 contain the packed track:sector address of the operand stored on the drum. Execution times for these orders are therefore dependent on the track displacement and rotational distance between the order location and that of the desired location.


LDM address

17 11 0

W M 0

X 1 0 1 1 1 T T T T T S S S S S S S

|<order>| |<---drum location--->|


The contents of the specified drum sector are written into the acumulator. Z and Cy are unaffected.


ADDM a

17 11 0

W M 0

X 1 0 0 1 0 T T T T T S S S S S S S

|<order>| |<---drum location--->|


Add the contents of the specified drum sector plus A and place the result in A. Sets Z and Cy modified as described in the text.


ADCM a

17 1 0

W M 0

X 1 0 0 1 1 T T T T T S S S S S S S

|<order>| |<---drum location--->|


Add the contents of specified drum sector plus Cy plus A and place the result in A. Sets Z and Cy as described in the text.


ORM a

17 11 0

W M 0

X 1 0 1 1 0 T T T T T S S S S S S S

|<order>| |<---drum location--->|


Merge the contents of the accumulator with the specified drum sector contents such that there is a 1 in every digit position of the accumulator where there is a 1 in the same digit position of either or both of the accumulator and the drum location. Sets Z accordingly, Cy is always cleared.


ANDM a

17 11 0

W M 0

X 1 0 1 0 1 T T T T T S S S S S S S

|<order>| |<---drum location--->|


Merge the contents of the accumulator and the specified drum location contents such that there is a 0 in every digit position of the accumulator where there is a 0 in the same digit position of either or both of the accumulator and the drum location. Sets Z accordingly, Cy is always cleared.


STO a

17 11 0

W M 0

X 1 1 0 1 0 T T T T T S S S S S S S

|<order>| |<---drum location--->|


Write the contents of the accumulator into the specified drum sector. Z and C are unaffected.


STA a

17 11 0

W M 0

X 1 1 0 0 1 T T T T T S S S S S S S

|<order>| |<---drum location--->|


Write the least -significant 12 digits of the accumulator into the least-significant 12 digits (address, K) of the specified drum sector, leaving the most-significant 6 digits unmodified. The intent is that the specified memory location contains an order whose address field is being modified. Z and Cy are unaffected.




LITERAL ORDERS


For the following orders K is a literal unsigned operand, in the range of 0 to 4095 (digit positions 0 through 11). K is extended to 18 bits with zeroes. The drum is not referenced, therefore execution time for these orders is fixed at four minor cycles.


LD k

17 11 0

W M 0

X 1 0 0 0 1 K K K K K K K K K K K K

|<order>| |<------constant----->|


Write value K to the accumulator. Z and C are unaffected.


ADD k

17 11 0

W M 0

X 0 1 1 1 0 K K K K K K K K K K K K

|<order>| |<------constant----->|


Add constant K plus A and place the result in A. Sets Z and Cy as described in the text.


ADC k

17 11 0

W M 0

X 0 1 1 0 1 K K K K K K K K K K K K

|<order>| |<------constant----->|


Add constant K plus Cy to A and place the result in A. Sets Z and Cy.


OR k

17 11 0

W M 0

X 1 0 0 0 0 K K K K K K K K K K K K

|<order>| |<------constant----->|


Merge the contents of the accumulator with constant K such that there is a 1 in every digit position of the accumulator where there is a 1 in the same digit position of either or both of the accumulator and the drum location. Sets Z accordingly, Cy is always cleared.


AND k

17 11 0

W M 0

X 0 1 1 1 1 K K K K K K K K K K K K

|<order>| |<------constant----->|


Merge the contents of the accumulator with constant K such that there is a "1" in every digit position of the accumulator where there is a "0" in the same digit position of either or both of the accumulator and the drum sector. Sets Z accordingly, Cy is always cleared.



JUMP k

17 11 0

W M 0

X 1 0 0 1 0 K K K K K K K K K K K K

|<order>| |<------constant----->|


The constant value K is written to circulator C, therefore the next program order executed will be from that drum location. While this order takes only four minor cycles to execute, the fetch of the next order will be as calculated for the drum-addressing orders above. Z and Cy unaffected.


LDA k

17 11 0

W M 0

X 1 1 0 0 0 K K K K K K K K K K K K

|<order>| |<------constant----->|


This order is exactly identical in operation to LD. LDA exists solely to allow differentiating constant-K orders from constant-address orders in order to facilitate automatic programming techniques. Z and Cy are unaffected.




OTHER DIGIT-MANIPULATION ORDERS


The following orders perform various logical and arithmetical operations on the accumulator.



SR k

17 11 0

W M 0

X 0 1 0 0 0 K K K K K K K K K K K K

|<order>| |<------constant----->|


The contents of circulator A are first divided by two, then summed with K, the result then placed in circulator A. Z is set if the result in A is zero, and Cy is always cleared (since overflow due to the addition is not possible). When K is zero, this causes the accumulator to be simply shifted right one place.


RLC

17 11 0

W M 0

X 0 0 1 1 1 X X X X X X X X X X X X

|<order>| |<------constant----->|


The contents of the accumulator are modified as follows: all digits are shifted one position to the left; the contents of the Cy flip-flop is placed in the right (least-significant) position; the previously most significant digit shifted off the left (most significant) end is placed in the Cy flip-flop. In other words, the accumulator and Cy flip-flop are treated as a 19-bit ring counter that is shifted one position counterclockwise. Z and Cy are set accordingly.


COM k

17 11 0

W M 0

X 0 1 0 0 1 K K K K K K K K K K K K

|<order>| |<------constant----->|


Invert all of the bits in the accumulator (0's become 1's, 1's become 0's) and add K, placing the result in the accumulator. If K is 0, then this instruction performs a one's complement; if 1 then it performs a two's complement. Z and C are set accordingly.


SKIP ORDERS


The following orders modify the sequence of order execution under influence of the program itself, by meeting specified states of the Z and Cy flip-flops or the state of the teletype input line. The Z, Cy and teletype input line remain unaffected. For these orders the k field is undefined.


SZ

17 11 0

W M 0

X 0 0 0 1 1 X X X X X X X X X X X X

|<order>| |<------constant----->|


SNZ

17 11 0

W M 0

X 0 0 1 0 0 X X X X X X X X X X X X

|<order>| |<------constant----->|


SC

17 11 0

W M 0

X 0 0 1 0 1 X X X X X X X X X X X X

|<order>| |<------constant----->|


SNC

17 11 0

W M 0

X 0 0 1 1 0 X X X X X X X X X X X X

|<order>| |<------constant----->|


These orders cause 1 to be added to the C circulator if the specified condition is met, causing the next order to be skipped. The conditions are:


Z the last arithmetic order left all bits of the accumulator clear

NZ the last arithmetic order left at least one bit set in the accumulator

C(y) the last arithmetic order generated an overflow condition

NC(y) the last arithmetic order did not generate an overflow condition


[IF SECTORS/TRACK NOT A POWER OF TWO:] It is recommended that skip instructions not be executed in the last sector on a track.

STZ

17 11 0

W M 0

X 0 1 0 1 0 X X X X X X X X X X X X

|<order>| |<------constant----->|


STNZ

17 11 0

W M 0

X 0 1 0 1 1 X X X X X X X X X X X X

|<order>| |<------constant----->|


Adds 1 to the C circulator if the condition is met, causing the next program order to be skipped. The condition is teletype input false (STZ) or true (STNZ). This order is the basis for the entire IO structure; it is strenuously recommended that the library routines provided with the machine be used unless very careful consideration is given to the consequences. Serial data appearing at the interface is thereby made procedural, the serial data is reconstructed by orders before and after this order.


AND 0 # clear the acumulator,

STNZ # if data asserted,

OR 1 # recreate it here.


MACHINE CONTROL ORDERS


These orders control or are influenced by various hardware aspects of the Machine.



TTO

17 11 0

W M 0

X 0 1 1 0 0 X X X X X X X X X X X X

|<order>| |<------constant----->|


Asserts the least-significant digit of A onto the teletype or paper tape punch output flip-flop. This is the sole output mechanism. Teletype word assembly and timing is done by careful placement of words around a dedicated track. It is strongly recommended that the teletype routines provided with the machine be used.


SWA k

17 11 0

W M 0

X 0 0 0 0 1 K K K K K K K K K K K K

|<order>| |<------constant----->|


The 18 switches of the operator's console SWITCH REGISTER are written to the accumulator, a 1 being written in digit positions where the switch is in the "up" position, otherwise a zero. Z and Cy are not affected.


HALT k

17 11 0

W M 0

X 0 0 0 0 1 K K K K K K K K K K K K

|<order>| |<------constant----->|


General machine control order. TBD.

THE AUTOMATIC COMPILER


[DRAFT notes: aka the assembler, currently there is only the Perl assembler, which is undoubtedly a superset of any native compiler, should such a thing get written. Also at this time the binary loader and loader format is TBD.


[To be inserted here also is a complete explanation and justification for 30 years of base-level assumptions about line-oriented input (unless it becomes tootedious).]


The Automatic Compiler is the primary way to produce sequences of orders for solutions to problems using the Universal Machine. It accepts as input a sequence of teletype characters arranged as described in this section that describe machine orders, drum storage locations, constants and variables, and meta-orders that control the interpretation of the stream of characters from the input tape; this arrangement of teletype characters thus becomes an abstract description of a program of orders to perform any function.


The end result of a successful run of the automatic compiler against an input tape is the production of an output tape that contains the actual machine orders to perform the functions abstractly described by the programmer.


In addition, programs can be assembled using libraries of previously worked-out and tested routines stored on one or more input tapes. Further, the machine is provided with standardized drum-resident routines for commonly used functions such as teletype I/O, printing, and arithmetical routines.


[DRAFT note: a whole section tying the above summary to a sample input tape, including teletype-printable representation, etc, will be inserted here. Mainly the rest of this section is devoted to documenting the Perl assembler functions. I know that you know how to use an ordinary1970-style two pass assembler.]



TELETYPE CHARACTERS AND THEIR MEANINGS


As the input tape is read, the Compiler interprets the characters read one by one. The meaning of each character depends entirely on the current state of the internal turing machine and characters previously read. At each Compiler state, certain characters cause the Compiler to change state, possibly punching other characters to the output tape. Please refer to Appendix A for a complete list of teletype characters and their representations in the Universal Machine.


The arrangement of these internal states causes the Compiler to maintain a perceptible set of semantic and syntactical rules which the programmer must follow. Luckily, most of these resulting rules follow an "english-like" form as to make for easy memorization. [This is obviously swiped from Knuth, especially as embodied in TeX -- even though the Perl compiler is the usual atrocity and in no way is the code this elegant.]


Characters are considered to be in the following groups:



Whether a given character is allowed depends entirely on the current state of the Compiler's internal turing machine. The current state can be understood by referring to figure XXX, below, which represents a series of example characters from the input tape:


[picture of punched tape here]

Fig. XXX


Perforations on a fragment on that sample input tape might contain:


cr lf nul nul sp sp sp A N D sp sp 3 1 sp sp sp sp # r e t a i n sp t h e sp ... sp A cr lf nul ...


which produces the following when printed on the teleprinter:


Printed result: | AND 31 # retain the 5 least digits of A |

Machine state: 0 1 2 3 4 5 0


The "state" number indicates what the compiler will allow on the input tape without producing an error. As you can see the states correspond reasonably to formatted text:


STATE EXPECTS

0 separator(s), or a label (described below)

1 order or number

2 separator(s)

3 value, if required by order (described below)

4 separator(s), if a value follows an order

5 program note


State becomes 0 when a cr or lf is read from the tape; an error results if a required state (eg. 3) is missed. The # character causes the compiler to ignore all input characters until the next CR or LF is read.


In this document we will refer exclusively to the convenient representation of characters as displayed on a teleprinter, though it is assumed that the programmer recognizes the underlying tape contents.

ORDERS


Machine orders are represented by names composed of letters, as described in the MACHINE ORDERS section. Many orders require an operand, which must follow the order name, separated by one or more separator characters. An operand may be a number, character constant, or named variable, or an expression containing any or all of the above.



NUMBERS


All numbers are treated by the compiler as unsigned integers, in the range of 0 to 262144, expressed on the input tape in one of three input radix as indicated by a leading character. Further, the allowed digit-characters depends on the radix character that proceeds them:


0 100 77777 262144 decimal values

$0 $100 $77777 $777777 octal values

.100 .111111111111111111 binary values



CHARACTER CONSTANTS


Often it is convenient to use a teleprinter character in an expression, and the following has been provided to do so:


'X


This refers to the numeric value of the letter X, represented as a six-digit code, where the lower five digits are the standard teleprinter character code, and the sixth, most-significant digit is "1" for characters in the FIGS case, and "0" otherwise; in this example the result is decimal 29. Please refer to Appendix A for a complete list of character codes.



NAMED VARIABLES


The compiler provides a mechanism for assigning numerical values to arbitrary six-character named symbols, which can be used anywhere a number or character constant is required. In fact there are a number of ways in which values are assigned to names, designed for the programmers convenience.


First, symbols can be defined explicitly by the EQ meta-order, described below. Secondly, it is often convenient to assign the "current" order (drum) location to a variable for later reference in a program (eg. For programmatic looping); this is done by starting a symbol name with the first character following the CR or LF ending the previous line of input, where the Compiler would otherwise be expecting state "0". Third, the machine orders themselves are in fact simply variables, pre-defined by the Compiler, and can be used as numbers (this is of dubious value). And last, the "current" drum location is always referenced by the reserved variable name C.


In fact the use of symbols by the compiler is very simple. The compiler maintains a table of named variables and their values, and any time a a letter appears where a number (or radix indicator) is expected, the letter and the characters that follow it are looked up in the table. If a match is found, the value associated with that name is assumed. If the name is not found in the table, an error is assumed. Note that this useful trick may produce surprising results when typing mistakes are made.


Note that this scheme places limitations on the characters allowed in symbol names: they must begin with a letter, but may then contain letters and or digits, up to six positions.



META-ORDERS


In addition to the symbolic machine orders listed in previous sections, the compiler provides the following meta-orders that direct how the compiler treats subsequent orders. They may assign numeric values to symbolic names, or determine into which drum location orders or data is to be stored.


Meta-orders, like orders, must be preceeded by at least one space character [IS THIS TRUE?]. If an order requires or accepts additional parameters they must follow the order/meta-order by at least one space character.


TRACK n


Specifies the track into which subsequent orders or data will be stored. The track must physically exist or an error will result.


SECTOR n


Specifies the initial sector n within a track into which subsequent orders and data will be stored. Thereafter orders/data are stored sequentially, up to the maximum sectors in a track. The compiler produces an error if the maximum sector would be exceeded.


SYMBOL EQ n

SYMBOL: [Maybe eliminate this]


These two meta-orders assign a numeric value to a named variable. [The first form ]explicitly assigns n to the symbol. Note that n in turn may itself be a symbol, but it must already be defined when this meta-order is encountered or an error will result.[The second form assigns to the name the "current" drum location, usually to symbolically render a specific order within a program sequence, and in general is equivalent to "SYMBOL EQ C". ]


TEXT /ijklmn/

TEXT "abc"

TEXT "s", 8, 4

TEXT n m o p q ...


[Note: This meta-order will be reexamined, and probably simplified.]


This meta-order stores packed character data into drum locations, three six-bit characters per word, starting with the right-most six bits of the location. As many drum locations as necessary are used to contain the data given. If the the character data provided is not a multiple of three, the unused "characters" in the drum word are filled with NUL (0's). If the number of characters is a multiple of three, an additional drum word of all zeros is added.


For the first two forms the initial character is used to bracket the character data; the initial character itself therefore cannot appear within, hence the definition of two allowable initial characters. For the first two forms only printable teletype characters can appear between the marker characters, specifically not CR, LF, BEL, etc. The third form can be used to enter characters of this type, where n m o p q are numbers or other allowable literal values.


Note further that the TEXT meta-order accepts any number of arguments, including intermixes of all three syntactical types.


See Appendix A for a complete list of teletype character codes.


STORAGE n


This meta-order is used to set aside a sequence of drum storage locations. The drum locations are not modified. Essentially, the compiler adds n to the the "current" sector value. An error is produced if there is not enough sectors remaining on the track.


PROGRAMMING CONVENTIONS


Subroutine linkage


The machine provides an order to support a modification of the EDSAC type "Closed A" subroutine linkage mechanism, supported by the automatic compiler.


To call a subroutine only the following orders are required:


r LDA (r + 2) # A is now equal to C + 2

r + 1 JUMP s # transfer control to subroutine s

r + 2 ... # next order to be executed upon return


After the execution of the LDA order in drum location r the accumulator contains (r + 2). The JUMPinstruction then transfers control to the subroutine.


The subroutine itself provides return linkage in the following manner:


s STA s + n # save the return address

s + 1 ... # intervening subroutine orders

s + n JUMP 0 # 0 address overwritten before execution


The subroutine, if it is to use the accumulator, must first store the return address passed to it; in general the most convenient is in the address (k) field of a JUMP order that will become the return linkage; the STA order has been provided for this purpose. After storing the return address the subroutine executes whatever orders it must, which may include other subroutines. To return to the calling routine, the address field of the JUMP order at drum location (s + n) already contains address (r + 2) and after execution the main routine will continue.


POWER CONTROL PANEL


[The controls and indicators relating to power on, power sequencing, standby, and any drum power requirements will be located on the POWER CONTROL PANEL elsewhere on the machine, and will remain TBD until engineering is done, but essentially there will be a power-sequencing regimen to avoid filament damage, restricted ambient temperature range, mechanisms to avoid problems (power-fail detection, etc). This will be at least partly automated with a microcontroller and solid-state power supplies.]



LIBRARY ROUTINES


The subroutine library consists of commonly used subroutines assigned fixed locations on the drum, as well as subroutines meant to be included into programs symbolically, as needed.


The fixed routines are actually only jump instructions to the actual routines, so that the routines themselves can be modified or improved without requiring already-written programs to be modified to match.


PASS 1

PASS 2

00:000 000000 # SOFTWARE LIBRARY ROUTINES FOR THE UNIVERSAL MACHINE.

00:000 000000 # MRU 2 JULY 2001

00:000 000000 # 25 JAN 2001

00:000 000000

00:000 000000 # NOTE! THIS PRELIMINARY CODE IS NOT OPTIMALLY CODED!

00:000 000000

00:000 000000

00:000 000000 RETURN EQ 0 # place-holder for return addresses

00:000 000000 POINTER EQ 0 # place-holder for runtime pointers

00:000 000000 VAR EQ 0 # place-holder for runtime variables

00:000 000000

00:000 000000 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

00:000 000000 # STANDARD JUMP TABLE LOCATION.

00:000 000000

00:000 000000 track 0

00:000 000000 sector 0

00:000 000000

00:000 225400 start: jump test # program entry

00:001 220001 ttyo: jump ttyo # (simulated)

00:002 220002 ttyi: jump ttyi # (simulated)

00:003 221015 ttyow: jump ttyowx # print packed chars

00:004 221000 ttyos: jump ttyosx # print string

00:005 221411 ttyod: jump ttyodx # print decimal

00:006 222000 ttyoo: jump ttyoox # print octal

00:007 220436 multUS: jump multUx # mult unsigned single

00:010 220400 multUD: jump multUDx # mult unsigned double

00:011 220061 m10: jump m10x # single mult by 10

00:012 000000

00:012 000000 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

00:012 000000 track 0

00:024 000024 sector 20

00:024 000000

00:024 000000 ttchar: VAR # ttyxx argument

00:025 000000 ttarg: VAR # ttyxx argument

00:026 000000 ttopt: VAR # ttyxx options

00:027 000000 zschar: VAR # zero-suppress

00:030 000000 errno: VAR # subr status

00:031 000000 Mper: VAR # multiplier

00:032 000000 Mcand: VAR # multiplicand or LSW

00:033 000000 Mcandh: VAR # multiplicand MSW

00:034 000000 Mtest: VAR # mult. routine

00:035 000000 MQ: VAR # quotient or LSW

00:036 000000 MQh: VAR # quotient MSW

00:037 000000

00:037 777777 minus1: -1 # constant

00:040 777772 minus6: -6 # constant

00:041 000000

00:041 000066 digtbl: '0 # table of digits

00:042 000067 '1

00:043 000063 '2

00:044 000041 '3

00:045 000052 '4

00:046 000060 '5

00:047 000065 '6

00:050 000047 '7

00:051 000046 '8

00:052 000070 '9

00:053 000003 'A

00:054 000031 'B

00:055 000016 'C

00:056 000011 'D

00:057 000001 'E

00:060 000015 'F

00:061 000000

00:061 000000 # ---------------------------------------------------------------

00:061 000000

00:061 000000 # Unsigned single-precision fixed multiply Mcand by 10.

00:061 000000

00:061 310072 m10x: sta m10r

00:062 270032 ldm Mcand

00:063 200000 or 0 # clear carry

00:064 070000 rlc # times two,

00:065 320032 sto Mcand # save that,

00:066 070000 rlc

00:067 070000 rlc # times eight,

00:070 240032 addm Mcand # times ten,

00:071 320032 sto Mcand

00:072 220000 m10r: jump RETURN

00:073 000000

01:073 000001 track 1

01:000 000000 sector 0

01:000 000000

01:000 000000 # Unsigned double-precision multiply Mcand by Mper

01:000 000000 # leaving the result in MQ (ls word) and MQh

01:000 000000 # (ms word). Destroys Mcand and Mper. Sets errno

01:000 000000 # if overflow out of MS digit.

01:000 310434 multUDx: sta mdlr

01:001 170000 and 0

01:002 320035 sto MQ

01:003 320036 sto MQh # initialize

01:004 210001 ld 1

01:005 000000

01:005 320034 mdl1: sto Mtest # m'per digit tester

01:006 250031 andm Mper # test m'per digit

01:007 040000 snz

01:010 220422 jump mdl2 # add in Mcand if 1

01:011 270032 ldm Mcand # Mcand lo

01:012 240035 addm MQ # + MQ lo

01:013 320035 sto MQ # = MQ lo

01:014 270033 ldm Mcandh # Mcand hi

01:015 230036 adcm MQh # + MQ hi + carry

01:016 320036 sto MQh # = MQ hi

01:017 000000

01:017 210000 ld 0

01:020 230030 adcm errno # remember overflow error

01:021 320030 sto errno

01:022 000000

01:022 270032 mdl2: ldm Mcand

01:023 200000 or 0 # clear carry

01:024 070000 rlc # shift multiplicand

01:025 320032 sto Mcand # Mcand * 2

01:026 270033 ldm Mcandh # double precision

01:027 230033 adcm Mcandh #

01:030 000000

01:030 270034 ldm Mtest

01:031 200000 or 0 # clear carry

01:032 070000 rlc

01:033 040000 snz # if no more bits

01:034 220000 mdlr: jump RETURN # done.

01:035 220405 jump mdl1

01:036 000000

01:036 000000

01:036 000000 # Unsigned single-precision multiply Mcand by Mper

01:036 000000 # leaving the result in MQ. Destroys Mcand.

01:036 000000 # Sets errno if overflow out of MS digit.

01:036 310464 multUx: sta mslr

01:037 170000 and 0

01:040 320035 sto MQ

01:041 210001 ld 1

01:042 000000

01:042 320034 msl1: sto Mtest # m'per digit tester

01:043 250031 andm Mper # test m'per digit

01:044 040000 snz

01:045 220454 jump msl2 # add in Mcand if 1

01:046 270032 ldm Mcand # Mcand

01:047 240035 addm MQ # + MQ

01:050 320035 sto MQ # = MQ

01:051 000000

01:051 210000 ld 0

01:052 230030 adcm errno # remember overflow error

01:053 320030 sto errno

01:054 000000

01:054 270032 msl2: ldm Mcand

01:055 200000 or 0 # clear carry

01:056 070000 rlc # shift multiplicand

01:057 320032 sto Mcand # Mcand * 2

01:060 000000

01:060 270034 ldm Mtest

01:061 200000 or 0 # clear carry

01:062 070000 rlc

01:063 040000 snz # if no more bits

01:064 220000 mslr: jump RETURN # done.

01:065 220442 jump msl1

01:066 000000

01:066 000000 # -------------------------------------------------

01:066 000000

02:066 000002 track 2

02:000 000000 sector 0

02:000 000000

02:000 000000 # Output a string of packed characters.

02:000 000000 #

02:000 311010 ttyosx: sta ttysr

02:001 270024 ldm ttchar # ptr to string

02:002 000000

02:002 311003 tts0: sta tts1 # set string pointer

02:003 270000 tts1: ldm POINTER # load text word,

02:004 320024 sto ttchar

02:005 301007 lda C+2

02:006 221015 jump ttyowx # output one word,

02:007 040000 snz

02:010 220000 ttysr: jump RETURN # exit if end of string

02:011 271003 ldm tts1

02:012 160001 add 1 # advance string ptr,

02:013 221002 jump tts0

02:014 000000

02:014 000000 # -----------------------------------------------------

02:015 000015 sector 13 # OPTIMUM 64x5

02:015 311027 ttyowx: sta ttwr

02:016 270024 ldm ttchar

02:017 321047 sto ttwv1 # optimum storage

02:020 211024 ld ttw1 # reset table ptr,

02:021 000000

02:021 311023 ttw0: sta ttwj2

02:022 270024 ldm ttchar # A=char,

02:023 220000 ttwj2: jump POINTER # jump into table,

02:024 221036 ttw1: jump ttw3 # LS char,

02:025 221030 jump ttw2 # 2nd char,

02:026 221030 jump ttw2 # 3rd char,

02:027 220000 ttwr: jump RETURN # return

02:030 000000

02:030 000000 # Shift right one character, output it.

02:030 100000 ttw2: sr 0

02:031 100000 sr 0

02:032 100000 sr 0

02:033 100000 sr 0

02:034 100000 sr 0

02:035 100000 sr 0

02:036 000000 # Output the LS character, advance the pointer to

02:036 000000 # the next character in the word in ttchar.

02:036 320024 ttw3: sto ttchar

02:037 301041 lda C+2

02:040 220001 jump ttyo # output a char,

02:041 040000 snz # if it was a NULL,

02:042 221027 jump ttwr # exit

02:043 271023 ldm ttwj2 # current table ptr,

02:044 160001 add 1 # increment,

02:045 221021 jump ttw0 # loop.

02:046 000000

02:047 000047 sector 39 # OPTIMUM 64x5

02:047 000000 ttwv1: VAR

02:050 000000

02:050 000000 # -----------------------------------------------------

02:050 000000

02:050 000000

02:050 000000 # -----------------------------------------------------

02:050 000000

03:050 000003 track 3

03:000 000000 sector 0

03:000 000000

03:000 000000 # Output TTARG as a decimal number. Leading zero's are

03:000 000000 # handled according to ZSFLAG:

03:000 000000 # '0' displayed as 0

03:000 000000 # ' ' displayed as space

03:000 000000 # 0 suppressed.

03:000 000000 # Modifies TTARG, TTCHAR.

03:000 000000

03:000 474540 ttddk1: -100000 # table of divisors

03:001 754360 -10000

03:002 776030 -1000

03:003 777634 -100

03:004 777766 -10

03:005 000000 0 # end of table marker

03:006 000000 ttzchr: 0 # zero-suppress character

03:007 000000 ttddr: RETURN # return address

03:010 000000 ttddr2: RETURN # subr return address

03:011 000000

03:011 321407 ttyodx: sto ttddr # save return addr,

03:012 270027 ldm zschar

03:013 321406 sto ttzchr # copy of zero-supp char

03:014 211463 ld ttdd7 # ptr to decade char output

03:015 321410 sto ttddr2 # inside loop

03:016 211400 ld ttddk1 # init ptr to divisors

03:017 000000

03:017 311421 ttdd0: sta ttdd1 # top of outer loop,

03:020 311436 sta ttdd4 # set ptr to current divisor

03:021 270000 ttdd1: ldm POINTER # check for end of table

03:022 200000 or 0 # marked with 0

03:023 030000 sz

03:024 221432 jump ttdd2 # jump if more decades,

03:025 000000

03:025 000000 # Remainder is less than 10; output directly.

03:025 000000

03:025 271407 ldm ttddr # set return from routine

03:026 321410 sto ttddr2

03:027 270025 ldm ttarg # get remainder

03:030 320024 sto ttchar

03:031 221444 jump ttdd5 # go output

03:032 000000

03:032 000000 # Determine quotient/digit by repeated subtraction of

03:032 000000 # the decade divisor.

03:032 000000

03:032 270037 ttdd2: ldm minus1 # seed to enter loop

03:033 000000

03:033 160001 ttdd3: add 1

03:034 320024 sto ttchar # next try

03:035 270025 ldm ttarg # the remainder,

03:036 240000 ttdd4: addm POINTER # subtract decade,

03:037 050000 sc

03:040 221444 jump ttdd5 # until underflow,

03:041 320025 sto ttarg # repeat

03:042 270024 ldm ttchar

03:043 221433 jump ttdd3 # until it does.

03:044 000000

03:044 000000 # Underflow -- TTCHAR is number of decades.

03:044 000000 # Output the value in TTARG as a decimal character,

03:044 000000 # but suppressing leading zeroes as indicated. This returns

03:044 000000 # according to previously-set ttddr2.

03:044 000000

03:044 270024 ttdd5: ldm ttchar # decimal value,

03:045 200000 or 0 # (test it)

03:046 271406 ldm ttzchr # output left-fill char

03:047 040000 snz

03:050 221460 jump ttdd6a # if leading zero

03:051 210066 ld '0 # non-zero value,

03:052 321406 sto ttzchr # clear zero-suppress

03:053 270024 ldm ttchar

03:054 210041 ld digtbl # ptr to decimal characters,

03:055 240024 addm ttchar # index it,

03:056 311457 sta ttdd6

03:057 270000 ttdd6: ldm POINTER # fetch the character,

03:060 320024 ttdd6a: sto ttchar

03:061 271410 ldm ttddr2 # where we return to...

03:062 220001 jump ttyo # output character

03:063 000000

03:063 271421 ttdd7: ldm ttdd1 # ... here during loop.

03:064 160001 add 1 # advance divisor table ptr

03:065 221417 jump ttdd0 # loop.

03:066 000000

03:066 000000

04:066 000004 track 4

04:000 000000 sector 0

04:000 000000

04:000 000000

04:000 000000 # Output ttarg as an octal number.

04:000 312023 ttyoox: sta ttoor

04:001 270040 ldm minus6 # oct digits in word,

04:002 320026 sto ttopt

04:003 270025 ldm ttarg # get passed value,

04:004 070000 ttoo1: rlc # shift MSB into Cy,

04:005 070000 rlc # rotate MS octal digit

04:006 320025 sto ttarg # because carry gets lost

04:007 070000 rlc # to LS bits

04:010 070000 rlc

04:011 170007 and 7

04:012 160041 add digtbl # ptr into digit table,

04:013 312014 sta ttoo2

04:014 270000 ttoo2: ldm POINTER # load digit

04:015 320024 sto ttchar # setup for call ttyo

04:016 212020 ld ttoo3

04:017 220001 jump ttyo # print digit,

04:020 270026 ttoo3: ldm ttopt

04:021 160001 add 1

04:022 040000 snz # exit after 6 digits

04:023 220000 ttoor: jump RETURN

04:024 320026 sto ttopt

04:025 270025 ldm ttarg

04:026 070000 rlc

04:027 222004 jump ttoo1

04:030 000000

04:030 000000

04:030 000000

04:030 000000 # ----------------------------------------------------------------

04:030 000000 # END of library, start of test code.

04:030 000000

04:030 000000

12:030 000012 track 10

12:000 000000 sector 0

12:000 000000

12:000 000000 t1: text / TIMES /

12:001 062004 4, 16, 6

12:002 050134 28, 1, 5

12:003 000004 4, 0

12:003 000000 t2: text / IS /

12:004 050604 4, 6, 5

12:005 000004 4, 0

12:005 000000 t3: text 4, 8, 2

12:006 021004 4, 8, 2

12:007 000000 0

12:007 000000 t4: text /, OCTAL /

12:010 300454 44, 4, 24

12:011 032016 14, 16, 3

12:012 000422 18, 4, 0

12:012 000000 t5: text / OVERFLOW!/, 4, 8

12:013 363004 4, 24, 30

12:014 151201 1, 10, 13

12:015 233022 18, 24, 19

12:016 100455 45, 4, 8

12:017 000000 0

12:017 000021 n: 17

12:020 000003 m: 3

12:021 777766 i: -10

12:022 000000

12:022 000000 tx1: text /OK, SO HOW DOES THIS GO? IT IS PROBABLY/, 2, 8, /STILL VERY, VERY SLOW./, 2, 8

12:023 541730 24, 15, 44

12:024 300504 4, 5, 24

12:025 302404 4, 20, 24

12:026 110423 19, 4, 9

12:027 050130 24, 1, 5

12:030 242004 4, 16, 20

12:031 040506 6, 5, 4

12:032 713032 26, 24, 57

12:033 200604 4, 6, 16

12:034 050604 4, 6, 5

12:035 122604 4, 22, 10

12:036 033130 24, 25, 3

12:037 252231 25, 18, 21

12:040 051002 2, 8, 5

12:041 220620 16, 6, 18

12:042 360422 18, 4, 30

12:043 251201 1, 10, 21

12:044 360454 44, 4, 30

12:045 251201 1, 10, 21

12:046 220504 4, 5, 18

12:047 742330 24, 19, 60

12:050 001002 2, 8, 0

12:050 000000

13:050 000013 track 11

13:000 000000 sector 0

13:000 000000

13:000 000000 # test code

13:000 000000

13:000 275017 test: ldm n

13:001 320032 sto mcand # multiply this

13:002 320025 sto ttarg

13:003 170000 and 0

13:004 320030 sto errno

13:005 320027 sto zschar # suppress leading 0's

13:006 305410 lda C+2

13:007 221411 jump ttyodx # print m'cand

13:010 000000

13:010 215000 test2: ld t1

13:011 320024 sto ttchar

13:012 305414 lda C+2

13:013 221000 jump ttyosx # print " times "

13:014 000000

13:014 275020 ldm m

13:015 320031 sto mper # by this

13:016 320025 sto ttarg

13:017 305421 lda C+2

13:020 221411 jump ttyodx # print m'per

13:021 000000

13:021 215003 ld t2

13:022 320024 sto ttchar

13:023 305425 lda C+2 # "equals"

13:024 221000 jump ttyosx

13:025 000000

13:025 305427 lda C+2

13:026 220400 jump multUDx # multiply

13:027 000000

13:027 270030 ldm errno # check for o'flow

13:030 200000 or 0

13:031 040000 snz

13:032 225437 jump mzzz1

13:033 000000

13:033 215012 ld t5 # OVERFLOW ERROR!

13:034 320024 sto ttchar

13:035 305462 lda done

13:036 221000 jump ttyosx

13:037 000000

13:037 270035 mzzz1: ldm MQ

13:040 320025 sto ttarg

13:041 305443 lda C+2

13:042 221411 jump ttyodx # print m'per

13:043 000000

13:043 000000

13:043 215007 ld t4

13:044 320024 sto ttchar # print "octal"

13:045 305447 lda C+2

13:046 221000 jump ttyosx

13:047 000000

13:047 270035 ldm MQ

13:050 320025 sto ttarg

13:051 305453 lda C+2

13:052 222000 jump ttyoox # print octal

13:053 000000

13:053 215005 ld t3

13:054 320024 sto ttchar # print CR, LF

13:055 305457 lda C+2

13:056 221000 jump ttyosx

13:057 000000

13:057 275017 ldm n

13:060 160021 add 17

13:061 060000 snc

13:062 010001 done: halt 1

13:063 325017 sto n

13:064 225410 jump test2

13:065 000000

13:065 000000

13:065 000000

13:065 000013 track 11

13:000 000000 sector 0

13:000 000000

13:000 000000

13:000 215022 tex: ld tx1

13:001 320024 sto ttchar

13:002 215404 ld tex2

13:003 221000 jump ttyosx

13:004 010000 tex2: halt 0

13:005 000000

13:005 000000

13:005 000000 # ---------------------------------------------------------------

13:005 000000


SYMBOLS

MSLR=000464 308=000464 TTOPT=000026 22=000026 TTDD0=001417

783=001417 TTDD1=001421 785=001421 TEX=005400 2816=005400

TTDD2=001432 794=001432 TTDD3=001433 795=001433 TTDD4=001436

798=001436 TTDD5=001444 804=001444 MCANDH=000033 27=000033

TTDD6=001457 815=001457 TTDD7=001463 819=001463 TTS0=001002

514=001002 TTS1=001003 515=001003 MQ=000035 29=000035

MDL1=000405 261=000405 MDL2=000422 274=000422 TTW0=001021

529=001021 TTW1=001024 532=001024 TTW2=001030 536=001030

TTW3=001036 542=001036 START=000000 0=000000 POINTER=000000

0=000000 TTDDR2=001410 776=001410 M10R=000072 58=000072

TTDDR=001407 775=001407 MTEST=000034 28=000034 M10X=000061

49=000061 MZZZ1=005437 2847=005437 TTWJ2=001023 531=001023

TTDDK1=001400 768=001400 TTYOD=000005 5=000005 TTYOOX=002000

1024=002000 MDLR=000434 284=000434 MULTUDX=000400 256=000400

RETURN=000000 0=000000 TTWR=001027 535=001027 MINUS1=000037

31=000037 TTYOO=000006 6=000006 TTYOSX=001000 512=001000

DIGTBL=000041 33=000041 TTOO1=002004 1028=002004 TTOO2=002014

1036=002014 TTYODX=001411 777=001411 MINUS6=000040 32=000040

TTOO3=002020 1040=002020 TTYOS=000004 4=000004 VAR=000000

0=000000 TTYOW=000003 3=000003 TTWV1=001047 551=001047

TTYOWX=001015 525=001015 TTCHAR=000024 20=000024 TTYSR=001010

520=001010 DONE=005462 2866=005462 I=005021 2577=005021

TTARG=000025 21=000025 ERRNO=000030 24=000030 M=005020

2576=005020 N=005017 2575=005017 MQH=000036 30=000036

MCAND=000032 26=000032 T1=005000 2560=005000 TTOOR=002023

1043=002023 TTZCHR=001406 774=001406 T2=005003 2563=005003

MSL1=000442 290=000442 T3=005005 2565=005005 MULTUD=000010

8=000010 MSL2=000454 300=000454 T4=005007 2567=005007

T5=005012 2570=005012 ZSCHAR=000027 23=000027 TEST=005400

2816=005400 TX1=005022 2578=005022 MPER=000031 25=000031

TEX2=005404 2820=005404 MULTUS=000007 7=000007 TTYI=000002

2=000002 TTDD6A=001460 816=001460 MULTUX=000436 286=000436

TEST2=005410 2824=005410 TTYO=000001 1=000001 M10=000011

9=000011

# 0 errors, 634 words, 166 symbols


Appendix A

ORDER CODES


Appendix B

TELETYPE CHARACTER CODE


Appendix C

POWERS OF TWO


power (n) (n)

of two 2 decimal 2 octal

0 0 0

1 1 1

2 3 3

3 7 7

4 15 17

5 31 37

6 63 77

7 127 177

8 255 377

9 511 777

10 1023 1777

11 2047 3777

12 4095 7777

13 8191 17777

14 16383 37777

15 32767 77777

16 65535 177777

17 131071 377777

18 262143 777777


Appendix D

Initial orders



Universal Machine Operators Manual Copyright Tom Jennings 1999-2002 Page 44

Website contents, unless otherwise specified, © 2023 by Tom Jennings is licensed under CC BY-SA 4.0