:IF[AltoMode]; TITLE[MesaLS--Alto.Mode]; :ELSE; TITLE[MesaLS--Pilot.Mode]; :ENDIF; *Common tail and refill for instructions on page 4 ONPAGE[4]; MesaRefill4: gotop[MesaRefill], Pfetch4[PC,IBUF,4], at[2377]; *NOP *In DMesa, we should only get here if IntPending is set by an I/O controller. *AMesa uses NOP for padding. @NOP: T ← (RZero) + 1, goto[NOPint,IntPending], opcode[0]; P4Tail: lu ← NextInst[IBUF]; P4Tailx: NIRET; *NOPint is entered from @NOP above and from BLTstop (in Mesax). MIPend *backs up the PC by IntType (which is always =1 here, but is 0 if MIPend is *entered from IdleLoop in MesaP). Then it clears IntPending and checks *(NWW#0 & xfWDC=0). If this quantity is true, MIPend starts the interrupt; *otherwise it returns. The return will cause a BLT to be restarted. The *return sends control to the byte code that was elided when the NOP was forced. NOPint: IntType ← T, loadpage[prPage]; * IntType ← (PC backup if stopping) T ← (GetRSpec[103]) xor (377c), callp[MIPend]; * T ← Stkp xor 377 lu ← NextInst[IBUF], call[P4Tailx]; * Monitor instructions are in MesaP.mc P4Ret: RETURN; *Load Local n, n=0-7 LL0: T ← LocalCache0, goto[PushT], opcode[10] ; LL1: T ← LocalCache1, goto[PushT], opcode[11] ; LL2: T ← LocalCache2, goto[PushT], opcode[12] ; LL3: T ← LocalCache3, goto[PushT], opcode[13] ; *LL0: Pfetch1[LOCAL,Stack,4], goto[P4Tail], opcode[10] ; *LL1: Pfetch1[LOCAL,Stack,5], goto[P4Tail], opcode[11] ; *LL2: Pfetch1[LOCAL,Stack,6], goto[P4Tail], opcode[12] ; *LL3: Pfetch1[LOCAL,Stack,7], goto[P4Tail], opcode[13] ; LL4: Pfetch1[LOCAL,Stack,10], goto[P4Tail], opcode[14] ; LL5: Pfetch1[LOCAL,Stack,11], goto[P4Tail], opcode[15] ; LL6: Pfetch1[LOCAL,Stack,12], goto[P4Tail], opcode[16] ; LL7: Pfetch1[LOCAL,Stack,13], goto[P4Tail], opcode[17] ; *Load Local Byte LLB: T ← NextData[IBUF], opcode[20]; Pfetch1[LOCAL,Stack], goto[P4Tail]; *Load Local Double Byte LLDB: T ← NextData[IBUF], opcode[21]; LLDB1: Pfetch2[LOCAL,Stack], call[FQT]; *If FQT returns, quadOVF has occurred. Fetch the first word into RTEMP CALL[IncT1], Pfetch1[LOCAL,RTEMP]; Pfetch1[LOCAL,Stack], goto[DoubleReadTail]; *By this time, we know that the first fetch has not faulted. If the second one faults, *the fourth instruction after the Pfetch will be aborted. If we wait to update the first *word, we don't have to tell the fault handler anything about the state of the memory. DoubleReadTail: nop; Stack&-1; *Adjust the stackpointer to point to the first word of the pair DoubleReadTailx: T ← RTEMP; Stack ← T; *deposit the first word lu ← NextInst[IBUF]; Stack&+1, NIRET; *final stkp adjust IncT1: T ← (Zero) + (T) + 1, return; *increment T by 1 FQT: goto[.+2, QuadOVF]; lu ← NextInst[IBUF], call[P4Tailx]; Stack&-1, return; *adjust the stackpointer modified by the failed fetch to point *one below the SECOND word to be fetched. *Store Local n, n=0-7 SL0: T ← stack&-1, Opcode[22]; SL0x: LocalCache0 ← T, goto[StoreLocalCache]; SL1: T ← stack&-1, Opcode[23]; SL1x: LocalCache1 ← T, goto[StoreLocalCache]; SL2: T ← stack&-1, Opcode[24]; SL2x: LocalCache2 ← T, goto[StoreLocalCache]; SL3: T ← stack&-1, Opcode[25]; SL3x: LocalCache3 ← T, goto[StoreLocalCache]; *SL0: PStore1[LOCAL,Stack,4], goto[P4Tail], Opcode[22]; *SL1: PStore1[LOCAL,Stack,5], goto[P4Tail], Opcode[23]; *SL2: PStore1[LOCAL,Stack,6], goto[P4Tail], Opcode[24]; *SL3: PStore1[LOCAL,Stack,7], goto[P4Tail], Opcode[25]; SL4: PStore1[LOCAL,Stack,10], goto[P4Tail], Opcode[26]; SL5: PStore1[LOCAL,Stack,11], goto[P4Tail], Opcode[27]; SL6: PStore1[LOCAL,Stack,12], goto[P4Tail], Opcode[30]; SL7: PStore1[LOCAL,Stack,13], goto[P4Tail], Opcode[31]; StoreLocalCache: lu ← NextInst[IBUF]; PStore4[LOCAL,LocalCache0,4], NIRET ; *Store Local Byte SLB: T ← NextData[IBUF], opcode[32]; PStore1[LOCAL,Stack], goto[P4Tail]; *Put Local n, n=0-3. Equivalent to SLn,Push % PL0: PStore1[LOCAL,Stack,4], goto[QPutTail], Opcode[33]; PL1: PStore1[LOCAL,Stack,5], goto[QPutTail], Opcode[34]; PL2: PStore1[LOCAL,Stack,6], goto[QPutTail], Opcode[35]; PL3: PStore1[LOCAL,Stack,7], goto[QPutTail], Opcode[36]; QPutTail: Stack&+1, goto[P4Tail]; % PL0: T ← stack&-1,opcode[33]; LocalCache0 ← T, goto[PutTail]; PL1: T ← stack&-1,opcode[34]; LocalCache1 ← T, goto[PutTail]; PL2: T ← stack&-1,opcode[35]; LocalCache2 ← T, goto[PutTail]; PL3: T ← stack&-1,opcode[36]; LocalCache3 ← T, goto[PutTail]; PutTail: Stack&+1; PStore4[LOCAL,LocalCache0,4], goto[P4Tail]; *Load Global n, n=0-7 LG0: Pfetch1[GLOBAL,Stack,3], goto[P4Tail], opcode[37] ; LG1: Pfetch1[GLOBAL,Stack,4], goto[P4Tail], opcode[40] ; LG2: Pfetch1[GLOBAL,Stack,5], goto[P4Tail], opcode[41] ; LG3: Pfetch1[GLOBAL,Stack,6], goto[P4Tail], opcode[42] ; LG4: Pfetch1[GLOBAL,Stack,7], goto[P4Tail], opcode[43] ; LG5: Pfetch1[GLOBAL,Stack,10], goto[P4Tail], opcode[44] ; LG6: Pfetch1[GLOBAL,Stack,11], goto[P4Tail], opcode[45] ; LG7: Pfetch1[GLOBAL,Stack,12], goto[P4Tail], opcode[46] ; *Load Global Byte LGB: T ← NextData[IBUF], opcode[47]; Pfetch1[GLOBAL,Stack], goto[P4Tail]; *Load Global Double Byte LGDB: T ← NextData[IBUF], opcode[50] ; LGDB1: Pfetch2[GLOBAL,Stack], call[FQT]; *If FQT returns, quadOVF occurred. See LLDB. Call[IncT1], Pfetch1[GLOBAL,RTEMP]; Pfetch1[GLOBAL,Stack], goto[DoubleReadTail]; *Store Global n, n=0-7 SG0: PStore1[GLOBAL,Stack,3], goto[P4Tail], Opcode[51]; SG1: PStore1[GLOBAL,Stack,4], goto[P4Tail], Opcode[52]; SG2: PStore1[GLOBAL,Stack,5], goto[P4Tail], Opcode[53]; SG3: PStore1[GLOBAL,Stack,6], goto[P4Tail], Opcode[54]; *Store Global Byte SGB: T ← NextData[IBUF], opcode[55]; PStore1[GLOBAL,Stack], goto[P4Tail]; *Load Immediate n, n=0-6 LI0: T ← 0c, goto[PushT], Opcode[56]; LI1: T ← 1c, goto[PushT], Opcode[57]; LI2: T ← 2c, goto[PushT], Opcode[60]; LI3: T ← 3c, goto[PushT], Opcode[61]; LI4: T ← 4c, goto[PushT], Opcode[62]; LI5: T ← 5c, goto[PushT], Opcode[63]; LI6: T ← 6c, goto[PushT], Opcode[64]; *Load Immediate Negative 1. LIN1: T ← (Zero)-1, goto[PushT], Opcode[65]; *Load Immediate Negative Infinity LINI: T ← 100000c, goto[PushT], Opcode[66]; *Load Immediate Byte LIB: T ← NextData[IBUF], Opcode[67]; PushT: lu ← NextInst[IBUF]; Stack&+1 ← T, NIRET; *Load Immediate Word :IF[AltoMode]; **************************************** LIW: lu ← GetRSpec[127], skip[R even], Opcode[70]; lu ← NextData[IBuf]; T ← NextData[IBUF]; lu ← CycleControl ← NextData[IBUF]; :ELSE; ************************************************ LIW: lu ← CycleControl ← NextData[IBUF], Opcode[70]; T ← NextData[IBUF]; :ENDIF; *********************************************** T ← (lhmask[GetRSpec[127]]) OR T, goto[PushT]; *Load Immediate Negative Byte LINB: T ← 177400c, opcode[71]; T ← NextData[IBuf] OR T, call[PushT]; *Local Address Byte - since MDS is 64K aligned, the low half of the base register is L LADRB: T ← LOCAL, Opcode[72]; LADRBx: T ← (NextData[IBUF]) + (T), call[PushT]; *Global Address Byte GADRB: T ← GLOBAL, goto[LADRBx], Opcode[73]; *unused opcodes on page 4 T ← sUnimplemented, goto[doTrapP4], opcode[74]; T ← sUnimplemented, goto[doTrapP4], opcode[75]; T ← sUnimplemented, goto[doTrapP4], opcode[76]; T ← sUnimplemented, goto[doTrapP4], opcode[77]; doTrapP4: LoadPage[opPage3]; gotop[kfcr]; *Common tail and refill for instructions on page 5 OnPage[5]; MesaRefill5: gotop[MesaRefill], Pfetch4[PC,IBUF,4], at[2777]; P5Tail: lu ← NextInst[IBUF]; P5Tailx: NIRET; FetchMDSToStack: Pfetch1[MDS,Stack],RETURN; FetchMDSToRTEMPx: RTEMP1 ← T; *save pointer FetchMDSToRTEMP: Pfetch1[MDS,RTEMP]; P5Ret: RETURN; *allow time for T to be written FetchCODEToStack: Pfetch1[CODE,Stack], return; DecS1IncT1: Stack&-1, goto[IncT1p5]; FetchMNBRLPToRTEMP: T ← MNBR; FetchLPToRTEMP: Pfetch1[LP,RTEMP], goto[P5Ret]; * allow time to write T FetchMNBRLPToStack: T ← MNBR; FetchLPToStack: Pfetch1[LP,Stack], goto[P5Ret]; * allow time to write T TtoRTEMP: RTEMP ← T, return; AddTtoStack: T ← (Stack&-1) + (T), return; *Read n, n=0-4 R0: T ← (Stack&-1) + (0c), goto[ReadTail], Opcode[100]; R1: T ← (Stack&-1) + (1c), goto[ReadTail], Opcode[101]; R2: T ← (Stack&-1) + (2c), goto[ReadTail], Opcode[102]; R3: T ← (Stack&-1) + (3c), goto[ReadTail], Opcode[103]; R4: T ← (Stack&-1) + (4c), goto[ReadTail], Opcode[104]; *Read Byte @RB: T ← CNextData[IBUF], call[AddTtoStack], Opcode[105]; ReadTail: Pfetch1[MDS,Stack],goto[P5Tail]; *Write n, n=0-2 W0: T ← (Stack&-1) + (0c), goto[WriteTail], Opcode[106]; W1: T ← (Stack&-1) + (1c), goto[WriteTail], Opcode[107]; W2: T ← (Stack&-1) + (2c), goto[WriteTail], Opcode[110]; *Write Byte WB: T ← CNextData[IBUF], call[AddTtoStack], Opcode[111]; WriteTail: PStore1[MDS,Stack], goto[SQT]; *PStore1's cant cause quadOVF, so this checks the local cache *Read Field :IF[AltoMode]; **************************************** AlignField: usectask, gotop[AF6]; onpage[6]; AF6: T ← apc&apctask; RTEMP ← T; lu ← GetRSpec[127], skip[R even]; lu ← NextData[IBuf]; lu ← CycleControl ← NextData[IBUF]; *get field descriptor T ← NextData[IBUF]; *get offset apc&apctask ← RTEMP; return; onpage[5] @RF: loadpage[6], call[AlignField], Opcode[112]; :ELSE; ************************************************ @RF: T ← NextData[IBUF], Opcode[112]; *get offset lu ← CycleControl ← NextData[IBUF]; *get field descriptor :ENDIF; *********************************************** RFy: T ← (Stack&-1) + (T), call[FetchMDSToStack]; *add pointer, fetch lu ← NextInst[IBUF]; RFx: Stack ← RF[Stack], NIRET; *do the work on the stack *Write Field :IF[AltoMode]; **************************************** WF: loadpage[6], call[AlignField], Opcode[113]; :ELSE; ************************************************ WF: T ← NextData[IBUF], Opcode[113]; *get offset lu ← CycleControl ← NextData[IBUF]; *get field descriptor :ENDIF; *********************************************** Wfz: T ← (Stack&-1) + (T), call[FetchMDSToRTEMPx]; *add pointer, fetch T ← WFA[Stack&-1]; *field to be inserted WFy: RTEMP ← (WFB[RTEMP]) or (T); *do insert WFx: T ← RTEMP1, goto[WS0x]; *Read Double Byte RDB: T ← NextData[IBUF], Opcode[114]; T ← (Stack&-1) + (T), LoadPage[4], goto[DoubleRead]; *Read Double 0 RD0: T ← Stack&-1, LoadPage[4], Opcode[115]; DoubleRead: Pfetch2[MDS,Stack], callp[FQT]; *If FQT returns, quadOVF has occurred. See LLDB. Call[IncT1p5], Pfetch1[MDS,RTEMP]; Pfetch1[MDS,Stack]; DoubleReadx: LoadPage[4]; Stack&-1, gotop[DoubleReadTailx]; IncS2T1: Stack&+2; *Increment stkp by 2, and... IncT1p5: T ← (Zero) + (T) + 1, RETURN; *increment T by 1 *Write Double Byte WDB: T ← CNextData[IBUF], call[AddTtoStack], opcode[116]; DoubleWrite: PStore2[MDS,Stack], call[SQT]; *If SQT returns, do two single stores PStore1[MDS,Stack], call[IncS2T1]; PStore1[MDS,Stack], goto[WSDBx]; *Write Double 0 WD0: T ← Stack&-1, goto[DoubleWrite], opcode[117]; *Store quadword test SQT: RTemp1 ← T, goto[.+3, quadOVF]; *Bypass kludge LoadPage[4]; CLCR0: T ← (rsh[LOCAL,2]) + 1, , gotop[CLCR1]; *Check for local cache refill required Stack&+1, return; *set stkp to point to the first word to be stored *Read String RSTR: T ← CNextData[IBUF], call[RWSTRx], opcode[120]; *get alpha lu ← RTEMP1, dblgoto[RSTRLeft, RSTRRight, Reven], LoadPage[4]; RSTRLeft: T ← rsh[RTEMP,10], gotop[PushT]; RSTRRight: T ← rhmask[RTEMP], gotop[PushT]; *Write String WSTR: T ← CNextData[IBUF], call[RWSTRx], opcode[121]; RTEMP1 ← T, dblgoto[WSTRLeft, WSTRRight, Reven]; *test low bit of RTEMP1, save pointer WSTRLeft: T ← lsh[Stack&-1, 10]; RTEMP ← (rhmask[RTEMP]) or (T), goto[WFx]; WSTRRight: T ← rhmask[Stack&-1]; RTEMP ← (lhmask[RTEMP]) or (T), goto[WFx]; RWSTRx: T ← (Stack&-1) + (T); *string index RTEMP1 ← T; T ← (Stack&-1); *pointer T ← (rsh[RTEMP1,1]) + (T), goto[FetchMDSToRTEMP]; *Read Indexed by Local Pair RXLP: T ← NextData[IBUF], opcode[122]; RTEMP1 ← T, call[LPPointer]; T ← (Stack&-1) + (T), goto[RILPx]; *Write Indexed by Local Pair WXLP: T ← NextData[IBUF], opcode[123]; RTEMP1 ← T, call[LPPointer]; T ← (Stack&-1) + (T), goto[WILPx]; *Read Indirect Local Pair RILP: T ← NextData[IBUF], opcode[124]; RTEMP1 ← T, call[LPPointer]; RILPx: T ← (RTEMP) + (T), goto[ReadTail]; *Read Indirect Global Pair RIGP: T ← NextData[IBUF], opcode[125]; RTEMP1 ← T, call[GPPointer]; RIGPx: T ← (RTEMP) + (T), goto[ReadTail]; *Write Indirect Local Pair WILP: T ← NextData[IBUF], opcode[126]; RTEMP1 ← T, call[LPPointer]; WILPx: T ← (RTEMP) + (T), goto[WriteTail]; *Read Indirect Local 0 RIL0: T ← LocalCache0, goto[ReadTail], opcode[127]; *RIL0: PFetch1[LOCAL,RTEMP,4], opcode[127]; T ← RTEMP, goto[ReadTail]; LPPointer: T ← 4c; *offset of local 0 T ← (ldf[RTEMP1, 10, 4]) + (T); Pfetch1[LOCAL,RTEMP]; LPPointerx: T ← ldf[RTEMP1, 14, 4], return; GPPointer: T ← 3c; *offset of global 0 T ← (ldf[RTEMP1, 10, 4]) + (T); Pfetch1[GLOBAL,RTEMP], goto[LPPointerx]; *Write Swapped 0 WS0: T ← (Stack&-1), call[WSPointer], opcode[130]; *T ← data WS0x: RTEMP1 ← T, LoadPage[4]; PStore1[MDS, RTEMP], gotop[CheckLocalCacheRefill]; OnPage[4]; CheckLocalCacheRefill: T ← (rsh[LOCAL,2]) + 1; CLCR1: lu ← (rsh[RTEMP1,2]) xor (T); skip[ALU#0]; PFetch4[LOCAL,LocalCache0,4], goto[P4Tail]; lu ← NextInst[IBUF], call[P4Tailx]; *Write Swapped Byte WSB: T ← Stack&-1, call[WSPointer], opcode[131]; WSBx: T ← (NextData[IBUF]) + (T), call[WS0x]; WSPointer: RTEMP ← T; T ← Stack&-1, return; *T ← pointer *Write Swapped Field :IF[AltoMode]; **************************************** WSF: Stack&-1, loadpage[6], call[AlignField], Opcode[132]; :ELSE; ************************************************ WSF: Stack&-1, opcode[132]; T ← NextData[IBUF]; lu ← CycleControl ← NextData[IBUF]; :ENDIF; *********************************************** T ← (Stack&+1) + (T), call[FetchMDSToRTEMPx]; *T ← pointer T ← WFA[Stack&-2], goto[WFy]; *Write Swapped Double Byte WSDB: T ← NextData[IBUF], opcode[133]; Stack&-2; T ← (Stack&+2) + (T); *T ← pointer + alpha Pstore2[MDS,Stack]; RTemp1 ← T, goto[.+2, quadOVF]; WSDBx: stack&-1, LoadPage[4], goto[CLCR0]; *back up stkp over pointer *Do two single stores Stack&+1; Pstore1[MDS, stack], call[IncS2T1]; Pstore1[MDS, stack]; Stack&-2, LoadPage[4], goto[CLCR0]; *back up stkp over lsb(data) and pointer *Read Field Code :IF[AltoMode]; **************************************** RFC: loadpage[6], call[AlignField], Opcode[134]; :ELSE; ************************************************ RFC: T ← NextData[IBUF], Opcode[134]; *get offset lu ← CycleControl ← NextData[IBUF]; *get field descriptor :ENDIF; *********************************************** T ← (Stack&-1) + (T), call[FetchCODEToStack]; lu ← NextInst[IBUF], call[RFx]; *Read Field Stack RFS: T ← (Stack&-1), call[StackFD], opcode[135]; :IF[AltoMode]; **************************************** lu ← GetRSpec[127], skip[Reven]; lu ← NextData[IBuf]; :ENDIF; *********************************************** CycleControl ← RTEMP, goto[RFy]; *Write Field Stack WFS: T ← Stack&-1, call[StackFD], opcode[136]; :IF[AltoMode]; **************************************** lu ← GetRSpec[127], skip[Reven]; lu ← NextData[IBuf]; :ENDIF; *********************************************** CycleControl ← RTEMP, goto[WFz]; *Displacement is in left byte, FD is in right byte StackFD: RTEMP ← T; T ← rsh[RTEMP, 10], return; *get displacement *Read Byte Long RBL: T ← (Stack&-1) and (377c), call[StackLPx], opcode[137]; T ← NextData[IBUF], call[RILPLx]; *displacement from pointer *Write Byte Long WBL: T ← (Stack&-1) and (377c), call[StackLPx], opcode[140]; T ← NextData[IBUF], call[WILPLx]; *displacement *Read Double Byte Long RDBL: T ← (Stack&-1) and (377c), call[StackLPx], opcode[141]; T ← NextData[IBUF]; DoubleReadLong: Pfetch2[LP,Stack]; goto[.+2,quadOVF]; lu ← NextInst[IBUF], call[P5Tailx]; *Do two single fetches, the first to RTEMP Pfetch1[LP,RTEMP], call[DecS1IncT1]; Pfetch1[LP,Stack], goto[DoubleReadx]; *Write Double Byte Long WDBL: T ← (Stack&-1) and (377c), call[StackLPx], opcode[142]; T ← NextData[IBUF]; DoubleWriteLong: Pstore2[LP, Stack], call[SQT]; *Do two single stores Pstore1[LP,Stack], call[IncS2T1]; *straigntforward increment of stkp aborts. We can speed this up by being more devious. Pstore1[LP,Stack], goto[WSDBx]; StackLP: T ← (Stack&-1) and (377c); StackLPx: LPhi ← T; T ← LPhi ← (lsh[LPhi,10]) + (T) + 1; LPhi ← (fixVA[LPhi]) or (T); T ← Stack&-1; LP ← T, return; *Read Indexed by Local Pair Long RXLPL: T ← NextData[IBUF], opcode[143]; RTEMP ← T, call[LocalLP]; T ← (Stack&-1) + (T), goto[RILPLx]; *Write Indexed by Local Pair Long WXLPL: T ← NextData[IBUF], opcode[144]; RTEMP ← T, call[LocalLP]; T ← (Stack&-1) + (T), goto[WILPLx]; *Read Indexed by Global Pair Long RXGPL: T ← NextData[IBUF], opcode[145]; RTEMP ← T, call[GlobalLP]; T ← (Stack&-1) + (T), goto[RILPLx]; *Write Indexed by Global Pair Long WXGPL: T ← NextData[IBUF], opcode[146]; RTEMP ← T, call[GlobalLP]; T ← (Stack&-1) + (T), goto[WILPLx]; *Read Indirect Local Pair Long RILPL: T ← NextData[IBUF], opcode[147]; RTEMP ← T, call[LocalLP]; RILPLx: Pfetch1[LP,Stack], goto[P5Tail]; *Write Indirect Local Pair Long WILPL: T ← NextData[IBUF], opcode[150]; RTEMP ← T, call[LocalLP]; WILPLx: Pstore1[LP,Stack], goto[P5Tail]; *Read Indirect Global Pair Long RIGPL: T ← NextData[IBUF], opcode[151]; RTEMP ← T, call[GlobalLP]; Pfetch1[LP,Stack], goto[P5Tail]; *Write Indirect Global Pair Long WIGPL: T ← NextData[IBUF], opcode[152]; RTEMP ← T, call[GlobalLP]; Pstore1[LP,Stack], goto[P5Tail]; *Format a long pointer from a local selector,,offset pair LocalLP: T ← RTEMP1 ← 5c; *rtemp1 is a flag for decLPTR (below). T ← (ldf[RTEMP, 10, 4]) + (T); *note - high half of pointer is fetched first Pfetch1[LOCAL,LPhi], goto[decLPTR]; LocalLPy: Pfetch1[LOCAL,LP]; *low half LocalLPx: T ← (LPhi) and (377c); T ← LPhi ← (lsh[LPhi,10]) +(T) + 1; LPhi ← (fixVA[LPhi]) or (T); *if we decide to trap on references to page 377, do it here T ← ldf[RTEMP, 14, 4], return; *Format a long pointer from a global selector,,offset pair GlobalLP: T ← RTEMP1 ← 4c; T ← (ldf[RTEMP, 10, 4]) + (T); *note - high half of pointer is fetched first Pfetch1[GLOBAL,LPhi], goto[decLPTR]; GlobalLPy: Pfetch1[GLOBAL,LP], goto[LocalLPx]; *low half decLPTR: lu ← ldf[RTEMP1,17,1]; *where to return (T is written here) T ← (AllOnes) + (T), dblgoto[LocalLPy,GlobalLPy,ALU#0]; *Read String Long RSTRL: T ← CNextData[IBUF], call[RWSTRLx], opcode[153]; T ← rsh[RTEMP1, 1], call[FetchLPToRTEMP]; lu ← RTEMP1, dblgoto[RSTRLeft, RSTRRight, Reven], LoadPage[4]; RWSTRLX: T ← (Stack&-1) + (T); RTEMP1 ← T, goto[StackLP]; *RTEMP1 ← String index *Write String Long WSTRL: T ← CNextData[IBUF], call[RWSTRLx], opcode[154]; T ← rsh[RTEMP1,1], call[FetchLPToRTEMP]; RTEMP1 ← T, dblgoto[WSTRLLeft, WSTRLRight, Reven]; *test low bit of RTEMP1 WSTRLLeft: T ← lsh[Stack&-1, 10]; RTEMP ← (rhmask[RTEMP]) or (T), goto[WFLx]; WSTRLRight: T ← rhmask[Stack&-1]; RTEMP ← (lhmask[RTEMP]) or (T), goto[WFLx]; *Read Field Long :IF[AltoMode]; **************************************** RFL: loadpage[6], call[AlignField], Opcode[155]; RTEMP ← T, call[StackLP]; T ← RTEMP, call[FetchLPToStack]; :ELSE; ************************************************ RFL: MNBR ← CNextData[IBUF], call[StackLP], opcode[155]; lu ← CycleControl ← CNextData[IBUF], call[FetchMNBRLPToStack]; :ENDIF; *********************************************** RFLx: lu ← NextInst[IBUF], call[RFx]; *Write Field Long :IF[AltoMode]; **************************************** WFL: loadpage[6], call[AlignField], Opcode[156]; RTEMP ← T, call[StackLP]; T ← RTEMP, call[FetchLPToRTEMP]; :ELSE; ************************************************ WFL: MNBR ← CNextData[IBUF], call[StackLP], opcode[156]; lu ← CycleControl ← CNextData[IBUF], call[FetchMNBRLPToRTEMP]; :ENDIF; *********************************************** RTEMP1 ← T; WFLy: T ← WFA[Stack&-1]; RTEMP ← (WFB[RTEMP]) or (T); WFLx: T ← RTEMP1; Pstore1[LP,RTEMP], goto[P5Tail]; *Read Field Stack Long RFSL: T ← Stack&-1, call[TtoRTEMP], opcode[157]; CycleControl ← RTEMP, call[StackLP]; T ← rsh[RTEMP,10]; :IF[AltoMode]; **************************************** lu ← GetRSpec[127], skip[R even]; lu ← NextData[IBuf]; :ENDIF; *********************************************** Pfetch1[LP,Stack], goto[RFLx]; *Write Field Stack Long WFSL: T ← Stack&-1, call[TtoRTEMP], opcode[160]; CycleControl ← RTEMP, call[StackLP]; T ← rsh[RTEMP,10], call[FetchLPToRTEMP]; :IF[AltoMode]; **************************************** lu ← GetRSpec[127], skip[R even]; lu ← NextData[IBuf]; :ENDIF; *********************************************** RTEMP1 ← T, goto[WFLy]; *Lengthen Pointer @LP: T ← Stack&-1, opcode[161]; *pop to interlock PFetch2's Stack&+1, skip[ALU=0]; *test for NIL T ← rsh[MDShi,10]; *push MDShi if non-NIL PushTP5: lu ← NextInst[IBuf]; Stack&+1 ← T, NIRET; *Store Local Double Byte SLDB: T ← NextData[IBUF], opcode[162]; Pstore2[LOCAL,Stack], call[SQT]; Pstore1[LOCAL,stack], call[IncS2T1]; Pstore1[LOCAL,Stack], goto[WSDBx]; *Store Global Double Byte SGDB: T ← NextData[IBUF], opcode[163]; Pstore2[GLOBAL,Stack], call[SQT]; Pstore1[GLOBAL,stack], call[IncS2T1]; Pstore1[GLOBAL,Stack], goto[WSDBx]; *Push PUSH: Stack&+1, goto[P5Tail], opcode[164]; *Pop POP: Stack&-1, goto[P5Tail], opcode[165]; *Exchange EXCH: T ← Stack&-1, Opcode[166]; MNBR ← Stack, Stack ← T, NoRegILockOK; T ← MNBR, goto[PushTP5]; *Link Byte - equivalent to PUSHX; LIB; SUB; SL0;, except that nothing is above stkp LINKB: T ← NextData[IBUF], opcode[167]; xfMX ← T ← (xfMX) - (T), LoadPage[4]; * PStore1[LOCAL,xfMX,4], goto[P4Tail]; LocalCache0 ← T, goto[StoreLocalCache]; *Duplicate DUP: T ← Stack&-1, opcode[170]; Stack&+2 ← T, goto[P5Tail]; :IF[AltoMode]; **************************************** NILCK: goto[P5Tail], Opcode[171]; NILCKL: goto[P5Tail], opcode[172]; BNDCK: Stack&-1, goto[P5Tail], opcode[173]; :ELSE; ************************************************ *NIL Check NILCK: T ← Stack&-1, Opcode[171]; NILCKx: Stack&+1, dblgoto[doTrapP5, P5Tail, ALU=0], T ← sPointerFault; *NIL Check Long NILCKL: T ← Stack&-1, opcode[172]; lu ← (Stack) or (T), goto[NILCKx]; *Bounds Check - Trap if (TOS-1) >= TOS (unsigned) BNDCK: Stack&-1, opcode[173]; T ← Stack&+1; lu ← (Stack&-1) - (T) - 1; dblgoto[doTrapP5, P5Tail, NoCarry], T ← sBoundsFault; :ENDIF; *********************************************** *Unimplemented opcodes on page 5 T ← sUnimplemented, goto[doTrapP5], opcode[174]; T ← sUnimplemented, goto[doTrapP5], opcode[175]; T ← sUnimplemented, goto[doTrapP5], opcode[176]; T ← sUnimplemented, goto[doTrapP5], opcode[177]; doTrapP5: LoadPage[opPage3]; gotop[kfcr]; :END[MesaLS];