{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 }