:IF[AltoMode]; TITLE[MesaX--Alto.Mode]; :ELSE; TITLE[MesaX--Pilot.Mode]; :ENDIF; *Dispatch base addresses SET[xfPage1p, LSHIFT[xfPage1,10]]; SET[xftype, ADD[xfPage1p, 140]]; SET[xfWRtab, ADD[xfPage1p, 160]]; SET[xfRRtab, ADD[xfPage1p, 200]]; SET[MiscDisp, ADD[xfPage1p, 220]]; OnPage[xfpage1]; *since xfPage1 has NextData's and NextInsts, it must have refill link at 377 xfRefill: gotop[MesaRefill], Pfetch4[PC,IBUF,4], AT[OR[LSHIFT[xfPage1,10],377]]; xfRet: return; SaveRLink: xfRLink ← T, return; EXMemStat: MemStat ← EarlyXfer, return; Xfer: xfXTSreg ← rsh[xfXTSreg,1], goto[XferNTC, REven]; *Trap check *Cause xfer trap with 0 as reason, xfMX as trap parameter T ← xfMX, LoadPage[7]; xfXTSreg ← 0c, gotop[XTrap]; XferNTC: dispatch[xfMX,16,2]; *entry for no trap check T ← xfMX, disp[XferType0]; *Control link is a frame pointer XferType0: xfCount ← T, skip[ALU#0], AT[xftype,0]; *save frame pointer RTEMP ← sControlFault, dblgoto[QTrap,QTrapF,MB]; *MB => don't free frame PFetch2[MDS,xfTemp], call[EXMemStat]; *Fetch G and PC T ← (LOCAL)-1, skip[MB]; PFetch1[MDS,xfFSI]; *Start freeing the current frame T ← xfTemp; *New G lu ← (GLOBAL) xor (T), skip[ALU#0]; T ← sUnbound, goto[StashMX]; *New G = 0 GLOBAL ← T, goto[CValid,ALU=0]; *NewG # OldG => load G and C GetGC: PFetch4[MDS, IBUF], call[xfRet]; *Fetch global frame overhead call[LoadC]; xfGfiWord ← T; *Finish freeing the current frame if required. CValid: T ← (xfFSI) + (xfav), goto[FreeDone, MB]; PFetch1[MDS, xfFrame]; *fetch the list head PStore1[LOCAL,xfFrame,0], call[xfRet]; *Store head of list into Local[0]; PStore1[MDS, LOCAL]; *Store LOCAL into list head :IF[AltoMode]; ************************************** FreeDone: T ← lsh[xfTemp1, 1], goto[PCok, r >= 0]; T ← (Zero) - T; xfTemp ← (Zero) + (T) + 1, goto[PCokx]; :ELSE; ********************************************** FreeDone: T ← xfTemp1; :ENDIF; ********************************************* PCok: xfTemp ← T; PCokx: T ← xfCount, LoadPage[7]; LOCAL ← T, gotop[XferGO]; *Control Link is a procedure descriptor XferType1: xfCount ← T, AT[xftype,1]; *save descriptor T ← xfgft; T ← (ldf[xfCount,0,11]) + (T); T ← (ldf[xfCount,0,11]) + (T); * 2*gfi + gft PFetch2[MDS,xfTemp], call[EXMemStat]; *Fetch G and the entry vector offset T ← xfTemp; *New G GLOBAL ← T, skip[ALU#0]; T ← sUnbound, goto[StashMX]; *Trap PFetch4[MDS, IBUF]; *Fetch the global frame overhead T ← xfTemp1, task; *Calculate the entry vector index xfCount ← (ldf[xfCount,11,5]) + (T) +1; xfCount ← lsh[xfCount,1], call[LoadC]; * 2*evi + 2 xfGfiWord ← T, LoadPage[7]; T ← xfCount, gotop[.+1]; OnPage[7]; PFetch2[CODE,xfTemp]; *fetch PC and FSI LFCEntry: T ← ldf[xfTemp1,10,10], goto[Alloc]; *Get a frame AllocRetx: PStore4[MDS, GLOBAL]; *Initialize frame xfTemp ← lsh[xfTemp,1]; *Form byte PC MNBR ← LOCAL, LOCAL ← t, NoRegILockOK, skip[MB]; T ← MNBR, call[Free]; XferGO: PCF ← xfTemp, TASK; *Enter here from XferType0 MemStat ← XferFixup; T ← rsh[xfTemp,1]; PFetch4[CODE,IBUF]; PC ← T; *bypass kludge PC ← (PC) and not (3c); PFetch4[LOCAL,LocalCache0,4]; :IF[AltoMode]; **************************************** nop; * allow page fault to happen before load page t←CODEhi, LoadPage[0]; PChi←t, call[SwapBytes]; :ELSE; ************************************************ t←CODEhi; PChi←t; :ENDIF; *********************************************** T ← xfBrkByte; MemStat ← Normal, goto[DoBB, ALU#0]; DispMan: T ← NextData[IBUF]; *must execute one instruction without interrupts xfBrkByte ← T, skip[ALU#0]; *skip over NOPs goto[DispMan]; DoBB1: xfBrkByte ← (xfBrkByte) or (40400c); DMx: xfBrkByte ← lcy[xfBrkByte,2]; APC&APCTask ← xfBrkByte; xfBrkByte ← zero, RETURN; DoBB: lu ← NextData[IBUF], Call[DoBB1]; *skip the instruction in IBUF P7Tail: lu ← NextInst[IBUF], AT[P7TailLoc]; P7Tailx: MemStat ← Normal, NIRET; *Control link is indirect XferType2: PFetch1[MDS,RTEMP], AT[xftype,2]; call[xfRet]; Dispatch[RTemp,16,2]; T ← RTEMP, disp[XferType0]; *Control link is unbound whatsis XferType3: T ← sUnbound, goto[StashMX], AT[xftype,3]; *Load the C register from the global frame information in IBUF..IBUF2 LoadC: T ← IBUF1, skip[REven]; T ← sCSegSwappedOut, goto[StashMX]; CODE ← T; lu ← ldf[IBUF2,0,10]; lu ← ldf[IBUF2,10,2], skip[ALU=0]; *Check for short C T ← MDShi, goto[SetCODEhi]; *and use MDShi if so T ← IBUF2, skip[ALU=0]; *check for code out of bounds T ← IBUF2 ← (IBUF2) or (100c); *and set bits 1 and 9 if so T ← (lsh[IBUF2,10]) or (T); SetCODEhi: CODEhi ← T; T ← IBUF, return; *return GfiWord in T OnPage[7]; *Enter from @ALLOC or XferType1 with FSI in T. Returns frame in T. *Return to PushTP7 if MemStat.0 = 1, else to AllocRetx. Alloc: T ← (lsh[R400,1]) + (T); PFetch1[MDS,xfFrame], task; *the head of the list (can't fault) xfRSAV ← T; lu ← ldf[xfFrame,16,1], skip[ROdd]; T ← xfFrame, dblgoto[FrType0, FrType2, ALU=0]; T ← xfFrame, dblgoto[FrType1, FrType3, ALU=0]; FrType0: PFetch1[MDS, RTemp1]; *Fetch Frame[0] T ← xfRSav; PStore1[MDS, RTemp1]; *Store into head of list T ← xfFrame; MemStat ← (MemStat) and not (100000c), dblgoto[AllocRetx, PushTP7, R>=0]; FrType2: T ← rsh[xfFrame,2], goto[Alloc]; *Indirect FrType3: T ← rsh[xfFrame,2], goto[Alloc]; *Indirect FrType1: MemStat ← (MemStat) and not (100000c), goto[XATrap, R>=0]; *Trap - check for call from @ALLOC xfATPreg ← lsh[xfATPreg,2], call[SavePCInFrame]; *call was from @ALLOC LoadPage[xfPage1]; RTEMP ← sAllocListEmpty, goto[QTrap]; *don't free frame XATrap: T ← xfMX; *call was from Xfer - check for LFC xfATPreg ← T, goto[LFCAlloc,ALU=0]; LoadPage[xfPage1], goto[DoAllocTrap]; LFCAlloc: xfCount ← lsh[xfCount,1]; *Trap from LFC. Fab procedure descriptor xfCount ← (xfCount) - (3c); T ← (xfGfiWord) and not (177c); T ← (xfCount) + (T); * + is important - don't use OR xfATPreg ← T, LoadPage[xfPage1]; DoAllocTrap: RTEMP ← sAllocListEmpty, dblgoto[QTrap, QTrapF, MB]; *SUBROUTINE Free frees the frame in T. Free: T ← (AllOnes) + (T); PFetch1[MDS, xfFSI]; *get the frame's FSI xfFrame ← T, usectask; *bypass kludge - depends on MDS being 0 T ← APC&APCTask, TASK; xfRLink ← T; xfFSI ← T ← (xfFSI) + (xfAV); PFetch1[MDS, RTemp1]; *Fetch list head T ← xfFrame ← (xfFrame) + 1; PStore1[MDS, RTemp1], task; *Store head into frame T ← 100c; *Set MB ( => free finished) T ← xfFSI, SAluf ← T, task; PStore1[MDS, xfFrame]; *Store frame into head APC&APCTask ← xfRLink, goto[P7Ret]; OnPage[xfPage1]; SaveState: * usectask in calling instruction T ← APC&APCTASK, call[SaveRLink]; *save link in rlink T ← (xfTemp) + (11c); Pstore1[MDS, LOCAL], call[sv377]; T ← (stkp) xor T; * true stack pointer to T xfTemp2 ← T; T ← (xfTemp) + (10c), task; Pstore1[MDS, xfTemp2]; T ← (xfTemp2) - (7c); xfTemp1 ← 10c, skip[carry]; xfTemp1 ← (xfTemp1) + T + 1; * stack depth + 2 (8+(d-7)+1) stkp ← xfTemp1, T ← (xfTemp1) - 1; svloop: call[svpop]; T ← (stkp) xor T; * true stack pointer to T T ← (AllOnes) + T, goto[svloop, alu#0]; * T ← offset in saved stack apc&apctask ← xfRlink, goto[xfRet]; svpop: T ← (xfTemp) + T; Pstore1[MDS, Stack]; sv377: T ← (377c), return; LoadStateNF: T ← 100c; *Entry from Process mechanism and MStart. Ensure no frame freeing. SAluf ← T; LoadState: T ← (xfTemp) + (10c); Pfetch1[MDS,xfBrkByte], call[xfRet]; T ← (xfTemp) + (11c); Pfetch1[MDS,xfMX]; NWW ← (NWW) and not (100000c); T ← (xfTemp) + (12c); Pfetch1[MDS,xfMY], task; stkp ← RZero; T ← (xfBrkByte) and (17c); IBuf ← T; * stack depth saved for stkp below xfTemp1 ← 10c; T ← (IBuf) - (7c); * check for 7 or 8, T ← d-7 xfBrkByte ← rsh[xfBrkByte,10], skip[carry]; xfTemp1 ← (xfTemp1) + T + 1; * stack depth+2 (8+(d-7)+1) xfTemp2 ← T ← ZERO, call[ldloop]; ldloop: lu ← (xfTemp1) - T; T ← (xfTemp) + T, goto[ldpush, alu#0]; stkp ← IBuf, goto[Xfer]; ldpush: Pfetch1[MDS, Stack]; xfTemp2 ← T ← (xfTemp2) + 1, return; * return to ldloop * In general, we want to do the FreeSub after all possible Xfer page faults * can occur, but before all other traps. * UnBound, & cSwappedOut Traps come here StashMX: RTEMP ← T, TASK; * RTEMP holds SD index (through Free) T ← xfMX; xfOTPreg ← T, dblgoto[QTrap,QTrapF, MB]; * XferTrap, AllocTrap, & Control Traps come here if they need to free the frame, else to QTrap QTrapF: T ← LOCAL, call[FreeX]; QTrap: RTEMP ← (RTEMP) + (xfav); T ← (RTEMP) + (xfsdoffset); pfetch1[MDS,xfMX], goto[Xfer]; FreeX: LoadPage[7]; gotop[Free]; onpage[opPage3]; *Start from Nova. MStart: xfTemp ← T; *Pointer to State for LoadState T ← MDShi; *Initialize some Mesa Emulator registers GLOBALhi ← T; GLOBAL ← 1c; *Clobber G so that C will always be reloaded at the first Xfer LOCALhi ← T; MEMSTAT ← T ← 0c; xfMX ← 1c; NWW ← T; *Wipe out pending interrupts TickCount ← 3c, call[FFaultStack]; Stack ← (Stack) or (1c); * FFAULT ← "trap on page fault" xfXTSReg ← T, loadpage[xfPage1]; Local ← 0c, gotop[LoadStateNF]; FFaultStack: RTEMP ← FFaultAdd; Stkp ← RTEMP, return; SavePCInFrame: T ← CODE; *CODEhi and PChi are equal, so we only need to worry about the low word T ← (PC) - (T); *15 bits, since code segments are < 32k. :IF[AltoMode]; ************************************** T ← ldf[GetRSpec[127], 14,3] + T, skip[R even]; RTemp1 ← (Zero) - T, goto[StorPC]; RTemp1 ← T, goto[StorPC]; :ELSE; ********************************************** RTemp1 ← T; T ← PCFreg; RTemp1 ← (lsh[RTemp1,1]) + (T); *byte PC (relative to C) of the instruction to be executed *when this frame next runs. :ENDIF; ********************************************* StorPC: Pstore1[LOCAL, RTEMP1, 1]; T ← 100c; *Set MB T ← LOCAL, SALUF ← T; xfMY ← T, return; GetLink: lu ← xfGfiWord , goto[framelink,R even]; *xfGfiWord was set up by LoadC when this *frame became current. codelink: PFETCH1[CODE,RTEMP], return; framelink: PFETCH1[GLOBAL,RTEMP], return; onpage[opPage3]; MesaRefill7: gotop[MesaRefill], Pfetch4[PC,IBUF,4], at[3777]; *EFC0 - EFC16 @EFC0: T ← (1c) , goto[efcr] , OPCODE[300]; @EFC1: T ← (2c) , goto[efcr] , OPCODE[301]; @EFC2: T ← (3c) , goto[efcr] , OPCODE[302]; @EFC3: T ← (4c) , goto[efcr] , OPCODE[303]; @EFC4: T ← (5c) , goto[efcr] , OPCODE[304]; @EFC5: T ← (6c) , goto[efcr] , OPCODE[305]; @EFC6: T ← (7c) , goto[efcr] , OPCODE[306]; @EFC7: T ← (10c) , goto[efcr] , OPCODE[307]; @EFC8: T ← (11c) , goto[efcr] , OPCODE[310]; @EFC9: T ← (12c) , goto[efcr] , OPCODE[311]; @EFC10: T ← (13c) , goto[efcr] , OPCODE[312]; @EFC11: T ← (14c) , goto[efcr] , OPCODE[313]; @EFC12: T ← (15c) , goto[efcr] , OPCODE[314]; @EFC13: T ← (16c) , goto[efcr] , OPCODE[315]; @EFC14: T ← (17c) , goto[efcr] , OPCODE[316]; @EFC15: T ← (20c) , goto[efcr] , OPCODE[317]; @EFCB: T ← CNextData[IBuf] + 1 , call[efcr], OPCODE[320]; efcr: T ← (zero) - T , call[GetLink]; T ← RTEMP, goto[sfcr]; *LFC1 - LFC16 @LFC1: GOTO[lfcr] , T ← xfCount ← ( 4C) , OPCODE[321]; @LFC2: GOTO[lfcr] , T ← xfCount ← ( 6C) , OPCODE[322]; @LFC3: GOTO[lfcr] , T ← xfCount ← (10C) , OPCODE[323]; @LFC4: GOTO[lfcr] , T ← xfCount ← (12C) , OPCODE[324]; @LFC5: GOTO[lfcr] , T ← xfCount ← (14C) , OPCODE[325]; @LFC6: GOTO[lfcr] , T ← xfCount ← (16C) , OPCODE[326]; @LFC7: GOTO[lfcr] , T ← xfCount ← (20C) , OPCODE[327]; @LFC8: GOTO[lfcr] , T ← xfCount ← (22C) , OPCODE[330]; @LFC9: GOTO[lfcr] , T ← xfCount ← (24C) , OPCODE[331]; @LFC10: GOTO[lfcr] , T ← xfCount ← (26C) , OPCODE[332]; @LFC11: GOTO[lfcr] , T ← xfCount ← (30C) , OPCODE[333]; @LFC12: GOTO[lfcr] , T ← xfCount ← (32C) , OPCODE[334]; @LFC13: GOTO[lfcr] , T ← xfCount ← (34C) , OPCODE[335]; @LFC14: GOTO[lfcr] , T ← xfCount ← (36C) , OPCODE[336]; @LFC15: GOTO[lfcr] , T ← xfCount ← (40C) , OPCODE[337]; @LFC16: GOTO[lfcr] , T ← xfCount ← (42C) , OPCODE[340]; @LFCB: T ← NextData[IBuf] , OPCODE[341]; xfcount ← (zero) + (T) + 1; T ← xfcount ← lsh[xfcount,1] , goto[lfcr]; lfcr: PFetch2[CODE,xfTemp] , call[SavePCInFrame]; xfXTSreg ← rsh[xfXTSreg,1], skip[ROdd]; xfMX ← zero, goto[LFCEntry]; *in XferType1 *Cause trap with reason of 400, parameter of xfCount xfXTSreg ← 400c; T ← xfCount, goto[XTrap]; *SFC @SFC: T ← stack&-1 , OPCODE[342]; sfcr: xfMX ← T , call[SavePCInFrame]; loadpage[xfpage1]; goto[Xfer]; *RET @RET: PFetch1[LOCAL,xfMX,2], OPCODE[343]; *fetch return link *The following 4 instructions save L and G in LP and LPhi so that if a control *trap occurs on a RET, the previous state can be obtained. * T ← LOCAL; * bbSrcStartBitLo ← T; *RM 12 * T ← GLOBAL; * bbSrcStartBitHi ← T; *RM 13 xfXTSreg ← rsh[xfXTSreg,1], goto[RetTrap,ROdd]; T ← RZero, LoadPage[xfPage1]; xfMY ← SAluf ← T, gotop[XferNTC]; *MB=0 => free frame RetTrap: T ← 100c; SAluf ← T; *If RET traps, the frame is NOT freed T ← (LOCAL) + (6c); xfXTSreg ← 1000c; XTrap: xfXTPreg ← T, LoadPage[xfPage1]; RTEMP ← sXferTrap, dblgotop[QTrap, QTrapF, MB]; *LLKB @LLKB: T ← NextData[IBuf] , OPCODE[344]; call[GetLink] , T ← (zero) - (T) - 1; T ← RTEMP, goto[PushTP7]; *PORTO @PORTO: call[SavePCInFrame] , OPCODE[345]; T ← stack&-1; task, xftemp ← T; pstore1[MDS,xfMY]; task,T ← (zero) + (T) + 1; pfetch1[MDS,xfMX]; T ← xftemp , loadpage[xfpage1]; goto[Xfer] , xfMY ← T; *PORTI @PORTI: lu ← xfMY , OPCODE[346]; goto[portinz,alu=0] , T ← xfMX; pstore1[MDS,Rzero],call[P7Ret]; T ← (xfMX) + 1; portinz: PSTORE1[MDS,xfMY]; PFetch4[LOCAL,LocalCache0,4], goto[P7Tail]; *in case the port was in the active frame *KFCB @KFCB: T ← NextData[IBuf] , OPCODE[347]; kfcr: RTEMP ← T, call[SavePCInFrame], at[KFCRLoc]; loadpage[xfpage1]; goto[QTrap]; *DESCB @DESCB: T ← xfGfiWord, OPCODE[350]; RTEMP ← T; descbcom: T ← NextData[IBuf]; RTEMP1 ← t; t ← (RTEMP) and not (177c); t ← (lsh[RTEMP1,1]) + (t) + 1; goto[P7Tail],stack&+1 ← t; *DESCBS @DESCBS: T ← (STACK&-1) + (xfgfioffset), OPCODE[351]; pfetch1[MDS,RTEMP], goto[descbcom]; *BLT @BLT: LP ← 0c, OPCODE[352]; LoadPage[xfpage1]; T ← MDShi, gotop[.+1]; OnPage[xfpage1]; BLTcom: LPhi ← T; * fixup: fetch => count + 1; store => source-1, dest-1, count+1 MemStat ← BltFixup,call[BLTx]; * set return address to BLTloop; BLTloop: lu ← stack&-1; goto[BLTdone,alu=0] , T ← stack&+1; *get source, point to count stack ← (stack) - 1; *decrement count pfetch1[LP,RTEMP]; stack&+1; *point to dest T ← stack&-2; *get dest, point to source pstore1[MDS,RTEMP]; stack ← (stack) + 1;*increment source Stack&+2; Stack ← (Stack) + 1, goto[BLTint, IntPending]; *increment dest BLTx: stack&-1, return; *point to count, return to BLTloop BLTdone: stack&-2; BLTdonex: PFetch4[LOCAL,LocalCache0,4]; LoadPage[7]; goto[P7Tail],MemStat ← Normal; BLTint: T ← (RZero) + 1; BLTstop: LoadPage[opPage0]; PFetch4[LOCAL,LocalCache0,4], gotop[NOPint]; *BLTL @BLTL: T ← (Stack&-1) and (377c), OPCODE[353]; LPdesthi ← T, loadpage[xfpage1]; T ← LPdesthi ← (lsh[LPdesthi,10]) + (T) + 1, gotop[.+1]; OnPage[xfpage1]; LPdesthi ← (fixVA[LPdesthi]) OR T; T ← Stack&-2, loadpage[5]; LPdest ← T, callp[StackLP]; RTEMP1 ← (Zero); MemStat ← BltLFixup; * fixup: source+T, dest+T, count+1 Stack&+3, call[BLTLloop]; * point to count BLTLloop: lu ← Stack; * read count, point to source lo T ← RTEMP1, goto[BLTLdone,alu=0]; pfetch1[LP,RTEMP]; Stack ← (Stack) - 1; * decrement count RTEMP1 ← (RTEMP1) + 1; * increment offset pstore1[LPdest,RTEMP]; goto[BLTLint, IntPending]; return; * goes to BLTLloop BLTLdone: stack&-3, goto[BLTdonex]; BLTLint: Stack&-2; call[BLTLbump]; * wait for page fault before updating stack Stack&+2,call[BLTLbump]; T ← (RZero) + 1, goto[BLTstop]; BLTLbump: Stack ← (Stack) + (T) + 1; Stack&+1, FreezeResult; Stack ← (Stack) + 1, UseCOutAsCIn, Return; *BLTC @BLTC: T ← CODE, OPCODE[354]; LP ← T, loadpage[xfpage1]; T ← CODEhi, gotop[BLTcom]; *BLTCL @BLTCL: T ← sUnimplemented, goto[kfcr], Opcode[355]; *ALLOC @ALLOC: MemStat ← 100000c, OPCODE[356]; T ← stack&-1; xfATPreg ← T, goto[Alloc]; *set up in case trap occurs PushTP7: goto[P7Tail], stack&+1 ← t; P7Ret: return; *FREE @FREE: T ← Stack&-1, call[Free], OPCODE[357]; lu ← NextInst[IBUF], call[P7Tailx]; *Increment Wakeup Disable Counter (Disable Interrupts) @IWDC: goto[P7Tail],xfwdc ← (xfwdc) + 1 , OPCODE[360]; *Decrement Wakeup Disable Counter (Enable Interrupts) @DWDC: TASK, T ← (R400) or (52c), OPCODE[361]; PFetch1[MDS,xftemp]; T ← xftemp; NWW ← (NWW) or (T); RTEMP ← pRSImage, goto[DWDCnone, alu=0]; * see if any interrupts T ← (GetRSpec[103]) xor (377c); * read Stkp Stkp ← RTEMP, RTEMP ← T, NoRegILockOK; T ← Stack ← (Stack) or (IntPendingBit); * set IntPending Stkp ← RTEMP, RS232 ← T; DWDCnone: xfwdc ← (xfwdc) - 1, goto[DispMan]; *STOP @STOP: NWW ← (NWW) or (100000c), call[SavePCInFrame], OPCODE[362]; T ← currentstate; pfetch1[MDS,xftemp]; loadpage[xfpage1]; usectask,callp[SaveState]; T ← 1c, call[FFaultStack]; Stack ← (Stack) and not (T), loadpage[0]; * FFAULT ← "crash on page fault" PC ← StopStopPC, gotop[StartNova]; *CATCH CATCH: lu ← NextData[IBUF],call[P7Tail], Opcode[363]; *MISC - extended opcodes accessed by dispatching on alpha @MISC: T ← NextData[IBUF], opcode[364]; LoadPage[xfPage1], RTEMP ← T; gotop[.+1], Dispatch[RTEMP, 14, 4]; OnPage[xfPage1]; Disp[@ASSOC]; * dispatch on second byte * Associate - TOS contains map entry, (TOS-1) contains VP which is to get it. @ASSOC: T ← (Stack&-1) and not (100000C), AT[MiscDisp,0]; Call[MapLP], xBuf ← T; ASSOC1: XMap[LP, xBuf, 0], goto[MiscTail]; * Set Flags @SETF: T ← (Stack&-1) and not (100000C), AT[MiscDisp,1]; Call[MapLP], xBuf ← T; XMap[LP, xBuf, 0]; T ← LSH[xBuf3,10]; * Put flags,,card,blk0 in left byte T ← xBuf1 ← (RHMASK[xBuf1]) OR (T); * blk1,rowaddr in low byte T ← (ZERO) or not (T); * push old flags & page Stack&+1 ← T; * push old flags & page lu ← (ldf[xBuf3,11,3]) -1; * =0 if map entry = VACANT goto[.+2,ALU#0], xBuf ← (xBuf) and (70000C); * isolate new flags, ignore LogSE goto[ASSOC1], xBuf ← T; * Vacant entry, use old flags, oldpage T ← (Stack) and not (170000C); * Get old page number goto[ASSOC1], xBuf ← (xBuf) or (T); * new flags, old page *Subroutine MapLP creates a base register pair from a virtual page number for the Map opcodes. MapLP: T ← LSH[Stack,10]; LP ← T; * Set low Base T ← LHMask[Stack&-1]; goto[xfRET,ALU>=0], LPhi ← T; * Set high byte of high base LPhi ← (LPhi) OR (40000C), goto[xfRET]; * set bit 1 if 0 is set. * Read & Write Ram format: stack=40:43,,addr, (stack-1)=40:43, (stack-2)=0:17, (stack-3)=20:37. @ReadRam: T ← LDF[Stack&-1, 4, 14], AT[MiscDisp,2]; * get address RTEMP ← T; call[CSRead], T ← 1C; * read 20:37 call[CSRead], T ← 0C; * read 0:17 call[CSRead], T ← 3C; * read 40:43 T ← RTEMP; GOTO[MiscTail], Stack ← (LSH[Stack, 14]) or (T); * Subroutine CSRead reads control store for ReadRam opcode. CSRead: APCTASK&APC ← RTEMP; ReadCS; T ← CSData, AT[MiscDisp,22]; *successor of CSOp must be even return, Stack&+1 ← T; MC[VersionID,0]; *Checks compatibility with LRJ'd code. @LoadRamJ: T ← (Stack&-1) xor (1C), AT[MiscDisp,3]; RTemp1←T, LoadPage[opPage1]; * save bits, jump complemented T ← (Stack&-1) and (377C), CallP[StackLPx]; PFetch1[LP,RTemp,0], Call[MiscRet]; LU ← (RTemp) xor (VersionID); T ← sUnimplemented, Goto[MiscTrap,Alu#0]; T ← (SStkP&NStkP) xor (377C); RTemp ← FFaultAdd; StkP ← RTemp, RTemp ← T, NoRegILockOK; Stack ← (Stack) and not (1C); RTemp1 ← T ← (RTemp1) and (1C); * get jump flag (1 => no jump) xfTemp1 ← T, LoadPageExternal[LRJpage]; * allow tasking if not jumping StkP ← RTemp, GotoExternal[LRJStart]; MiscRet: Return; MiscTrap: loadpage[OpPage3]; gotop[kfcr]; OnPage[xfPage1]; * Opcodes for Mesa Input/Output. Stack[0:7]=XXX, Stack[10:13]=task no., * Stack[14:17]=I/O register number. @INPUT: T ← Stack&-1, AT[MiscDisp,5]; goto[MiscTail],Input[Stack]; @OUTPUT: T ← Stack&-1, AT[MiscDisp,6]; goto[MiscTail], Output[Stack]; *SetMaintenancePanel opcode * just put value on stack @SetMP: T ← stack&-1, loadpage[0], at[MiscDisp, 10]; callp[PNIP]; lu ← NextInst[IBUF], call[MiscTailx]; *Read realtime clock (push[RM325]; push[MM430]; @RCLK: loadpage[XMiscPage], at[MiscDisp, 11]; T ← (R400) OR (30c), callp[MXRClk]; Stack&+1 ← T; *Push[RM 325] T ← RTemp, goto[MiscPushT]; *Push [VM 430]; *Read printer @RPRINTER: T ← PRINTER, at[MiscDisp, 12]; Stack&+1 ← T, goto[MiscTail]; *Write printer @WPRINTER: PRINTER ← Stack&-1, goto[MiscTail], AT[MiscDisp,13]; @XferL: lu ← MNBR ← Stack&-1, AT[MiscDisp,14]; *new high base (8 bits) T ← Stack&-1, loadpage[opPage3]; *dest link xfMX ← T, call[SavePCInFrame]; Stack&+1 ← T, loadpage[XMiscPage]; *push L (returned by SavePCInFrame) T ← MNBR, callp[SetMBases]; *Switch Stack&+1 ← T, goto[Xfer]; *Push old base WMDS: loadpage[XMiscPage], AT[MiscDisp,15]; T ← Stack&-1, callp[SetMBases]; MiscTail: lu ← NextInst[IBUF]; MiscTailx: NIRET; OnPage[XMiscPage]; SetMBases: MNBR ← MDShi, MDShi ← T, NoRegILockOK; *Swap old and new bases MDShi ← T ← (lsh[MDShi, 10]) or (T); *make high and low bytes equal Globalhi ← T; LOCALhi ← T, Goto[SetIOBases]; *In Misc.Mc SetTime: loadpage[0], AT[MiscDisp,16]; T ← Stack&-1, callp[SetClrRS232]; skip[TimeOut]; Stack&+1 ← 0c, goto[MiscTail]; Stack&+1 ← 100000c, goto[MiscTail]; OnPage[0]; SetClrRS232: RTemp ← T; RTemp1 ← pRSImage; T ← (GETRSPEC[103]) xor (377c); Stkp ← RTemp1, RTemp1 ← T, NoRegILockOK; T ← RTemp, dblgoto[SetIt,ClearIt,R<0]; SetIt: Stack ← T ← (Stack) or (T), goto[SCRet]; ClearIt: Stack ← T ← (Stack) and not (T), goto[SCRet]; SCRet: Stkp ← RTemp1, RS232 ← T, return; SetDefaultPartition: loadpage[XMiscPage], AT[MiscDisp,17]; T ← Stack&-1, callp[MXPar]; MiscPushT: lu ← NextInst[IBUF]; Stack&+1 ← T, NIRET; *BitBLT BitBLT: T ← Stack0, LoadPage[bbPage], Opcode[365]; AC2 ← T, GotoP[MesaBitBLT]; *STARTIO @STARTIO: T ← stack&-1, LoadPage[EEPage], Opcode[366]; goto[EESIO], RTEMP1 ← 1c; *RTEMP1 is the return indicator (Mesa/Nova) *JRAM @JRAM: APCTask&APC ← Stack&-1, Goto[P7Ret], Opcode[367]; *Nova-flavored JMPRAM *DST @DST: T ← NextData[IBuf] , Opcode[370]; t ← (LOCAL) + (t) ,loadpage[xfpage1]; usectask,call[SaveState] , xftemp ← t; T ← (xftemp) + (12c), TASK; Pstore1[MDS, xfMY]; RefillLocalCache: PFetch4[LOCAL,LocalCache0,4], goto[P7Tail]; *LST @LST: T ← NextData[IBuf], Opcode[371]; call[SavePCInFrame],xfTemp ← T;* NextData must be before SavePC call GOTO[LSTFgo], T ← (xfTemp); *LSTF @LSTF: T ← RZero, Opcode[372]; T ← NextData[IBUF], Saluf ← T; *MB = 0 => free frame LSTFgo: T ← (LOCAL) + (T), LoadPage[xfpage1]; GOTOp[LoadState], xfTemp ← T; * xfTemp is pointer to saved state. *WR @WR: T ← NextData[IBuf] , Opcode[374]; xftemp ← T , loadpage[xfpage1]; dispatch[xftemp,16,2]; onpage[xfpage1]; disp[xfwr] , T ← stack&-1; xfwr: goto[MiscTail] , xfwdc ← T , at[xfwrtab,1]; goto[MiscTail] , xfXTSreg ← T , at[xfwrtab,2]; :IF[AltoMode]; :ELSE; ********************************************** MDShi ← T , at[xfwrtab,3]; T ← MDShi ← (LSH[MDShi,10]) + (T); LOCALhi ← T; GLOBALhi ← T, goto[MiscTail]; :ENDIF; ********************************************* *RR @RR: T ← NextData[IBuf] , Opcode[375]; xftemp ← T , loadpage[xfpage1]; dispatch[xftemp,15,3]; onpage[xfpage1]; LoadPage[4], disp[xfrr]; xfrr: gotop[PushT], T ← xfwdc , at[xfrrtab,1]; gotop[PushT], T ← xfXTSreg , at[xfrrtab,2]; gotop[PushT], T ← xfXTPreg , at[xfrrtab,3]; gotop[PushT], T ← xfATPreg , at[xfrrtab,4]; gotop[PushT], T ← xfOTPreg , at[xfrrtab,5]; gotop[PushT], T ← MDShi , at[xfrrtab,6]; *BRK @BRK: t ← zero , goto[kfcr] , Opcode[376]; *Cause pagefault trap - done only by fault, is not supposed to be encountered ininstruction stream. TrapFlap: T ← (PCFReg)-1, Opcode[377]; * back up PCF by one RTEMP ← T, LoadPage[FaultPage1]; PCF ← RTEMP, gotop[StartMemTrap]; *Unused opcodes on page 7 T ← sUnimplemented, goto[kfcr], Opcode[373]; :END[MesaX];