%
Page Numbers: Yes First Page: 1
Heading:
IfuRamSubrs.mcMay 6, 1982 11:18 PM%
* INSERT[D1ALU.MC];
* TITLE[Ifu1];
* INSERT[PREAMBLE.MC];
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CONTENTS

Routine
DESCRIPTION

putIfuLHIfuMLH[t] ← rscr
putIfuRHIfuMRH[t] ← rscr
getIfuLHt IfuMLH[t]
getIfuRHt ← IfuMRH[t]
initIfuM1Thru3Init Ifum locs 1-3 in current instruction set (IFUSIMPLE OPCODES).
initIfuM1Thru16Init IfuM locs 1-16B in current instruction set
ifuBackgroundWrite halt opcodes into Ifu memory
getIfuHaltReturns t, rscr = ifuHalt opcode (for IfuMemory)
initIfuMemoryInit selected opcodes into Ifu memory (IFUCOMPLEX OPCODES)
putIfuWdWrites (rscr,,rscr2) into IfuMemory at T
ifuAddParitySet parity bits for IfumLH, IfumRH (rscr, rscr2)
ifuCountOnesCount the number of one bits in t
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
May 6, 1982 11:19 PM
Add comments
June 17, 1981 3:34 PM
Add opSign3 instruction.
February 1, 1980 8:06 PM
Fix miscellaneous comments in fast opcodes init.
October 11, 1979 5:08 PM
Set Ifum[opPause] for inst ruction set 3 -- needed by event counters code.
June 15, 1979 4:35 PM
Change putIfuLH, putIfuRH, getIfuLH, getIfuRH to use mos.ifuCmmd
June 5, 1979 1:04 PM
Change symols ifu.Length* to ifu.IL*.
June 5, 1979 11:41 AM
Add calls to disableConditionalTask before writing Ifumemory, initializing regular memory system.
May 4, 1979 10:12 AM
Add calls to resetIfu after writing IfuM.
May 3, 1979 11:35 AM
Add missing composeIfuWd[], which should have been part of earlier fix to invoke putIfuWd directly.
May 3, 1979 9:59 AM
Remove extraneous endIfuWd[] from initIfum0Thru16.
May 3, 1979 9:07 AM
Make initIfuM1Thru* use iUsingInstrSet and call putIfuWd directly.
April 25, 1979 1:00 PM
Add fastExit, fastFetch, fastStore opcodes.
April 23, 1979 9:33 AM
Change InitIfum1thru3 to use the standard macros.
April 22, 1979 5:11 PM
Create this file from code in ifu1-ifu3.
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

* January 15, 1979 4:54 PM
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ifu Memory subroutines

This code doesn’t reset the Ifu. Caller Beware!

Enter with T = 10 bit IFU address. If writing ifum, rscr = 16 bit value
Exit W/ T = 16 bit value if reading IFUM.

Clobbers T
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

putIfuLH:
subroutine;* t = addr, rscr = value
t ← t OR (mos.ifuCmmd);* ifu data, not junk io
MOS ← t;* this sets the instruction set from B[6:7]
t ← lsh[t, 10];* left justify the byte
brkins ← t;* set brkins
noop;* wait for the address to filter to ram
IFUMLH ← rscr;* must keep data constant on B mux
return, B ← rscr;* for two cycles.

putIfuRH:
subroutine;* t = addr, rscr = value
t ← t OR (mos.ifuCmmd);* ifu data, not junk io
MOS ← t;* this sets the instruction set from B[6:7]
t ← lsh[t, 10];* left justify the byte
brkins ← t;* set brkins
noop;* wait for the address to filter to ram
IFUMRH ← rscr;* must keep data constant on B mux
return, B ← rscr;* for two cycles.

getIfuLH:
subroutine;* t = addr, returns lh value
t ← t OR (mos.ifuCmmd);* ifu data, not junk io
MOS ← t;* this sets the instruction set from B[6:7]
t ← lsh[t, 10];* left justify the byte
brkins ← t;* set brkins
noop;* wait for the address to filter to ram
return, t ← not(IFUMLH’);

getIfuRH:
subroutine;* t = addr, returns rh value
t ← t OR (mos.ifuCmmd);* ifu data, not junk io
MOS ← t;* this sets the instruction set from B[6:7]
t ← lsh[t, 10];* left justify the byte
brkins ← t;* set brkins
noop;* wait for the address to filter to ram
return, t ← not(IFUMRH’);
* June 5, 1979 11:42 AM

