*----------------------------------------------------------- Title[DMesaLS.mc...April 4, 1982 11:51 AM...Taft]; * Loads and Stores, plus various other stack operations *----------------------------------------------------------- % CONTENTS, by order of occurence Load/Store (16 bits) LLn, LGn Load Local n, Load Global n SLn, SGn Store Local n, Store Global n PLn Put Local n LIn Load Immediate n LIN1 Load Immediate -1 LINI Load Immediate Negative Infinity LIW Load Immediate Word LCO Load Code Offset LINB Load Immediate Negative Byte Load/Store (32 bits) LLDB, LGDB Load Local Double Byte, Load Global Double Byte SLDB, SGDB Store Local Double Byte, Store Global Double Byte Stack maintenance PUSH increment StkP POP decrement StkP DUP duplicate TOS EXCH Exchange top two stack items NILCK, NILCKL Nil check BNDCK Bounds check Machine Register Access RR Read register WR Write register % TopLevel; * Load/Store (16 bits) *-------------------------------------------------------------------- IFUR[LL0, 1, L, N[4]]; * Load Local n: Push[FetchMDS[L+n]^]; IFUR[LL1, 1, L, N[5]]; IFUR[LL2, 1, L, N[6]]; IFUR[LL3, 1, L, N[7]]; IFUR[LL4, 1, L, N[10]]; IFUR[LL5, 1, L, N[11]]; IFUR[LL6, 1, L, N[12]]; IFUR[LL7, 1, L, N[13]]; IFUR[LLB, 2, L]; * Load Local Byte: Push[FetchMDS[L+alpha]^]; IFUR[LG0, 1, G, N[3]]; * Load Global n: Push[FetchMDS[G+n]^]; IFUR[LG1, 1, G, N[4]]; IFUR[LG2, 1, G, N[5]]; IFUR[LG3, 1, G, N[6]]; IFUR[LG4, 1, G, N[7]]; IFUR[LG5, 1, G, N[10]]; IFUR[LG6, 1, G, N[11]]; IFUR[LG7, 1, G, N[12]]; IFUR[LGB, 2, G]; * Load Global Byte: Push[FetchMDS[G+alpha]^]; *-------------------------------------------------------------------- Fetch_ ID, T_ StackNoUfl&+1, IFUNext1; :IfMEP; Fetch_ ID, T_ Stack&+1_ MD, IFUNext1; Fetch_ ID, StkP+2, IFUNext1; :Else; PushMD: Stack_ MD, IFUNext0, Global; * Branched to by all IFUNext1 :EndIF; *-------------------------------------------------------------------- IFUR[SL0, 1, L, N[4]]; * Store Local n: StoreMDS[L+n]^ _ Pop[]; IFUR[SL1, 1, L, N[5]]; IFUR[SL2, 1, L, N[6]]; IFUR[SL3, 1, L, N[7]]; IFUR[SL4, 1, L, N[10]]; IFUR[SL5, 1, L, N[11]]; IFUR[SL6, 1, L, N[12]]; IFUR[SL7, 1, L, N[13]]; IFUR[SLB, 2, L]; * Store Local Byte: StoreMDS[L+alpha]^ _ Pop[]; IFUR[SG0, 1, G, N[3]]; * Store Global n: StoreMDS[G+n]^ _ Pop[]; IFUR[SG1, 1, G, N[4]]; IFUR[SG2, 1, G, N[5]]; IFUR[SG3, 1, G, N[6]]; IFUR[SGB, 2, G]; * Store Global Byte: StoreMDS[G+alpha]^ _ Pop[]; *-------------------------------------------------------------------- Store_ ID, DBuf_ Stack&-1, IFUNext0CF; :IfMEP; Store_ ID, Stack&-1_ DBuf_ MD, IFUNext0; Store_ ID, DBuf_ T, IFUNext0; :Else; CheckFault0: T_ MD, IFUNext0, Global; * Branched to by all IFUNext0CF :EndIf; *-------------------------------------------------------------------- IFUR[PL0, 1, L, N[4]]; * Put Local n: StoreMDS[L+n]^ _ Pop[]; SP _ SP+1; IFUR[PL1, 1, L, N[5]]; IFUR[PL2, 1, L, N[6]]; IFUR[PL3, 1, L, N[7]]; *-------------------------------------------------------------------- :IfMEP; Store_ ID, T_ DBuf_ Stack&-1, IFUNext2; Store_ ID, T_ Stack&-1_ DBuf_ MD, IFUNext2; Store_ ID, DBuf_ T, IFUNext2; :Else; Store_ ID, DBuf_ Stack, IFUNext0CF; :EndIf; *-------------------------------------------------------------------- IFUR[LI0, 1, L, N[0]]; * Load Immediate n: Push[n]; IFUR[LI1, 1, L, N[1]]; IFUR[LI2, 1, L, N[2]]; IFUR[LI3, 1, L, N[3]]; IFUR[LI4, 1, L, N[4]]; IFUR[LI5, 1, L, N[5]]; IFUR[LI6, 1, L, N[6]]; IFUR[LIB, 2, L]; * Load Immediate Byte: Push[alpha]; *-------------------------------------------------------------------- Stack+1_ ID, IFUNext0; :IfMEP; T_ ID, Stack&+1_ MD, Branch[PushT]; Stack+2_ ID, IFUNext0; :EndIf; PushT: StackT_ T, IFUNext2; * Tail of many load instructions *-------------------------------------------------------------------- IFUR[LIN1, 1, L, N[0]]; * Load Immediate Negative One: Push[177777B]; IFUR[LINI, 1, L, N[2]]; * Load Immediate Negative Infinity: Push[100000B]; *-------------------------------------------------------------------- T_ (ID-1) RCY 1, StkP+1, Branch[PushT]; :IfMEP; T_ (ID-1) RCY 1, Stack&+1_ MD, Branch[PushT]; T_ (ID-1) RCY 1, StkP+2, Branch[PushT]; :EndIf; *-------------------------------------------------------------------- IFUR[LINB, 2, L]; * Load Immediate Negative Byte: * Push[BitOr[alpha, 177400B]]; * Note: PrincOps definition is: Push[SignExtend[alpha]]; * however, both Alto and D0 implement LINB as given here. *-------------------------------------------------------------------- T_ (ID) OR (177400C), StkP+1, Branch[PushT]; :IfMEP; T_ (ID) OR (177400C), Stack&+1_ MD, Branch[PushT]; T_ (ID) OR (177400C), StkP+2, Branch[PushT]; :EndIf; :If[AltoMode]; ********** Alto version ********** *-------------------------------------------------------------------- IFUR[LIW, 3, Code, N[4]]; * Load Immediate Word: Push[256*alpha + beta]; UndefOp[MOpLCO]; * LCO undefined in Alto mode * Alto Mesa: This is an aligned 3-byte instruction. *-------------------------------------------------------------------- RTemp0_ (ID)-(PCX')-1, Branch[LIWM1]; * RTemp0_ PCX+4 :IfMEP; Stack_ MD, Branch[.-1]; StkP+1, Branch[.-2]; :EndIf; LIWM1: T_ (RTemp0) RSH 1, A_ ID, Branch[.+2, R odd]; PCF_ RTemp0; T_ T-1; Fetch_ T, T_ StackNoUfl&+1, IFUNext1; :Else; ******** PrincOps version ******** *-------------------------------------------------------------------- IFUR[LIW, 3, L]; * Load Immediate Word: Push[256*alpha + beta]; IFUR[LCO, 3, L]; * Load Code Offset -- same as LIW *-------------------------------------------------------------------- T_ ID, StkP+1, Branch[LIWM1]; :IfMEP; T_ ID, Stack&+1_ MD, Branch[LIWM1]; T_ ID, StkP+2, Branch[LIWM1]; :EndIf; LIWM1: T_ LSH[T, 10]; StackT_ (ID) OR T, IFUNext2; :EndIf; ********************************** * Load/Store (32 bits) *-------------------------------------------------------------------- IFUR[LLDB, 2, L]; * Load Local Double Byte: * Push[FetchMDS[L+alpha]^]; Push[FetchMDS[L+alpha+1]^]; IFUR[LGDB, 2, G]; * Load Global Double Byte: * Push[FetchMDS[G+alpha]^]; Push[FetchMDS[G+alpha+1]^]; * This microcode is also the tail of RDBL. *-------------------------------------------------------------------- T_ (Fetch_ ID)+1, StkP+1, Branch[LDBM1]; :IfMEP; T_ (Fetch_ ID)+1, Stack&+1_ MD, Branch[LDBM1]; T_ (Fetch_ ID)+1, StkP+2, Branch[LDBM1]; :EndIf; LDBM1: Fetch_ T, T_ Stack&+1_ MD, IFUNext1; *------------------------------------------------------------------ IFUR[SLDB, 2, L]; * Store Local Double Byte: * StoreMDS[L+alpha+1]^ _ Pop[]; StoreMDS[L+alpha]^ _ Pop[]; IFUR[SGDB, 2, G]; * Store Global Double Byte: * StoreMDS[G+alpha+1]^ _ Pop[]; StoreMDS[G+alpha]^ _ Pop[]; * This microcode is also the tail of WDBL. *------------------------------------------------------------------- StkP-1, Branch[SDBM2]; :IfMEP; T_ (Store_ ID)+1, DBuf_ T, Stack_ MD, Branch[SDBM1]; :EndIf; SDBM2: T_ (Store_ ID)+1, DBuf_ Stack&+1, Branch[SDBM1]; SDBM1: Store_ T, DBuf_ Stack&-2, IFUNext0CF; * Stack maintenance *----------------------------------------------------------- IFUR[PUSH, 1, L]; * Push: SP _ SP+1; * This is legal (to a maximum of two levels): * 1. After instructions that only pop the stack (i.e., that don't * push any results onto it), or * 2. After instructions that explicitly leave results above TOS * (e.g., DIV). * Entry 1 is not possible because it implies that rule 1 has been violated. *----------------------------------------------------------- StkP+1, IFUNext0; :IfMEP; Branch[.], Breakpoint; StkP+2, IFUNext0; :EndIf; *----------------------------------------------------------- IFUR[POP, 1, L]; * Pop: SP _ SP-1; *----------------------------------------------------------- StkP-1, IFUNext0; :IfMEP; Stack&-1_ MD, IFUNext0; IFUNext0; :EndIf; *----------------------------------------------------------- IFUR[EXCH, 1, L]; * Exchange: v _ Pop[]; u _ Pop[]; Push[v]; Push[u]; *----------------------------------------------------------- T_ Stack&-1, Branch[EXCHM2]; :IfMEP; Stack&-1_ T_ MD, Branch[.+1]; :EndIf; EXCHM2: Stack&+1_ T, Q_ Stack&+1, Branch[EXCHM1]; EXCHM1: StackT_ Q, IFUNext2; *----------------------------------------------------------- IFUR[DUP, 1, L]; * Duplicate: u _ Pop[]; Push[u]; Push[u]; *----------------------------------------------------------- Stack+1_ Stack&+1, IFUNext0; :IfMEP; T_ Stack&+1_ MD, IFUNext1; Stack+2_ T, IFUNext0; :EndIf; *----------------------------------------------------------- IFUR[NILCK, 1, L]; * NIL Check: * p: POINTER _ Pop[]; Push[p]; IF p=NIL THEN PointerTrap[]; *----------------------------------------------------------- PD_ Stack, Branch[NILCKM1]; :IfMEP; Stack_ PD_ MD, Branch[NILCKM1]; PD_ T, StkP+1, Branch[NILCKM1]; :EndIf; NILCKM1: T_ sPointerFault, DblBranch[DoFaultT, NoFaultF, ALU=0]; *----------------------------------------------------------- IFUR[NILCKL, 1, L]; * NIL Check Long: * p: LONG POINTER _ PopLong[]; PushLong[p]; IF p=NIL THEN PointerTrap[]; *----------------------------------------------------------- T_ Stack&-1, Branch[NILCKLM2]; :IfMEP; PD_ T OR MD, Stack_ MD, Branch[NILCKM1]; :EndIf; NILCKLM2: PD_ T OR (Stack&+1), Branch[NILCKM1]; *----------------------------------------------------------- IFUR[BNDCK, 1, L]; * Bounds Check: * v: CARDINAL _ Pop[]; u: CARDINAL _ Pop[]; Push[u]; * IF u>=v THEN BoundsTrap[]; *----------------------------------------------------------- T_ Stack&-1, Branch[BNDCKM2]; :IfMEP; PD_ MD-T-1, Stack&-1_ MD, Branch[BNDCKM1]; :EndIf; BNDCKM2: PD_ T-(Stack)-1, Branch[BNDCKM1]; BNDCKM1: * Carry <=> TOS=0]; BigBDispatch_ T; Branch[RRTable]; RROutOfBounds: T_ A0, Branch[PushT]; *----------------------------------------------------------- RRTable: DispTable[nRRegs]; :If[AltoMode]; ********** Alto version ********** T_ A0, Branch[PushT]; * 0 undefined T_ WDC, Branch[PushT]; * 1 WDC T_ XTSReg, Branch[PushT]; * 2 Xfer trap state T_ A0, Branch[PushT]; * 3 Xfer trap parameter -- unimplemented T_ ATPReg, Branch[PushT]; * 4 Alloc trap parameter T_ OTPReg, Branch[PushT]; * 5 Other trap parameter T_ MDSHi, Branch[PushT]; * 6 high part of MDS :Else; ******** PrincOps version ******** T_ CurrentPSB, Branch[PushT]; * 0 current PSB T_ WDC, Branch[PushT]; * 1 WDC T_ XTSReg, Branch[PushT]; * 2 Xfer trap state T_ A0, Branch[PushT]; * 3 undefined T_ A0, Branch[PushT]; * 4 undefined T_ A0, Branch[PushT]; * 5 undefined T_ MDSHi, Branch[PushT]; * 6 high part of MDS T_ A0, Branch[PushT]; * 7 undefined T_ CurrentTime, Branch[PushT]; * 10 process time in ticks :EndIf; ********************************** *----------------------------------------------------------- *----------------------------------------------------------- IFUR[WR, 2, L]; * Write Register: Register[alpha] _ Pop[]; * If alpha is out of bounds, pops argument and does nothing else. *----------------------------------------------------------- Set[nWRegs, IfE[AltoMode, 0, 11, 3]]; * Number of defined registers T_ (ID)-(Add[nWRegs]C), Branch[WRM1]; :IfMEP; T_ (ID)-(Add[nWRegs]C), Stack_ MD, Branch[WRM1]; T_ (ID)-(Add[nWRegs]C), StkP+1, Branch[WRM1]; :EndIf; WRM1: T_ T+(Add[nWRegs]C), Branch[WROutOfBounds, ALU>=0]; BigBDispatch_ T; T_ Stack&-1, Branch[WRTable]; WROutOfBounds: IFUNext0; *----------------------------------------------------------- WRTable: DispTable[nWRegs]; :If[AltoMode]; ********** Alto version ********** IFUNext0; * 0 undefined WDC_ T+1, Branch[DWDCM1]; * 1 WDC XTSReg_ T, IFUNext0; * 2 Xfer trap state :Else; ******** PrincOps version ******** CurrentPSB_ T, IFUNext0; * 0 current PSB WDC_ T, Reschedule, IFUNext0; * 1 WDC XTSReg_ T, IFUNext0; * 2 Xfer trap state MDSHi_ T, Call[SetMDS]; * 3 high part of MDS IFUNext0; * 4 undefined IFUNext0; * 5 undefined IFUNext0; * 6 undefined IFUNext0; * 7 undefined CurrentTime_ T, IFUNext0; * 10 current process time *----------------------------------------------------------- Subroutine; SetMDS: T_ Link; TopLevel; MemBase_ G, Call[SetMDSBRHi]; MemBase_ L, Call[SetMDSBRHi]; MemBase_ SD, Call[SetMDSBRHi]; MemBase_ MDS; Link_ T, Branch[SetMDSBRHi]; Subroutine; SetMDSBRHi: BRHi_ MDSHi, Return; TopLevel; :EndIf; ********************************** (1552)