Page Numbers: Yes X: 530 Y: 10.5" First Page: 18
Margins: Top: 1.3" Bottom: 1"
Heading:
Dorado MicroassemblerEdward R. Fiala21 July 1980
15. Small Constants
The hardware allows low bits of the FF field in an instruction to be used as operands for functions selected by high bits of the FF field. When used this way, the low bits of FF are called a small constant.
"Literal" small constants such as "17S", "1S", etc. may appear in instructions without previous definition. Alternatively, small constants can be defined in advance by the following macro:
MSC[NAME,P1,...,P4];*defines NAME as a small constant with value = sum of P1...P4.
Warning: MSC also defines NAME as a parameter. If you redefine the parameter with the same name as the small constant, you will also redefine the small constant.
The RBase[RMADDR] macro is used to construct correct small constants for loading into the RBase← register prior to referencing the RM address or RM region RMADDR; RM references will be discussed later.
Some example clauses using small constants are as follows:
RBase←RBase[RTEMP],*Addresses the RM region containing address RTEMP
Cnt←13S,*Loads Cnt with 13
Small constants cannot be used as B constants--they are not equivalent to constants.
16. Assembling Base Register Names
Base registers are referred to when loading MemBase and in assembling for IFUM. Base registers are defined by clauses of the form:
BR[MDS,1];*Define MDS as base register 1
BR[CODEBASE,37];*Define CODEBASE as base register 37
Since your program can also refer to the four base registers pointed at by the MemBX register, a separate construct is provided to define names for this purpose:
BRX[LOCAL,n];*Define LOCAL as MemBX-relative base register n = 0 to 3
Address symbols defined by BR and BRX can then be used as in "MemBase←MDS" or "MemBaseX←LOCAL" in the program, and these names can be used in IFUM assembly statements as discussed later. In addition, the address symbols will be used by Midas when pretty-printing microinstructions.
17. Assembling Device Numbers for TIOA
Device numbers are defined symbolically by clauses of the form:
DEVICE[DSP,120];
This defines DSP as an address symbol that will be used in symbolic printout by Midas when the number 120 appears in the TIOA register.
During assembly the name DSP can then be used as a constant. For example,
T←DSP;
TIOA←T;
causes TIOA to be loaded with the full 8-bit device address. Alternatively, in situations where you are sure that the high 5 bits of TIOA contain the correct value, you can use the short method of loading TIOA, as follows:
TIOA[DSP];
This loads the low three bits of TIOA with the low three bits of DSP while leaving the high five bits of TIOA unchanged.
18. Symbolic Use of Task Numbers
Task numbers are defined symbolically by clauses of the form:
TASKN[FLT,17];*Define the fault task as 17
FLT can then be referred to during assembly by the following kinds of clauses:
RdTPC←FLT;*Read TPC[FLT] into Link
LdTPC←FLT;*Load TPC[FLT] from the value in Link
Wakeup[FLT];*Initiate a wakeup for FLT
FLT will also be passed as an address to Midas and will be used in printing the contents of CTASK, TASK, NEXT, etc. symbolically. Since Midas may eventually print task specific register addresses symbolically also (e.g. TIOA DSPTSK 120, RBASE DSPTSK 10), it is desirable to keep the task names fairly short to avoid using too much of the display window during debugging.
The task names EMU for the emulator (task 0) and FLT for the fault task (17) are predefined in D1Lang.mc.
19. Assembling Data for RM
The assembler can assemble data and assign addresses in RM in several ways discussed in this section.
The hardware allows any one of the 20 registers pointed to by RBase to be read/written by an instruction. To define 20-long regions of RM:
RMRegion[RGNNAME];*allocates a 20-long region RGNNAME
New regions are allocated in blocks of 20 starting at 0 and ascending by 20 for each new region. I.e., the first region you define is 0 to 17, next 20 to 37, etc. up to 360 to 377.
After defining a region with RMRegion, you can proceed immediately to define addresses in that memory using the macros given below. Alternatively, you can reselect that region at a later time:
SetRMRegion[RGNNAME];*reselects a region RGNNAME for allocation
"Literals" in RM, such as "32224R", may be referenced in instructions without previous definition. The first reference to an RM literal will assemble the literal value into a register in the current region. Subsequent references to the literal will refer to the same location in RM. It is illegal to duplicate a literal in more than one region.
Other ways of assigning storage in a region are as follows:
RV[NAME,P1,...,P8];*define NAME as an address in the current region with value = sum of
*parameters.
RVN[NAME];*Defines NAME in current region without initial value.
Reserve[N];*Skips N (an integer < 20) words in the region
Define variables with RVN rather than a useless initial value because this will prevent the "Cmpr" action in Midas (which compares the microstore image against what you loaded) from reporting fictitious errors. In system microcode (as opposed to diagnostics), any occurrence of a variable with an initial value is probably a programming error since it requires a reload to restore the initial value. Hence, if you have variables with initial values, you probably should store the initial values elsewhere (in IM, for example), define the variables with RVN, and copy the initial values into the registers during initialization.
The assembler checks at assembly-time that the base for an RM address agrees with the value believed to be in RBase. This is controlled by the following macros:
KnowRBase[RGNNAME];*declares RGNNAME to be in RBase
DontKnowRBase;*declares that the contents of RBase are unknown
The small-constant clauses that load RBase (see the Small Constants section) change the assembly-time parameter for the current region.
It may be convenient to code subroutines that use temporary storage in RM and are called with several possible values in RBase. For example, a programming convention might reserve the first two words in each of several regions as temporary storage for subroutines. Then the subroutine will want to reference these words in a regionless way.
To do this, first reserve temporaries for each region (using Reserve). Then define a regionless RM address as follows:
RVREL[NAME,DISP];*declares NAME a regionless address in RM with displacement DISP
*relative to the current value in RBase.
The subroutine would then reference NAME. These references would not cause "Invalid RBase" error messages.
20. Assembling Data for STK
The hardware allows the 400-word STK memory to be treated as four separate stacks of 100 words each. We expect at least one of these four stacks to be used as the Mesa evaluation stack, and perhaps all four will be used for this purpose, representing different procedure frames or something.
However, it is also possible that one or more of the four STK regions will be used to hold data in some way other than as a stack. For example, STK is the best available memory for (emulator-only) tables because it is the only memory with an indexable address.
The assembler has several macros that allow data to be assembled for STK. These are:
STKRegion[i];*where i = 0 to 3 selects one of the four STK regions for allocation.
STKWrd[i];*where i = 0 to 77, sets the word for the next allocation.
STKVal[p0,p1, ... , p8];*sums up to 9 parameters and stores the result in the currently selected
*STK word, and then advances to the next word.
21. Assembling Data Items In the Instruction Memory
If you do not want to clutter RM with infrequently referenced constants or variables, and if you are willing to cope with the hardware kludges for reading/writing the instruction memory as data, then you can store data items in IM.
To assemble a table of data in the instruction memory:
Set[T1Loc,100];
Data[(TABLE1: Byt0[P1,...,P8] Byt1[...] Byt2[...] Byt3[...], At[T1Loc])];
Data[(Byt0[P1,...,P8] Byt1[...] Byt2[...] Byt3[...], At[T1Loc,1])];
...
where TABLE1 is an IM address symbol equal to the location of the first instruction in the table, P1, ..., P8 are parameters or integers. Byt0, Byt1, Byt2, and Byt3 assemble for the different 9-bit bytes of the instruction and correspond to the bits read by ReadIM[0], ReadIM[1], ReadIM[2], and ReadIM[3]. "At" is discused in the "Placement" section later. Sample sequences for reading and writing IM are given in the "Programming Examples" section.
It is important to note that while Byt0 and Byt2 may assemble data items up to 9 bits wide, Byt1 and Byt3 are limited to 8-bit wide items because the 9th bits for these are parity bits, and the assembler will not let you load bad parity into IM as part of a data item.
22. Assembling for IFUM
Micro assembles data for an imaginary IFU identical to the Dorado IFU except that the address of the target location in IM is a full 14-bit address rather than the compact 12-bit form used by Dorado. MicroD imposes the necessary placement constraints on IFU target addresses in IM and transforms the imaginary IFU instruction into the form expected by Dorado.
Before using any of the IFU macros discussed below, you must declare the instruction set number as follows:
InsSet[0,1];*Declares instruction set 0 with 1 instruction per entry vector
InsSet[1,4];
*Declares instruction set 1 with 4 instructions per entry vector
InsSet[2,4];
*Declares instruction set 2 with 4 instructions per entry vector
InsSet[3,1];
*Declares instruction set 3 with 1 instruction per entry vector
You can define parameters or integers to use in place of the literal arguments to InsSet, if you want to.
It is desirable, though not required, for an IFUM assembly statement to be given after its target instruction has been assembled to avoid a forward reference. This reduces work required by both Micro and MicroD, so the assembly will run faster.
There are three macros defined for assembling IFUm words. These are:
IFUReg[opcode,length,memb,rbaseb,ifad,n,sign,pa];*Regular opcode
IFUPause
[opcode,length,memb,rbaseb,ifad,n,sign,pa];*Pause opcode
IFUJmp
[opcode,2,memb,rbaseb,ifad,sign];*2-byte jump opcode
IFUJmp
[opcode,1,memb,rbaseb,ifad,disp];*1-byte jump opcode
In these:
ArgumentValueEffect
opcode0 to 377Together with InsSet, opcode specifies the IFUM word to be loaded.
length1 to 3Number of bytes in the opcode.
n0 to 16First operand delivered by ←ID -or-
17if no operand.
sign0 or 1Operand sign or sign extension (see hardware documentation).
pa0 or 10 if not packed-alpha, 1 if packed-alpha.
membBRX address0..MemBX[0:1]..address loaded into MemBase -or-
BR addressThe BR address must identify BR 34 to BR 37; a value of 4 to 7 is assembled into memb; 34+memb[1:2] is loaded into MemBase at t0 of the entry instruction.
rbaseb0 or 1RM region loaded into RBase at t0 of the entry instruction.
ifadIM addressthe tag on the first instruction in the IFU entry vector for the opcode.
disp-40 to +37The displacement of a one-byte jump opcode (fills in the n, sign, and pa fields appropriately)
"ifad" is the address of the first instruction in the entry vector for the opcode. The last InsSet pseudooperation specified the number of entry instructions per vector. You must put these instructions in sequence in the source file beginning with the one whose tag is "ifad."
Warning: The assembler does not check that you have done this.
For one-byte jump opcodes, the assembler will correctly transform the "disp" argument, which should be an integer in the range -40 to +37, into proper values for the "n," "sign," and "pa" fields of the IFUM word (see hardware manual). For two-byte jumps, only the "sign" field is utilized by the hardware, and the assembler will put don’t-care values into "n" and "pa."
Since the above macros are fairly jaw-breaking (six or eight arguments), you may wish to use Micro’s macro-definition capability to define shorter forms for your own use. You may also wish to use the "Repeat" builtin to define blocks of opcodes. Here are two examples:
*Macro to define Byte Lisp opcodes of length 1
*Byte Lisp is instruction set number 1
M[RegOp,IFUReg[#1,1,MDS,0,#2,17,0,0]];
RegOp[0,CONS];
RegOp[1,RPLACA];
RegOp[2,RPLACD];
*Generate 20 one-byte jump instructions with displacements from 1 to 20
Set[DX,1];
Repeat[20,IFUJmp[Add[77,DX],1,MDS,JMP,DX] Set[DX,Add[DX,1]]];
I think that assembling data for IFUM is the only place where falling back to basic Micro constructs such as Macro definition will be desirable.
23. Assembling for ALUFM
The processor’s Alu provides all 20 boolean operations on A and B and 20 arithmetic operations, each with an optional carry. Only about 11 of the 40 possible arithmetic functions seem to me to have any hope of application (See the MECL System Design Handbook specification for the MC10181 ic’s, if you are curious about the others.)
The 20-word ALUFM memory contains six Alu control signals in each word. Since only 20 of the 31 potentially useful Alu operations can be stored in ALUFM, you must define a suitable subset by editing the D1Alu.Mc file according to instructions on its first page; this file must be assembled after D1Lang as discussed in the "Assembly Procedures" section. This will assemble storage for ALUFM and define all macros pertinent to each Alu operation. 16 operations believed most useful are *’ed in the table below, leaving two operations unspecified.
Addresses 16 and 17 are special--these are the two addresses used by shift operations. By convention, ALUFM 16 must contain the controls for "not A" (so the shifter output on A, which is inverted, will go through the Alu to the masker). ALUFM 17 is not presently constrained (Perhaps the "A" operation, which would allow shifter output to be inverted before masking, is a good choice for ALUFM 17).
Note: You must define both "A" and "B" because those sources which can be optionally routed over either A or B (i.e., RM, T, Q, and MD) require that both paths be available through the Alu. Both "not A" and "not B" must be defined for the same reason (and "not A" is required for the shifter).
The XorCarry and XorSavedCarry functions modify the input carry and the Carry20 function OR’s a 1 into the carry out of the low-order four-bit ALU slice; these are written as standalone clauses; since carries affect only arithmetic, they are useless noops with logical operations.
BitBlt is expected to use ALUFM 15 and 17 as variables. However, if BitBlt restores these upon exit, and if they are preserved across map faults and other traps, the emulator will be able to use two other operations; you should edit D1Alu.Mc to define these operations as "emulator-only" so that an error will be flagged if they are erroneously used by any task other than the emulator. To support restoration of these prior to exit from BitBlt, D1Lang defines symbols AFMn (n = 0 to 17) as constants equal to the normal contents of corresponding ALUFM locations. These allow normal contents of an ALUFM location to be restored as follows:
T←AFM17;*T ← normal contents of ALUFM location 17
ALUFMRW←T, ALUF[17];
The AFMn constants are also used to initialize ALUFM during boot-loading.
Below, the potentially useful Alu operations are listed:
A00
A1-1
*AA straight through (arithmetic)
AA straignt through (logical)
*BB straight through
*not Aones complement of A
*not Bones complement of B
*A and Blogical and
not A and Bparsed (not A) and B
not A and not Bparsed (not A) and (not B)
A and not Bparsed A and (not B)
*A or Binclusive ’OR’
A or not Bparsed A or (not B)
not A or Bparsed (not A) or B
not A or not Bparsed (not A) or (not B)
*A#Bexclusive ’OR’
*A xor Bexclusive ’OR’ (alternate syntax)
A=Bequivalence or exclusive nor
A xnor Bequivalence (alternate syntax)
A eqv Bequivalence (alternate syntax)
*A+Bsum
*A+B+1
*A-B-1equals A+(not B)
*A-Bdifference
*A-1
*A+1
2AA+A
2A+1
*Indicates that these are defined for system microcode
24. General Comments on Instruction Statements
The general layout of an instruction statement is as follows:
TAG:branch clause, T←MD, rmaddr←(A phrase) and (B phrase), function, placement;
TAG is an instruction memory address symbol. This may be used in branch clauses as discussed later. Micro places instructions sequentially starting at 0; then the postprocessing program MicroD relocates, or places, the instructions at their runtime locations.
Branch and placement clauses are discussed later. They present no special problems in understanding and are easy to program.
Functions that don’t involve routing data from one place to another are also easy to program--you just write the appropriate name as a separate clause in the instruction, as discussed in the "Standalone Clauses" section.
However, clauses that involve moving data from one place to another are tricky. This section tries to present the general concepts behind programming these clauses.
Data-routing clauses all have one or more "←"’s in them and require parentheses in some places to cause evaluation in the correct order. One of these clauses is evaluated from right-to-left, or from "source" to "destinations".
If there is only one source and one destination in the clause, no problem: simply write "destination←source", e.g.:
MemBase←MDS,
T←RMADDR,The assembler figures out how to route data from the RM address RMADDR to B (or A if B has been used) then through the Alu and into T.
RMADDR←34C,Again the assembler figures out how to construct the constant 34, route it onto B and through the Alu, and into the correct RM address.
When you have A or B phrases embedded in Alu expressions, then you have to use parentheses, e.g.:
T←(Fetch←RMADDR)+1,The assembler routes the contents of the RM address RMADDR onto both A and Mar, does A+1 in the Alu, routes the Alu onto PD, and stores PD in T.
T←(Fetch←T)+(Q←RMADDR)The assembler routes RM address RMADDR onto B and into Q, T onto both A and Mar, performs "A+B" in the Alu, routes the Alu onto PD, and loads PD into T.
In assembling the first clause above, the assembler proceeds in the following way:
a.RMADDR is looked up first and recognized as an RM address. The proper value is assembled for the RStk field of the instruction. At this point data from RMADDR might be routed over either A or B.
b.Fetch← is looked up next. The ASel field is set to cause the fetch, and RM is routed onto A using FF[0:1] (There are some complications when FF has been used as a constant.).
c.A+1 is recognized as an Alu operation, AluF is set to cause A+1, and the data is now at PD.
d.Finally, the assembler identifies T←PD and modifies the LC field appropriately.
Note: The "()" in the above example are not optional. If you omit them, the assembler would look up "RMADDR+1", which would be undefined.
One general idea in the above is that at each stage the source is routed only as far as necessary to load it into the destination.
Note:T←Fetch←RMADDR,is legal
T←Fetch←(RMADDR),
is legal
T←(Fetch←RMADDR),
is legal
Fetch←T←RMADDR,
is illegal
The last clause above is illegal because, by the time the assembler recognizes Fetch←, it has already routed the source data past A and through the Alu, and there is no path from the Alu to Mar. The assembler is not clever enough to remember that the data originally started on A.
Here are some more "()" examples:
T←T+(RMADDR),is legal--"()" are mandatory around all A and B sources except "T", "MD", "Q", and "ID".
T←(T)+(RMADDR),is legal--"()" optional around "T", "MD", "Q", and "ID".
T←(T+(RMADDR)),is legal--extra "()" around an entire source always OK
(T←T+(RMADDR)),is legal
T←(T+(RMADDR)) rsh 1,is legal--"()" are mandatory
T←T+(RMADDR) rsh 1,is illegal--the assembler will evaluate RMADDR OK, but it won’t recognize the rest.
You must also write clauses in the correct order. Since the assembler evaluates clauses from right-to-left, whenever there are different ways to do something, the assembler will pick one of the ways, and you must be sure that it makes the correct choice by putting the clauses in the correct order.
The five decisions of interest are:
a.Branch clauses--the assembler has to know whether FF is available for a branch condition, long goto, or long call. The assembler has special stuff to figure this out, so you can position the branch clause anywhere in the instruction statement.
b.RM, T, MD, or Q routed through Alu clauses--the assembler will use B for this routing unless you have already used B for something else. Hence, if you are using B for something else, put that clause to the right in the instruction statement.
c.Different RM addresses for read and write--Be sure that the RADDR2← destination is to the left of the RADDR1 source in the instruction statement.
d.Shifter operations that OR shifter output with another A source before routing through the Alu--this is rarely done, ordinarily an error. If you really want to do this, the shifter clause should be to the right in the instruction statement.
e.Put FF>77 clauses to the right of A clauses. If you violate this rule, correct statements will still assemble correctly, but some erroneous statements won’t get checked by the assembler.
I think that the above cases are the only ones where the assembler’s decision algorithms might cause trouble. Obeying (b) through (f) above nearly always produces a statement that will assemble correctly, and I think that any legal instruction can be written in a way that satisfies these. If you encounter problems with these rules, see me.
25. Small Constant Clauses
The hardware allows low bits of FF in instructions to be used as literal values in several places. The valid clauses for these uses are:
MemBase←SC,MemBase loaded from small constant (unusual) -or-
MemBase←MDS
MemBase loaded from value of BR address symbol (usual)
RBase←SC,
RBase loaded from small constant (unusual)
RBase←RBase[RADDR]
-or-
RBase←RBase[RGNNAME]
Normal ways to load RBase
CNT←SC,
Loop counter from small constant
MemBX←SC,
MemBX loaded with 0 to 3
MemBaseX←SC,
MemBase loaded with 0..MemBX[0:1]..SC (unusual) -or-
MemBaseX←LOCAL
where LOCAL is a BRX address (usual) -or-
MemBase←LOCAL
same as MemBase←LOCAL
A←SC,
A from 0 to 17 (usually embedded in Alu expression)
Fetch←SC,
Memory reference from small constant
In the above "SC" can be any of the small constant tokens discussed in the earlier section on small constants, namely, a literal like "14S" or a name defined by MSC.
The blocks of FF decodes for waking up tasks and loading the low bits of TIOA are not written as small constant clauses. Instead Wakeup[task] and TIOA[device] are used (i.e., standalone clauses); the arguments to these should be address symbols in the TASKN and DEVICE memories, respectively, as discussed earlier. An alternative syntax for Wakeup[task] is Notify[n], where n is an integer (0 to 17) specifying the task to be awakened; this alternate syntax is not expected to be useful except for diagnostics checking out the control section.
26. A Clauses
If you study the way in which various operations are encoded in the ASel and FF fields of the instruction (see hardware manual), you will discover that activity on A is usually encoded in the ASel field, leaving FF available for encoding another function. Memory references use FF[0:1] as well as ASel, leaving FF[2:7] available for encoding one of 100 common functions and branch conditions.
When FF is used literally as a constant on B, the A source is limited to RM, T, or ID, and the source for memory references is limited to T or RM.
Shift operations are hardware sources of A, but the assembler treats these as PD outputs. In other words, the various shift-and-mask statements assemble the "shift" value into ASel and select either the "not A" Alu operation (AluF = 16) or the variable Alu operation (AluF = 17), as discussed in the shifter section.
An A source can be any of the following:
ADummy source for clause splitting. It indicates that the source for some destination is A (You probably won’t ever use this because normally the A source and destination are written as a single clause.).
RADDRAn RM address (never uses FF except to OR with shifts)
TUses only ASel if not with a memory reference, only FF[0:1] with Fetch← or Store←, or FF (< 100) with other memory references
IDUses only ASel if not with a memory reference, only FF[0:1] with Fetch← or Store←, undefined for other memory references
MDUses ASel and FF
QUses FF (< 100)
0S to 17SUses FF (< 100)
Rule: You have to enclose small constant and RM addresses in "()" when they are embedded in an Alu expression; "()" are optional for other A sources.
Destinations for A are the Alu, the eight memory references and other control functions in the memory section, and RF← and WF← for shifter-setup. A destinations can be any of the following:
Fetch←Start memory fetch--uses ASel only
IFetch←Start memory fetch in which ID from the IFU replaces low bits of BR (see hardware manual)--uses ASel and FF[0:1] (emulator only).
LongFetch←Start memory fetch in which B extends the displacement on Mar (see hardware manual)--uses ASel and FF[0:1].
Store←Start memory store--uses ASel only (data for write must be put on B in a separate clause)
IOFetch←Start 20-word fetch on behalf of io device--uses ASel and FF[0:1] (illegal in emulator or fault task)
IOStore←Start 20-word store on behalf of io device--uses ASel and FF[0:1] (illegal in emulator or fault task)
PreFetch←Put 20-word data unit in cache--uses ASel and FF[0:1]
Map←Write Map for VA, data on B--uses ASel and FF[0:1] (emulator or fault task only)
RMap←Does the Map← reference together with the ReadMAP function, suppressing the write of the Map so that old data can be read non-destructively in the Pipe; since the FF field is used for ReadMAP, the displacement for the reference can only come from an RM/STK address (emulator or fault task only).
Flush←Purge VA from cache--uses ASel and FF[0:1] (emulator or fault task only)
DummyRef←Loads VA into the Pipe (for reading BR’s)
any Alu expression or destination
BRLo←Uses FF (> 77)
BRHi←Uses FF (> 77)
CFlags←Uses FF (> 77)
RF←Uses FF (> 77). Read-field setup for shifter.
WF←Uses FF (> 77). Write-field setup for shifter.
A←No-op destination--simply routes the source onto A
The primary memory operations Fetch← and Store←, do not prevent FF from being used as a B constant, an "insert field" or "extract field" value, or a long goto/call. FF can be used in these ways if the A source is an RM address or T. However, when FF is not used in these ways, FF[0:1] must encode the source for the reference (RM, T, or ID). The eight secondary memory references (IFetch←, LongFetch←, Map←, Flush←, IOFetch←, IOStore←, DummyRef←, and PreFetch←) require FF[0:1] for encoding. This means that only functions 0 to 77 can be encoded in the same instruction with a memory operation, and secondary memory references consume FF to specify any source other than an RM address.
The above can be combined arbitrary ways and used in Alu expressions, e.g.:
RADDR←T←Fetch←ID,
T←RADDR←Fetch←2S,
T←(Fetch←T)+(RADDR),
The MCR register has some bits loaded from A and some from B. This is encoded by a stand-alone clause of the form "LoadMCR[A,B]", where A and B are A and B source clauses respectively, as discussed later.
Warning: If you illegally write an expression that uses one of the FF decodes between 100 and 377 to the left of a memory reference clause with RM or T as the source, the assembler will not detect the error.
27. B Clauses
The common B sources can be selected by the BSel field in the instruction, leaving FF free for other uses. Less common sources are encoded by functions (FF > 77), and for these BSel may optionally encode the Q← destination. With common sources, B destinations are selected by functions.
The implications of this arrangement are as follows:
You can route any common B source (RM, T, MD, or Q) through the Alu into RM or T while using FF for something else.
You can route any common source to any destination by using FF.
You can route any uncommon source through the Alu or to Q← by using FF.
B sources can be any of the following (all of the FF’s are > 77):
BDummy source for clause splitting (You probably will never use this since it is normally possible to embed the B phrase inside the B arm of the Alu phrase.)
ConstantsUses FF--see earlier constant section
RADDR
T
MDMemory data
Q
LinkUses FF
RWCPRegUses FF (does Link←B’ and B←CPReg, intended for Midas)--overrules loading of Link by Call or Return in the same instruction
DBufUses FF
FaultInfo’Uses FF
Pipe0Uses FF (VAHi is a synonym)
Pipe1Uses FF (VALo is a synonym)
Pipe2’Uses FF
Pipe3’Uses FF (Map’ is a synonym)
Pipe4’Uses FF (Errors’ is a synonym)
Config’Module indicators and IC size stuff--uses FF
Pipe5Uses FF (PRef is a synonym)--cache stuff and reference flags
PCX’Uses FF
EvCntA’Uses FF
EvCntB’Uses FF
IFUMRH’Low part of IFU data--uses FF
IFUMLH’High part of IFU data--uses FF
Note: All FF-encoded B sources except PCX’, EvCntA’, and EvCntB’ (i.e., those from the IFU board) are too slow for Alu arithmetic; the assembler will flag an error if you use any other FF-encoded B source in an arithmetic expression.
Rule: When used in an Alu phrase, B sources must be enclosed in "()", except that "()" are optional around "T", "Q", and "MD".
B destinations can be any of the following:
B←No-op destination--simply routes source onto B
DBuf←A no-op destination. Actual loading of Dbuf is enabled by the Store← memory operation; this is just for readability.
MapBuf←Another no-op destination. Actual loading of MapBuf is enabled by the Map← memory operation.
Q←Uses FF (< 100) ordinarily, or BSel with FF-encoded B sources
Cnt←Uses FF (> 77)
Link←Uses FF (> 77)--overrules loading of Link by Call, Return, or CoReturn in same instruction
PCF←Uses FF (> 77)--loads PC and starts IFU
StkP←Uses FF (> 77)
TIOA←Uses FF (> 77)--TIOA loaded from B[0:7]
Output←Uses FF (< 100)
MemBase←Uses FF (> 77); loads from B[3:7].
RBase←Uses FF (> 77); loads from B[14:17].
Pointers←Uses FF (> 77); does both MemBase←B[3:7] and RBase←B[14:17].
ShC←Uses FF (see "Shifter Clauses")
Hold&TaskSim←Uses FF (> 77)
InsSetOrEvent←Uses FF (> 77)
MOS←Uses FF (> 77), synonym for InsSetOrEvent←
GenOut←Uses FF (> 77), general output to io devices
EventCntB←Uses FF (> 77), synonym for GenOut←
IFUMRH←Uses FF (> 77) (B must remain good through the following instruction--see hardware manual).
IFUMLH←Uses FF (> 77) (B must regain good through the following instruction)
BrkIns←Uses FF (> 77); loads from B[0:7]
IFUTest←Uses FF (> 77)
ALUFMRW←Uses FF (> 77)--this one is simultaneously a B destination and an ALU source--the clause "AluF[n]" must appear in the same instruction where n (0 to 17) selects the location in ALUFM that is read and written
LdTPC←Uses JCN, forces low bit of RStk to be 1. Data on B is the task number whose PC is loaded from Link.
RdTPC←Uses JCN, forces low bit of RStk to be 0. Data on B is the task number whose PC is read into Link.
IMLHR0Pok←
IMLHR0Pbad←
IMLHR0’Pok←
IMLHR0’Pbad←
IMRHBPok←
IMRHBPbad←
IMRHB’Pok←
IMRHB’Pbad←Use JCN and RStk[1:3]. These 10 kludge destinations are various forms for writing IM, where the parity (POK or PBAD), the 21st data bit (RStk.0 or RStk.0’ for the left-half, Block or Block’ for the right-half), and the half-word (left or right) are specified in the macro name and assembled into RStk[1:3]. The other 20 data bits are written from B.
BDispatch←Uses FF (< 100). 8-way dispatch on B[13:15]
BigBDispatch←Uses FF (< 100). 256-way dispatch on B[8:15].
MidasStrobe←Uses FF (> 77). Shifts out DMux addess bit in B[4].
any ALU destination
Some examples of instructions which read and write ALUFM are as follows:
T←(ALUFMRW←T), A+B+1;Loads ALUFM[X] with value in T, where X is the location assembled with control for A+B+1; the old contents of ALUFM[X] are saved in T.
T←ALUFMEM, AluF[3];Reads ALUFM[3] through PD into T