initIfuM1Thru3: subroutine;

* THESE OPCODES ARE USED IN IFUSIMPLE

pushReturn[];

call[disableConditionalTask];
call[resetIfu];
call[getIUsingInstrSet];
t ← lsh[t, 10];* position instr set value for writing ifuM
stack+1 ← t;

newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 1c;
call[putIfuWd], t ← t or (stack);

newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[2]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 2c;
call[putIfuWd], t ← t or (stack);

newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[3]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 3c;
call[putIfuWd], t ← t or (stack);
%
t←(1400C);
rscr←t OR (375C);* putIfuLH doesn’t clobber rscr!
call[putIfuLH], t ← (r0)+1;* ifuLH[1] ← 1775B
t ← (2c);
call[putIfuLH];* ifuLH[2] ← 1775B
t ← (3c);
call[putIfuLH];* ifuLH[3] ← 1775B;

rscr3 ← (277C);* common low 8 bits for ifuRH
t ← (rscr3) OR (75400c);
rscr ← t;
call[putIfuRH], t ← (r0)+1;* ifuRH[1] ← 75677B
t ← (rscr3) OR (73400c);
rscr ← t;
t ← (2c);
call[putIfuRH];* ifuRH[2] ← 37677B
t ← (rscr3) OR (61400C);
rscr ← t;
t ← (3c);
call[putIfuRH];* ifuRH[3] ← 61677B
%
call[resetIfu];* clear breakPending, which gets set as a result of writing IfuM.
pReturnP[];

* May 4, 1979 10:14 AM
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Initialize IFU memory for test case 2
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
initIfuM0Thru16: subroutine;
pushReturn[];
call[disableConditionalTask];
call[resetIfu];
call[getIUsingInstrSet];
t ← lsh[t, 10];* position instr set value for writing ifum
stack+1 ← t;
* opcode at iUsingInstrSet,,0: length=1,pause
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[1]; ifJump[0]; ifN[17];
composeIfuWd[];
call[putIfuWd], t ← stack;
* opcode at iUsingInstrSet,,1: length=1
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 1C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,2: length=2
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[2]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 2C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,3: length=3
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[3]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 3C;
call[putIfuWd], t ← t or (stack);
noop;* for placement.
* opcode at iUsingInstrSet,,4: length=1, n=11
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[11];
composeIfuWd[];
t ← 4C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,5: length=2 ,n=12
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[2]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[12];
composeIfuWd[];
t ← 5C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,6: length=3, n=13
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[3]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[13];
composeIfuWd[];
t ← 6C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,7: length=2, Sign, jump
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[1]; ifLength[2]; ifMemB[3]; ifPause[0]; ifJump[1]; ifN[17];
composeIfuWd[];
t ← 7C;
call[putIfuWd], t ← t or (stack);
noop;* for placement.
* opcode at iUsingInstrSet,,10: length=2, jump
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[2]; ifMemB[3]; ifPause[0]; ifJump[1]; ifN[17];
composeIfuWd[];
t ← 10C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,11: length=1, jump
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[1]; ifN[17];
composeIfuWd[];
t ← 11C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,12: length=1, jump, n=2
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[1]; ifN[2];
composeIfuWd[];
t ← 12C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,13: length=1, jump, n=2
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[1]; ifN[3];
composeIfuWd[];
t ← 13C;
call[putIfuWd], t ← t or (stack);
noop;* for placement.
* opcode at iUsingInstrSet,,14: length=1, sign, jump, n=17
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[1]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[1]; ifN[17];
composeIfuWd[];
t ← 14C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,15: length=1
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 15C;
call[putIfuWd], t ← t or (stack);
* opcode at iUsingInstrSet,,16: length=1
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[3]; ifPause[0]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← 16C;
call[putIfuWd], t ← t or (stack);
call[resetIfu];* clear breakPending, which gets set as a result of writing IfuM.
pReturnP[];

* June 5, 1979 11:43 AM
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ifuBackground
This subroutine causes all the locations in the Ifu memory to contain parity-valid instructions that will cause the processor to get an error (invoke the ERROR code) if any of them gets executed. This detects the case where the ifu starts executing an uninitialized opcode.
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ifuBackground:
pushReturn[];

call[disableConditionalTask];
call[resetIfu];
t ← 1777C;
cnt ← t;
ifuBackgroundL:
noop;
call[getIfuHalt];* Returns rscr2 = ifumLH, rscr = ifumRH.
t←cnt;
call[putIfuWd], stack+1←t;* t = address to write. Save cnt since
cnt ← stack&-1;* putIfuWd will clobber it.

