: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];