{File name <tajo>TMyBusExt.mc Description: DandeLion Interlisp Emulator Bus Extension Author: Purcell Created: 31-May-84 16:45:34 } { purcell 3-Jun-85 23:03:10 add long delays in bus} { by don 24-Mar-85 11:40:24 deleted spurious output at tail of input/writes added extra arg for BusCtl command added u for mBusAddrM {fZ = 3} added u for orig alpha changed stack reads to STK saved L {instead of PV} fixed page fault exits fixed normal exits reallocated u regs changed loading of rhTT from uVirtH } {INPUT: TOSH ← smallpl, DISP4[MiscIn], c1, at[0D,10, MiscDisp];} { (\PCBLT (alpha op) VIRTUALADDR PCADDRH PCADDRL COUNT) L3Disp values initialized to alpha byte 1,2 bit data size: 0=word, 1=byte, 2=reversed bytes, 3=nibble 4 bit 0=output, 1=input 8 bit extra states 0 read/output word 1,9 read/output bytes 2,A read/output bytes reversed 3,7,B,F read/output nibbles 4 input/write word 5,D input/write bytes 6,E input/write bytes reversed } {L} RegDef[rAddr, R, 3]; {pc bus address low 16 bits} {TOSH} RegDef[rDataIn, R, 1]; {TT} RegDef[rDataOut, R, 2]; {rDataOut not needed during cross so alias with and use TT} {Rx real TOS word count remaining (end input/write at 0; end read/output at -1)(fetch from virt+TOS-1) Q used by mapping routine } RegDef[uPPsave, U, 0CE];{unused u reg} RegDef[uxx3, U, 43];{fZ=3} RegDef[uAlpha, U, 4B];{any temp} RegDef[uVirtL, U, 27];{TT} RegDef[uVirtH, U, 4A];{any temp} RegDef[uBusCtl, U, 52];{fZ=2} RegDef[uAddr, U, 33];{rAddr}{fZ=3} RegDef[uDataOut, U, 42];{fZ=2} {RegDef[UrL, U, 3B]; {rA = L, fZ = ←RH}} {L0 unused L1 Fix {L1.None} {L2 0=normal, 1=test loop // unused} L3 phase and op} { orig alpha: == operation 0 read/output word 1 read/output bytes 2 read/output bytes reversed 3 read/output nibbles 4 input/write word 5 input/write bytes 6 input/write bytes reversed TOS count{16 bits} STK-0 bus control word STK-1 low base address out{16 bits} STK-2 mBusAddrM{16 bits} STK-3 virt addr of buffer{24 bits} STK-5 operation{3 bits} Regs: L saved into UrL TOS remaining count T temp Rx temp TT temp UrL ← L uPPsave last write to PP uVirtL buffer addr lo uAddr Bus addr uBusCtl Control to Bus uDataOut data out } { in new version of Misc.mc @ESC: Xbus ← ibHigh, XDisp, c1, opcode[370'b]; ESCx: TT ← ib, XDisp, push, DISP4[ESCHi], c2; PC ← PC + 1, STK ← TOS, pop, DISP4[ESC8n], c3, at[8,10,ESCHi]; } { this replaces @BANDBLT } PCBKW: at[3,10,ESC8n], FloatNop, L1 ← L1.None, c1; UrL ← L, L2 ← 0, c2; Rx ← 0FF + 1, c3; Q ← uPPsave, c1; PPort ← Q and ~Rx, c2; FloatNop, c3; {seventh arg in TOS} Rx ← STK, pop, c1;{sixth arg} uBusCtl ← Rx, c2; , c3; rAddr ← STK, pop, c1;{fifth arg} Rx ← STK, pop, c2;{fourth arg} uxx3 ← Rx, c3; Rx ← STK, pop, c1;{third arg} uVirtH ← Rx, c2; Rx ← STK, pop, c3;{second arg} uVirtL ← Rx, c1; Rx ← STK, pop, c2;{first arg} uAlpha ← Rx, c3; Rx{2*TOS} ← TOS LShift1, c1; FLTimes.WA.WB{% fZ=3}, Float.M, Xbus{mBusAddrM} ← uxx3, c2; , c3; {TT=rDataOut=virtL} pcA4: Xbus ← uAlpha, XDisp, c1; rDataIn{4*TOS} ← Rx LShift1, DISP4[pcAdd, 0C], c2; rAddr ← rAddr + TOS, GOTO[pcArg], c3, at[0C, 10, pcAdd];{word addressing} rAddr ← rAddr + Rx{2*TOS}, GOTO[pcArg], c3, at[0D, 10, pcAdd];{byte addressing} rAddr ← rAddr + Rx{2*TOS}, GOTO[pcArg], c3, at[0E, 10, pcAdd];{byte reversed} rAddr ← rAddr + rDataIn{4*TOS}, GOTO[pcArg], c3, at[0F, 10, pcAdd];{nibble addressing} pcArg: rAddr ← rAddr -1, c1; uAddr ← rAddr, Rx ← 0{force remap}, c2; Xbus ← uAlpha, XDisp, c3; pcBCtl: Float.L, Xbus{mBusAddrL} ← uAddr, BRANCH[pcBOut, pcBIn, 0B], c1; pcBIn: {T{TOSH} ← T{TOSH} or 1, }GOTO[pcCtlj], c2; {set mBusCtl for reads} pcBOut: {T{TOSH} ← T{TOSH} or 2, }GOTO[pcCtlj], c2; {set mBusCtl for writes} pcCtlj: {uBusCtl ← T{TOSH}}, c3; Xbus ← uAlpha, XDisp, c1; Float.M, Xbus{mBusCtl} ← uBusCtl, L3 ← 0, {L3 ← alpha} DISP4[pcBlk], c2; {pcRead subroutine; return to pcReadRet+L3, use uAddr, update uAddr, read virt+TOS-1} pcRead: MAR ← Rx ← [rhRx, Rx-1], BRANCH[$, pcDn2], c1; rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, L3Disp, BRANCH[$, pcRcr, 1], c2; pcRead3: uAddr ← rAddr, rDataOut ← MD, RET[pcReadRet], c3; {pcBus subroutine: return to pcBusRet+L3, used both for input and output; rDataIn ignored on output} pcBus2: Noop, c2; pcBus3: uAddr ← rAddr, c3; uDataOut ← rDataOut, c1;{% good for 5; ok others ?} Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, c2; pcBus: Noop, c3; pcBus1: Noop, CANCELBR[$, 3], c1; Noop, c2; {%P 3-Jun-85 23:02:25} { Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2;} Ybus ← rDataIn, Xbus ← PPort, XwdDisp{9(,10)}, c3; Q ← rDataIn or FloatResult, L3Disp, BRANCH[$, pcWait, 1], c1; rDataIn ← Q, Float.L, Xbus{mBusOData} ← uDataOut, {RET[pcBusRet{%T}],} BRANCH[pcBRo, pcBRi, 0B], c2; pcWait: Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, CANCELBR[pcBus, 0F], c2; pcBus3CH: uAddr ← rAddr, c3; uDataOut ← rDataOut, c1;{% good for 5; ok others ?} Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, c2; {%P 3-Jun-85 23:02:25} pcBusCH: Noop, c3; { Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3; Noop, c1; Noop, c2; Noop, c3;} pcBus1CH: Ybus ← TOS - 1, ZeroBr, CANCELBR[$, 3], c1; BRANCH[$, pcskipit], c2; Ybus ← rDataIn, Xbus ← PPort, XwdDisp{9(,10)}, c3; Q ← rDataIn or FloatResult, L3Disp, BRANCH[$, pcWaitCH, 1], c1; rDataIn ← Q, Float.L, Xbus{mBusOData} ← uDataOut, {RET[pcBusRet{%T}],} BRANCH[pcBRo, pcBRi, 0B], c2; pcBRo: Ybus ← 2, YDisp, L3Disp, GOTO[pcBR] c3; pcBRi: Ybus ← rDataIn and 2, YDisp, L3Disp, GOTO[pcBR] c3; pcBR: L3Disp, BRANCH[zBit1, $, 0D], c1; Noop, RET[pcBusRet], c2; zBit1: Xbus ← TIData,{%T} RET[pcBusRet], c2; pcWaitCH: Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, CANCELBR[pcBusCH, 0F], c2; pcskipit: Ybus ← rDataIn, Xbus ← PPort, XwdDisp{9(,10)}, c3; Q ← rDataIn or FloatResult, L3Disp, BRANCH[$, pcWaitCHs, 1], c1; rDataIn ← Q, FloatNop{turn off mBusIData}, {RET[pcBusRet{%T}],} BRANCH[pcBRo, pcBRi, 0B], c2; pcWaitCHs: Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, CANCELBR[pcBusCH, 0F], c2; {0: Block Read/Output Words}{uAddr=rAddr=last, TOS=cnt} CALL[pcRead], c3, at[0, 10, pcBlk]; pcOW: TOS ← TOS -1, CarryBr, c1, at[0, 10, pcReadRet]; uDataOut ← rDataOut, BRANCH[pcDn, pcBus, 0E], c2; Noop, CALL[pcRead], c3, at[0, 10, pcBusRet], c3; {1: Block Read/Output Bytes} CALL[pcRead], c3, at[1, 10, pcBlk]; pcOB: TOS ← TOS -1, CarryBr, L3 ← 9, c1, at[1, 10, pcReadRet]; uDataOut ← rDataOut, BRANCH[pcDn, pcBus, 0E], c2; rDataOut ← rDataOut LRot8, L3 ← 1, c3, at[9, 10, pcBusRet]; pcOBB: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, GOTO[pcBus2], c1; CALL[pcRead], c3, at[1, 10, pcBusRet], c3; {2: Block Read/Output Bytes Reversed} Ybus ← TOS, ZeroBr, CALL[pcRead], c3, at[2, 10, pcBlk]; pcOBr: rDataOut ← rDataOut LRot8, c1, at[2, 10, pcReadRet]; uDataOut ← rDataOut, L3 ← 0A, c2; TOS ← TOS-1, Xbus ← PPort, XwdDisp{9(,10)}, GOTO[pcBus1], c3; {TOS was tested for zero at Read} rDataOut ← rDataOut LRot8, L3 ← 2, c3, at[0A, 10, pcBusRet]; pcOBBr: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, GOTO[pcBus2], c1; Ybus ← TOS, ZeroBr, , CALL[pcRead], c3, at[2, 10, pcBusRet], c3; {3: Block Read/Output Nibbles} CALL[pcRead], c3, at[3, 10, pcBlk]; pcON: TOS ← TOS -1, CarryBr, L3 ← 7, c1, at[3, 10, pcReadRet]; uDataOut ← rDataOut, BRANCH[pcDn, pcBus, 0E], c2; rDataOut ← rDataOut LRot12, L3 ← 0B, c3, at[7, 10, pcBusRet]; pcONN: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, GOTO[pcBus2], c1; rDataOut ← rDataOut LRot12, L3 ← 0F, c3, at[0B, 10, pcBusRet]; pcONNN: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, GOTO[pcBus2], c1; rDataOut ← rDataOut LRot12, L3 ← 3, c3, at[0F, 10, pcBusRet]; pcONNNN: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, GOTO[pcBus2], c1; Noop, CALL[pcRead], c3, at[3, 10, pcBusRet], c3; pcInPipeStart: uAddr ← rAddr, c1; Float.L, Xbus{mBusOData} ← uDataOut, c2; Float.L, Xbus{mBusAddrL} ← uAddr, c3; rAddr ← rAddr -1, Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, c1; uAddr ← rAddr, rDataIn ← 0, GOTO[pcBus], c2; {4: Block Input/Write Words} rAddr ← rAddr -1, c3, at[4, 10, pcBlk]; pcInPipeStartCH: uAddr ← rAddr, c1; Float.L, Xbus{mBusOData} ← uDataOut, c2; Float.L, Xbus{mBusAddrL} ← uAddr, c3; rAddr ← rAddr -1, Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, c1; uAddr ← rAddr, rDataIn ← 0, GOTO[pcBusCH], c2; pcIW: TOS ← TOS -1, NZeroBr, c1, at[4, 10, pcWriteRet]; uAddr ← rAddr, rDataIn ← 0, BRANCH[pcDnCH, pcBusCH, 0E], c2; rDataIn ← rDataIn, CALL[pcWrite], c3, at[4, 10, pcBusRet]; pcWrite: {% T test bit 1} Ybus ← rDataIn, YDisp, c1; BRANCH[zeroBit1, $, 0D], c2; Noop, GOTO[pcWrite1], c3; zeroBit1: Xbus ← TStatus, GOTO[pcWrite1], c3; pcWrite1: MAR ← Rx ← [rhRx, Rx-1], c1; pcWrite2: MDR ← rDataIn, Float.L, Xbus{mBusAddrL} ← uAddr, L3Disp, BRANCH[$, pcWcr, 1], c2; rAddr ← rAddr -1, Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, RET[pcWriteRet], c3; {5: Block Input/Write Bytes} rAddr ← rAddr -1, GOTO[pcInPipeStart], c3, at[5, 10, pcBlk]; rDataIn ← rDataIn {and 0F}, L3 ← 0D, c3, at[5, 10, pcBusRet]; pcIBB: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, c1; rDataIn ← rDataIn LRot8, GOTO[pcBus3CH], c2; rDataIn ← rDataIn LRot8, CALL[pcWrite], c3, at[0D, 10, pcBusRet]; pcIB: TOS ← TOS -1, NZeroBr, L3 ← 5, c1, at[0D, 10, pcWriteRet]; uAddr ← rAddr, rDataIn ← 0, BRANCH[pcDn, pcBus, 0E], c2; {6: Block Input/Write Bytes Reversed} rAddr ← rAddr -1, GOTO[pcInPipeStart], c3, at[6, 10, pcBlk]; rDataIn ← rDataIn {and 0F}, L3 ← 0E, c3, at[6, 10, pcBusRet]; pcIBBr: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, c1; rDataIn ← rDataIn LRot8, GOTO[pcBus3CH], c2; rDataIn ← rDataIn LRot0, CALL[pcWrite], c3, at[0E, 10, pcBusRet]; pcIBr: TOS ← TOS -1, NZeroBr, L3 ← 6, c1, at[0E, 10, pcWriteRet]; uAddr ← rAddr, rDataIn ← 0, BRANCH[pcDn, pcBus, 0E], c2; {Exceptions} {Remap to Virt+TOS-1}{don't fault if TOS=0} pcWcr: Noop, CANCELBR[pcCr, 0F], c3; pcRcr: rAddr ← rAddr +1, CANCELBR[pcCr, 0F], c3; pcCr: TOS ← TOS -1, CarryBr, c1; TT ← uVirtL, BRANCH[pcCz, pcCnz], c2; pcCz: rhTT ← uVirtH, GOTO[pcMp], c3; pcCnz: TT ← TT + TOS, CarryBr, c3; rhTT ← uVirtH, BRANCH[pcnoInc, pcInc], c1; pcnoInc: , c2; GOTO[pcMp], c3; pcInc: Q ← rhTT+1, LOOPHOLE[byteTiming], c2; rhTT ← Q LRot0, GOTO[pcMp], c3; pcMp: Map ← Q ← [rhTT, TT], c1; TOS ← TOS + 1, c2; Rx ← rhRx ← MD, XwdDisp, c3; Map ← Q ← [rhTT, TT], DISP2[pcFault], c1; MDR ← Rx or 0B0, GOTO[beWMapb], c2, at[0,4,pcFault]; MDR ← Rx or 0B0, GOTO[beWMapb], c2, at[1,4,pcFault]; beWMapb: L3Disp, c3; pcMpD: MAR ← Rx ← [rhRx, TT+0], BRANCH[pcRead2, pcWrite2, 0B], c1; pcRead2: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, L3Disp, GOTO[pcRead3], c2; {% fix ups} pcFault: T ← qWriteProtect, GOTO[beWMapX], c2, at[2,4,pcFault]; T ← qPageFault, GOTO[beWMapX], c2, at[3,4,pcFault]; beWMapX: {push stack back = 6 push's} Q ← uPPsave, push, c3; PPort ← Q, push, c1; L ← UrL, push, c2; PC ← PC - 1, push, c3; push, c1; L1Disp, push, GOTO[WTrap], c2; {exits} pcDnCH: GOTO[pcDn1], c3; pcDn2: , CANCELBR[$, 2], c2; pcDn: , c3; pcDn1: L ← UrL, CANCELBR[$, 3], c1; Rx ← uPPsave, IBDisp, c2; PPort ← Rx, DISPNI[OpTable], c3; { E N D }