loopUntil[CNT=0&-1, ifuBackgroundL];

call[resetIfu];* clear breakPending, which gets set as a result of writing IfuM.
returnP[];
* April 19, 1979 11:10 AM
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
getIfuHalt
This subroutine returns rscr2 = ifumLH, rscr = ifumRH for an opcode that causes the processor to start executing code that invokes an error. Parity has not been computed.
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
getIfuHalt:
pushReturn[];
newIfuWd[];
ifPa[0]; ifAd[22]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[1]; ifJump[0]; ifN[17];
composeIfuWd[];
t ← rscr2;
returnP[];


* June 17, 1981 3:34 PM
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
initIfuMemory

THESE OPCODES ARE USED IN IFUCOMPLEX!
Initialize the Ifu memory to contain opcodes for the various tests used in the ifu diagnostic. The majority body of code in this subroutine consists of macros that construct integer values corresponding to the proper bits for the Ifu memory. The endIfuWd macro invokes the subroutine putIfuWd to write those values into the Ifu.
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

initIfuMemory: subroutine;
pushReturn[];
call[disableConditionalTask];
call[resetIfu];

*
pause (length 1)
iicPause:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[1]; ifJump[0]; ifN[17];
endIfuWd[3, opPause!];

*
jump . (length 0)
iicJump0
:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[0];
endIfuWd[3, jump0!];* write the constructed value into location jump0 of Ifu memory

*
jump.-1 (length=1)
iicJumpm1:
newIfuWd[];
ifPa[1]; ifAd[15]; ifSign[1]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[17];
endIfuWd[3, jumpM1!];

*
jump.+1 (length=1)
iicJp1:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[1];
endIfuWd[3, jump1!];

*
opNoop (length=1)
iicOpL1:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[4];
endIfuWd[3, opNoop!];

*
opNoopL2 (length=2)
iicopL2:
newIfuWd[];
ifPa[1]; ifAd[15]; ifSign[0]; ifLength[2]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[15];
endIfuWd[3, opNoopL2!];
noop;* for placement

*
opNoopL3 (length=3)
iicopL3:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[3]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[6];
endIfuWd[3, opNoopL3!];

*
jumpL2 (length=2)
iicJpL2:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[0]; ifLength[2]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[1];
endIfuWd[3, jumpL2!];

*
jumpML2 (length=2)
iicJmL2:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[1]; ifLength[2]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[17];
endIfuWd[3, jumpML2!];

*
opSign3 (length=3)
iicOpSign3:
newIfuWd[];
ifPa[0]; ifAd[15]; ifSign[1]; ifLength[3]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[17];
endIfuWd[3, opSign3!];
noop;* for placement

* February 1, 1980 8:07 PM
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Fast OpCodes
The microcode that handles these opcodes executes very quickly; ie., it circumvents the arduous, main loop for the general tests by performing an IfuJump[0] "in line" in the microcode. This implies that tests constructed with these opcodes will never return unless the microcode explicitly notices the test should terminate.
%*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* fast1 (length=1)
iicFast1:
newIfuWd[];
ifPa[0]; ifAd[14]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[1];
endIfuWd[3, fast1!];

*
fastJfail (length=2)
iicFastJfail:
newIfuWd[];
ifPa[0]; ifAd[13]; ifSign[0]; ifLength[2]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[17];
endIfuWd[3, fastJfail!];
noop;* for placement

*
fastJ (length=2)
iicFastJ:
newIfuWd[];
ifPa[0]; ifAd[16]; ifSign[0]; ifLength[2]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[17];
endIfuWd[3, fastJ!];

*
fastMJ (length=2)
iicFastMJ:
newIfuWd[];
ifPa[0]; ifAd[16]; ifSign[1]; ifLength[2]; ifMemB[0]; ifPause[0]; ifJump[1]; ifN[17];
endIfuWd[3, fastMJ!];
noop;* for placement

*
fastHalt (length=1)
iicfastHalt:
newIfuWd[];
ifPa[0]; ifAd[22]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[1]; ifJump[0]; ifN[17];
endIfuWd[3, fastHalt!];
noop;* for placement

*
fastExit (length=1)
iicfastExit:
newIfuWd[];
ifPa[0]; ifAd[10]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[17];
endIfuWd[3, fastExit!];
noop;* for placement

