{File name BusExt.mc Description: DandeLion Interlisp Emulator Bus Extension Author: Purcell Created: 31-May-84 16:45:34 Purcell 4-Aug-84 3:07:29 remove delay; mask adc to 12 bits Purcell 4-Aug-84 1:02:24 add delay to pcblt Purcell 1-Aug-84 20:48:27 forgot to "←ib" after "←ibNA"; 5 needed in pipe primed Purcell 30-Jul-84 20:59:53 start more pipe on inputs (4) (5 needs work] Purcell 28-Jul-84 15:56:16 check out Purcell 28-Jul-84 11:53:43 more desk checking of block, test bit 9 Purcell 27-Jul-84 0:42:14 restart pc bus block opcode Purcell 11-Jul-84 22:39:45 pc bus block write Purcell 11-Jul-84 16:41:15 add pipe delay in input and move TOSH← earlier Purcell 10-Jul-84 9:29:57 fix Y0 bug in output Purcell 26-Jun-84 14:19:53 } {INPUT: TOSH ← smallpl, DISP4[MiscIn], c1, at[0D,10, MiscDisp];} { (SETQ MBUS.OUTL (PLUS 0 (LLSH REG 4))) (SETQ MBUS.OUTM (PLUS 11 (LLSH REG 4))) (SETQ MBUS.INL (PLUS 9 (LLSH REG 4))) (SETQ MBUS.INM (PLUS 10 (LLSH REG 4))) (\DEVICE.OUTPUT DATA MBUS.OUTL) (\DEVICE.OUTPUT DATA MBUS.OUTM) (SETQ DATA (\DEVICE.INPUT MBUS.INL)) (SETQ DATA (\DEVICE.INPUT MBUS.INM)) (\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 } {PV} 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[uVirtL, U, 27];{TT}{uTT} {ok} RegDef[uVirtH, U, 0C];{TOS}{ibNA} {BitBlt}{OK} RegDef[uBusCtl, U, 2];{fZ=2} {BitBlt}{OK} RegDef[uAddr, U, 33];{rAddr}{fZ=3} {OK} RegDef[uDataOut, U, 12];{fZ=2} {OK} {L0 unused L1 Fix {L1.NoFixes} L2 0=normal, 1=test loop L3 phase and op} PCBKW: FloatNop, L1 ← L1.NoFixes, c1, opcode[60'b]; uPV ← PV, L2 ← 0, c2; { PPort ← TT xor TT, c3;} Rx ← 0FF + 1, c3; Q ← uPPsave, c1; PPort ← Q and ~Rx, c2; , c3; pcA1: MAR ← [rhS, S+0], c1; S ← S - 2, c2; rAddr{L} ← MD, FloatNop, c3; pcA2: MAR ← [rhS, S+0], c1; S ← S - 2, c2; FLTimes.WA.WB{% fZ=3}, Float.M, Xbus{mBusAddrM} ← MD, c3; pcA3: MAR ← [rhS, S+0], c1; S ← S - 1, c2; uTOS ← TOS, TT ← MD{virtL}, c3; {TT=rDataOut=virtL} pcA4: Rx{2*TOS} ← TOS LShift1, Xbus ← ibNA, 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: MAR ← [rhS, S+0], c1; S ← S + 5, c2; uVirtL ← TT, TT ← MD{virtH}, c3; rAddr ← rAddr -1, c1; uAddr ← rAddr, Rx ← 0{force remap}, c2; uVirtH ← TT, Xbus ← ibNA, XDisp, c3; pcBCtl: TOSH ← 0{uBusCtl}, Float.L, Xbus{mBusAddrL} ← uAddr, BRANCH[pcBOut, pcBIn, 0B], c1; pcBIn: TOSH ← TOSH or 1, GOTO[pcCtlj], c2; {set mBusCtl for reads} pcBOut: TOSH ← TOSH or 2, GOTO[pcCtlj], c2; {set mBusCtl for writes} pcCtlj: uBusCtl ← TOSH, c3; Xbus ← ib, XDisp, c1; Float.M, Xbus{mBusCtl} ← uBusCtl, L3 ← 0, DISP4[pcBlk], c2; {pcRead subroutine; return to pcReadRet+L3, use uAddr, update uAddr, read virt+TOS-1} pcRead: MAR ← Rx ← [rhRx, Rx-1], c1; pcRead2: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, L3Disp, BRANCH[$, pcRcr, 1], c2; 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; Noop, c1; Noop, c2; Xbus ← PPort, XwdDisp{9(,10)}, c3; pcBus1: rDataIn ← rDataIn or FloatResult, L3Disp, BRANCH[$, pcWait, 1], c1; Float.L, Xbus{mBusOData} ← uDataOut, RET[pcBusRet], c2; pcWait: Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, CANCELBR[pcBus, 0F], c2; {0: Block Read/Output Words}{uAddr=rAddr=last, TOS=cnt} CALL[pcRead], c3, at[0, 10, pcBlk]; {pcRead: MAR ← Rx ← [rhRx, Rx-1], c1; pcRead2: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, L3Disp, BRANCH[$, pcRcr, 1], c2; uAddr ← rAddr, rDataOut ← MD, RET[pcReadRet], c3; } pcOW: TOS ← TOS -1, CarryBr, c1, at[0, 10, pcReadRet]; uDataOut ← rDataOut, BRANCH[pcDn, pcBus, 0E], c2; {pcBus: Q ← PPort, XwdDisp{9,10}, c3; pcBus1: rDataIn ← rDataIn or FloatResult, L3Disp, BRANCH[$, pcWait, 1], c1; Float.L, Xbus{mBusOData} ← uDataOut, RET[pcBusRet], c2; } Noop, CALL[pcRead], c3, at[0, 10, pcBusRet], c3; {1: Block Read/Output Bytes} CALL[pcRead], c3, at[1, 10, pcBlk]; {pcRead: MAR ← Rx ← [rhRx, Rx-1], c1; pcRead2: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, L3Disp, BRANCH[$, pcRcr, 1], c2; uAddr ← rAddr, rDataOut ← MD, RET[pcReadRet], c3;} 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; Noop, CALL[pcRead], c3, at[1, 10, pcBusRet], c3; {3: Block Read/Output Nibbles} CALL[pcRead], c3, at[3, 10, pcBlk]; {pcRead: MAR ← Rx ← [rhRx, Rx-1], c1; pcRead2: rAddr ← rAddr -1, Float.L, Xbus{mBusAddrL} ← uAddr, L3Disp, BRANCH[$, pcRcr, 1], c2; uAddr ← rAddr, rDataOut ← MD, RET[pcReadRet], c3;} 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; {4: Block Input/Write Words} rAddr ← rAddr -1, c3, at[4, 10, pcBlk]; 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; pcIW: TOS ← TOS -1, NZeroBr, c1, at[4, 10, pcWriteRet]; uAddr ← rAddr, rDataIn ← 0, BRANCH[pcDn, pcBus, 0E], c2; {pcBus: Xbus ← PPort, XwdDisp{9,10}, c*; rDataIn ← rDataIn or FloatResult, L3Disp, BRANCH[$, pcWait, 1], c*; Float.L, Xbus{mBusOData} ← uDataOut, RET[pcBusRet], c*; } rDataIn ← rDataIn, CALL[pcWrite], c3, at[4, 10, pcBusRet]; pcWrite: 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]; { 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;} {{ Float.L, Xbus{mBusOData} ← uDataOut, c3, at[5, 10, pcBlk]; rAddr ← rAddr -1, Xbus ← FloatResult{mBusIData}, FLFloatA{fZ=2}, Float.L, c1; uAddr ← rAddr, rDataIn ← 0, GOTO[pcBus], c2;}} pcIB: TOS ← TOS -1, NZeroBr, L3 ← 5, c1, at[0D, 10, pcWriteRet]; uAddr ← rAddr, rDataIn ← 0, BRANCH[pcDn, pcBus, 0E], c2; 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[pcBus3], c2; {pcBus2: uAddr ← rAddr, c2; uDataOut ← rDataOut, c3; Xbus ← PPort, XwdDisp{9(,10)}, c3; pcBus1: rDataIn ← rDataIn or FloatResult, L3Disp, BRANCH[$, pcWait, 1], c1; Float.L, Xbus{mBusOData} ← uDataOut, RET[pcBusRet], c2; } rDataIn ← rDataIn {and uF000}, CALL[pcWrite], c3, at[0D, 10, pcBusRet]; {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, rhTT ← uVirtH, GOTO[pcMp], c3; pcInc: Q ← rhTT+1, LOOPHOLE[byteTiming], c2; rhTT ← Q LRot0, c3; pcMp: Map ← Q ← [rhTT, TT], BRANCH[pcMp2, pcInc], c1; pcMp2: TOS ← TOS + 1, c2; Rx ← rhRx ← MD, XwdDisp, c3; Map ← Q ← [rhTT, TT], BRANCH[$, pcFault, 1], c1; MDR ← Rx or 30, c2; L3Disp, c3; pcMpD: MAR ← Rx ← [rhRx, TT+0], BRANCH[pcRead2, pcWrite2, 0B], c1; {% fix ups} pcFault: TOSH ← smallpl, c2; Q ← uPPsave, c3; PPort ← Q, c1; PV ← uPV, GOTO[RWTrap], c2; pcDn: S ← S - 6, L2Disp, c3; TOSH ← smallpl, BRANCH[$, pcRep], c1; , c2; pcAlmost: Rx ← uPPsave, c3; pcEnd: PPort ← Rx, L2 ← L2.0, c1; PV ← uPV, IBDisp, c2; PC ← PC + 1, L2 ← L2.0, DISPNI[OpTable], c3; pcRep: S ← S + 6, c2; TOS ← uTOS, GOTO[pcA1], c3; BusX: FloatNop{free BX in 2 BX cycles}, c2, at[09,10,MiscIn];{read L} TOS ← TOS LRot12, {FloatUMS,} c3; Ybus ← TOS, AltUaddr, c1; FloatULP, TOS ← FloatResult, c2; pcInDn: TOS ← FloatResult, c3; GOTO[IB.nop], c1; FloatNop{free BX in 2 BX cycles}, c2, at[0A,10,MiscIn];{read M} TOS ← TOS LRot12, {FloatUMS,} c3; Ybus ← TOS, AltUaddr, c1; FloatUMP, TOS ← FloatResult, GOTO[pcInDn], c2; {TT ← MD,} c3, at[0,10,MiscOut];{Write L} FloatNop{free BX in 2 BX cycles}, c1; TOS ← TOS LRot12, FloatUMS, c2; rhRx ← nRhS, Rx ← S + 2, c3; MAR ← Rx ← [rhRx, Rx + 0], c1; Ybus ← TOS, AltUaddr, L2 ← L2.0, IBDisp, c2; FloatULP, Xbus ← MD { ← FloatResult}, L2 ← L2.0, DISPNI[OpTable], c3; {TT ← MD,} c3, at[0B,10,MiscOut];{Write M} FloatNop{free BX in 2 BX cycles}, c1; TOS ← TOS LRot12, FloatUMS, c2; rhRx ← nRhS, Rx ← S + 2, c3; MAR ← Rx ← [rhRx, Rx + 0], c1; Ybus ← TOS, AltUaddr, L2 ← L2.0, IBDisp, c2; FloatUMP, Xbus ← MD, L2 ← L2.0, DISPNI[OpTable], c3; { E N D }