*
fastFetch (length=1)
iicfastFetch:
newIfuWd[];
ifPa[0]; ifAd[11]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[17];
endIfuWd[3, fastFetch!];
noop;* for placement

*
fastStore (length=1)
iicfastStore:
newIfuWd[];
ifPa[0]; ifAd[12]; ifSign[0]; ifLength[1]; ifMemB[0]; ifPause[0]; ifJump[0]; ifN[17];
endIfuWd[3, fastStore!];
noop;* for placement

call[resetIfu];* clear breakPending, which gets set as a result of writing IfuM.
returnP[];
* April 20, 1979 4:05 PM
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
putIfuWd
Write both left and right half of IFUM.
Enter with RSCR=ifuLH, RSCR2=ifuRH, T= ifu Address. Caller is responsible for resetting the Ifu before calling this routine! Call
ifuAddParity to correctly set the parity bits for this word of IFUM. Use putIfuLh and putIfuRh to write into IFUM.
%*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
putIfuWd: subroutine;
pushReturnAndT[];
call[ifuAddParity];* compute correct parity bits.

* now write rscr into IFUMLH and rscr2 into IFUMRH. Address is in Stack
putIfuWdFinishUp:
call[putIfuLh], t ← stack;* t ← ifu address, rscr = value for LH

rscr ← rscr2;
call[putIfuRH], t ← stack;* t = addr, rscr = value for RH

pReturnP[];
* February 6, 1979 2:54 PM
%
ifuAddParity
This routine expects rscr = ifuLH, rscr2 = ifuRH. It sets the parity bits in rscr2 as appropriate. It returns w/ rscr, rscr2 the same, EXCEPT for the correct parity bits set in rscr2.
%
ifuAddParity:
pushReturn[];
* compute pe0: n[0:3], memb low 2(memB[0:1]), instrAddr[0:1]
IfuAddPe0:
t← ldf[rscr2, ifu.nSize, ifu.nShift];* N first
call[ifuCountOnes];
q←t;

t←ldf[rscr2,2, ifu.memBlow2Shift];* now memB[0:1]
call[ifuCountOnes];
t←t+(q);
q←t;

t← ldf[rscr, 2, ifu.AdHi2Shift];* now InstrAddr[0:1];
call[ifuCountOnes];
t←t+(q);

t and (1c);* assume pe0 = 0. we’re computing even parity
skpif[ALU=0], t ← t-t;
t ← (1c);
t←lsh[t, ifu.pe0Shift];
rscr2 ← (rscr2) or t;* done w/ PE0

* compute pe1: instrAddr[2:9];
IfuAddPe1:
t← ldf[rscr, 10, ifu.AdLow8Shift];
call[ifuCountOnes];

t and (1c);* assume pe1 = 0. We’re computing even parity
skpif[ALU=0], t←t-t;
t ← 1c;
t←lsh[t, ifu.pe1Shift];
rscr2 ← (rscr2) or t;

* compute pe2: signN, packedAlpha, type[0:1], memBHi2, length[0:1]
IfuAddPe2:
t← ldf[rscr, ifu.paSize, ifu.paShift];* begin w/ packed alpha
q←t;

t←ldf[rscr2,ifu.signSize, ifu.signShift];* now ifuSign
call[ifuCountOnes];
t←t + (q);
q ← t;

t←ldf[rscr2, ifu.typeSize, ifu.typeShift];* now ifuSize
call[ifuCountOnes];
t←t + (q);
q ← t;

t ← ldf[rscr2, 2, ifu.memBhi2Shift];* now ifuBrHi2 (RBaseSelK, memBK)
call[ifuCountOnes];
t ← t + (q);
q ← t;

t ← ldf[rscr2, ifu.ILSize, ifu.ILShift];* now length of opcode
call[ifuCountOnes];
t←t+(q);

t and (1c);
skpif[ALU=0], t ← t-t;* assume even parity
t ← 1c;
t ← lsh[t, ifu.pe2Shift];
rscr2 ← (rscr2) or t;* done W/ PE2
returnP[];
* January 7, 1979 6:33 PM
ifuCountOnes: subroutine;* count the number of one bits in t.
* CLOBBER t, cnt. Return value in T. Push entering value of t onto stack.
pushReturn[];
cnt←17s;
stack+1←t;
t ← t-t;
icoL:
skpif[R EVEN], stack;
t ← t+1;* increment count of one bits when lsb of stack is one
loopUntil[CNT=0&-1, icoL], stack ← (stack) rsh 1;
pReturnP[];