{File name MdbNewLisp.mc; DandeLion Interlisp Emulator - slow returns Last edited: Purcell, 28-Dec-83 12:35:27 use 3 mapflags only Last edited: Charnley, 29-Dec-83 14:32:39 Last edited: Purcell, 28-Dec-83 12:35:27 use 3 mapflags for 4MB real mem but keep dp stored for iop Last edited: Charnley, 15-Jul-83 10:37:34 Last edited: April 7, 1983 12:34 AM; sink if fault and PV<3000'b Last edited: April 5, 1983 11:31 AM disable fault context double exit trap Last edited: February 5, 1983 11:42 AM Last edited: January 17, 1983 12:54 PM moved initialization to InitLisp.mc Last edited: November 20, 1982 4:33 PM % debugging hack: draw screen and pause Last edited: November 20, 1982 1:00 PM debugging IOP starting handshake Last edited: August 11, 1982 1:45 AM Try keeping display off during disk boot } SetTask[0]; {StartAddress[Start];} {M1Loc: Q ← 129'd, GOTO[sink2], c1, at[Maintenance1Loc];{MP9129} Q ← 130'd, GOTO[sink3], c2, at[Maintenance2Loc];{MP9130} Q ← 131'd, GOTO[sink1], c3, at[Maintenance3Loc];{MP9131}} {****************************************************************** READFLAGS *******************************************************************} READFLAGS: Xbus ← TOSH xor smallpl, NZeroBr, c1, opcode[161'b]; {71} rhTT ← TT ← TOS LRot8, BRANCH[$, rdfUfn], c2; TOSH ← smallpl, c3; Map ← [rhTT, TT], c1; TOS ← 0E0, c2; TOS ← MD and TOS, c3; TOS ← TOS LRot12, c1; Ybus ← TOS and 0F, YDisp, c2; DISP4[CvtFlags,1], c3; TOS ← 00, GOTO[RFExit], c1, at[01,10,CvtFlags]; {00} {clean 0 clean} TOS ← 02, GOTO[RFExit], c1, at[03,10,CvtFlags]; {20} {dirty 2 wp na} TOS ← 01, GOTO[RFExit], c1, at[05,10,CvtFlags]; {40} {vacant 1 dirty} TOS ← 03, GOTO[RFExit], c1, at[07,10,CvtFlags]; {60} {vacant, dirty 3 vacant} TOS ← 08, GOTO[RFExit], c1, at[09,10,CvtFlags]; {80} {ref 8 ref} TOS ← 0A, GOTO[RFExit], c1, at[0B,10,CvtFlags]; {A0} {vacant, ref A wp,ref}{na} TOS ← 09, GOTO[RFExit], c1, at[0D,10,CvtFlags]; {C0} {dirty, ref 9 dirty,ref} TOS ← 0D, GOTO[RFExit], c1, at[0F,10,CvtFlags]; {F0} {??? D rsvp} RFExit: TOS ← TOS LRot12, IBDisp, L2 ← L2.0, GOTO[DNI.pc1], c2; rdfUfn: Rx ← 161'b, GOTO[ufn1], c3; {****************************************************************** READRP *******************************************************************} READRP: Xbus ← TOSH xor smallpl, NZeroBr, c1, opcode[162'b]; rhTT ← TT ← TOS LRot8, BRANCH[$, rdrpUfn], c2; TOSH ← smallpl, c3; Map ← [rhTT, TT], c1; TOS ← ~0E0, L2 ← L2.0, c2; TOS ← MD and TOS, c3; {%M} Ybus ← TOS - 1, PgCarryBr, c1; BRANCH[rsect0, rsectN0], c2; rsect0: GOTO[readrpend], c3; rsectN0: TOS ← TOS - 3, GOTO[readrpend], c3; {%M} readrpend: PC ← PC + PC16, c1; IBDisp, c2; TOS ← TOS LRot8, L2 ← L2.0, DISPNI[OpTable], c3; rdrpUfn: Rx ← 162'b, GOTO[ufn1], c3; {****************************************************************** WRITEMAP *******************************************************************} WRITEMAP: {vp, rp, flag => vp} MAR ← [rhS, S], S ← S -1, c1, opcode[163'b];{73} Ybus ← TOSH xor smallpl, NZeroBr, CANCELBR[$, 2], c2; Rx ← MD{rp}, BRANCH[$, ufnWM0], c3; { Test to see if the rp is in the display bank. If so, leave it alone else bump pg# by 300} TT ← Rx and ~0FF, c1; Ybus ← TT + 0, ZeroBr, c2; TT ← 3, BRANCH[notDB, isDB], c3; notDB: TT ← TT LRot8, c1; Rx ← Rx + TT, c2; {add 3 segs} , c3; isDB: MAR ← [rhS, S + 0], c1; S ← S -1, c2; Q ← MD{rpH}, c3; MAR ← [rhS, S], S ← S -1, c1; Ybus ← Q xor smallpl, NZeroBr, CANCELBR[$,2], c2; TT ← MD{vp}, BRANCH[$, ufnWM1], c3; MAR ← [rhS, S+0], L2 ← L2.0, c1; Rx ← Rx LRot8, c2; Q ← MD{vpH}, c3; Noop, c1; Ybus ← Q xor smallpl, NZeroBr, c2; rhTT ← TT ← TT LRot8, BRANCH[$, ufnWM2], c3; S ← S -1, Xbus ← TOS LRot4, XDisp, c1; Rx ← Rx and ~0E0, DISP4[wmf, 4], c2; Rx ← Rx or 0, GOTO[wMap], c3, at[4, 10, wmf]; {clean} Rx ← Rx or 80, GOTO[wMap], c3, at[0C,10,wmf]; {ref, clean} Rx ← Rx or 040, GOTO[wMap], c3, at[5, 10, wmf]; {dirty --> dirty, ref} Rx ← Rx or 0C0, GOTO[wMap], c3, at[0D,10,wmf]; {dirty, ref --> dirty, ref} Rx ← Rx or 20{60}, GOTO[wMap], c3, at[6, 10, wmf]; {wp} Rx ← Rx or 0A0, GOTO[wMap], c3, at[0E,10,wmf]; {wp,ref} Rx ← Rx or 060, GOTO[wMap], c3, at[7, 10, wmf]; {vacant, dirty --> vacant, dirty} Rx ← Rx or 0E0, GOTO[wMap], {reserved} c3, at[0F,10,wmf]; {?? - everything} wMap: Map ← [rhTT, TT], c1; MDR ← Rx, PC ← PC + PC16, IBDisp, c2; TOS ← TT LRot8, L2 ← L2.0, DISPNI[OpTable], c3; ufnWM0: S ← S+1, GOTO[ufnX2], c1; ufnWM1: S ← S+3, GOTO[ufnX2], c1; ufnWM2: S ← S+3, GOTO[ufnX2], c1; {************************* Read Map Update Subroutine **************************} {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok, relative to RMapFixCaller} {returns thru L1 if wants to trap, relative to RFixForTrap} RLMapFix: Xbus ← Rx LRot0,XwdDisp, GOTO[RLMapFix1], c3; {RLMapFixPC: Rx ← PC, Xbus ← PC LRot0,XwdDisp, GOTO[RLMapFix1], c3;} RLMapFix1: Map ← [rhTT,TT], DISP2[RFixRFlags], c1; RFixRFlags: MDR ← Rx or 80, L0Disp, GOTO[ReRead], c2, at[PgClean,4]; MDR ← Rx or 80, L0Disp, GOTO[ReRead], c2, at[PgDirty,4,RFixRFlags]; MDR ← Rx or 80, L0Disp, GOTO[ReRead], c2, at[PgProt,4,RFixRFlags]; GOTO[RWTrap], c2, at[PgVacant,4,RFixRFlags]; ReRead: Xbus ← ReadOK, XDisp, RET[RMapFixCaller], c3; RWTrap: Noop, GOTO[PFault], c3; {copy of MapFix for more than 16 returns} RLxMapFix: Xbus ← Rx LRot0, XwdDisp, c3; RLxMapFix1: Map ← [rhTT,TT], DISP2[RxFixRFlags], c1; RxFixRFlags: MDR ← Rx or 80, L0Disp, GOTO[RexRead], c2, at[PgClean,4]; MDR ← Rx or 80, L0Disp, GOTO[RexRead], c2, at[PgDirty,4,RxFixRFlags]; MDR ← Rx or 80, L0Disp, GOTO[RexRead], c2, at[PgProt,4,RxFixRFlags]; GOTO[RWTrap], c2, at[PgVacant,4,RxFixRFlags]; RexRead: Xbus ← ReadOK, XDisp, RET[RxMapFixCaller], c3; {************************* Write Map Update Subroutine **************************} {Timing: 4 cycles} {Enter at cycle 3, returns to cycle1} {returns thru L0 if map fixed ok} {returns thru L1 if wants to trap} WLMapFix: Xbus ← Rx LRot0, XwdDisp, c3; Map ← [rhTT, TT], WriteDISP2[FixWFlags], c1; FixWFlags: MDR ← Rx or 0C0, L0Disp, GOTO[ReWrite], c2, at[PgWrtOK,4,FixWFlags]; GOTO[RWTrap], c2, at[PgNoWrt,4,FixWFlags]; ReWrite: Rx ← Rx, Xbus ← PgDirty, XDisp, RET[WMapFixCaller], c3; {************************* FixForTrap (merge RFixForTrap and WFixForTrap) **************************} PC ← PC - 1, GOTO[NoMoreFix], c1, at[L1.DecDec,10,Fix]; PC ← PC - 1, GOTO[PushFix], c1, at[L1.PushDec2,10,Fix]; PushFix: S ← S + 2, GOTO[TrapFixDone], c2; PC ← PC - PC16, GOTO[NoMoreFix], c1, at[L1.DecOnly,10,Fix]; PC ← PC - 1 - PC16, GOTO[NoMoreFix], c1, at[L1.Dec3,10,Fix]; S ← S + 2, GOTO[NoMoreFix], c1, at[L1.PushOnly,10,Fix]; S ← S - 2, GOTO[NoMoreFix], c1, at[L1.PopOnly,10,Fix]; S ← S + 4, GOTO[NoMoreFix], c1, at[L1.Push2OK,10,Fix]; NoMoreFix: Noop, GOTO[TrapFixDone], c2; TrapFixDone: Noop, {GOTO[PUNT]} c3; NoFixes: Rx ← PV LRot8, c1, at[L1.NoFixes,10,Fix]; Ybus ← 5 - Rx {- 6}{+FFFA}, PgCarryBr{small PV}, c2; Rx ← FAULTFXP, BRANCH[PUNT, ReFault], c3; {store fault address in interface page} BBFault: PFault: , at[PFaultB0], rhRx ← INTERFACEspace, c1; Rx ← INTERFACEbasePage{20'b}{INTERFACEbase=10000'b}, c2; Rx ← Rx LRot8, c3; {for debugging set uPageFault to all ones while in fault} Map ← [rhRx,Rx], c1; , c2; Rx ← rhRx ← MD, c3; MAR ← [rhRx, 0 + IFPFAULTHI], c1; MDR ← rhTT, CANCELBR[$, 2], WriteOK, c2; uPageFault ← S xor ~ S, c3; MAR ← [rhRx, 0 + IFPFAULTHI + 1], L2 ← 0{NotInCall}, c1; MDR ← TT, L1Disp, CANCELBR[$, 2], WriteOK, c2; Rx ← {0 -} FAULTFXP, RET[Fix], c3; ReFault: Q ← 24'd, GOTO[sink2], c1;{MP9024} {**************************************************} CONTEXTSWITCH: {**************************************************} {Takes context number in TOS: switch to that context, return value ignored} {% SHOULD CHECK IF ANY PENDING INTERRUPTS - CURRENTLY MAY MISS KEYSTROKES } opcode[176'b],{7E} Ybus ← TOS xor FAULTFXP, ZeroBr{faultExit}, L2← 0{NotInCall}, c1; Rx← TOS, BRANCH[$, SwFault], c2; TOSH ← 0, CANCELBR[ConJn], c3; SwFault: uPageFault ← TOSH ← 0{notFaulting}, c3; ConJn: uWDC ← TOSH, PC← PC + PC16 {advance PC}, GOTO[PuntFor2], c1; {note that this code winds up storing the context number on the stack and then setting the no-push bit in the frame. This is not exactly the same as the Dorado, but no code relies on the value returned "to" a context} {**************************************************} {UvPCpageL is up to date as each opcode starts executing. If the instruction buffer holds bytes from two pages then mint is set and uPCCrossL ← -1. At end of instruction if (uPCCrossL and PC#0FF) then PC has crossed page as it was advanced in the instruction. In such a case the buffer will need refill and the situation will be caught at the next IBDisp by means of mint. If a trap such as stack overflow should happen after PC is advanced but before IBDisp then this case must be explicitly checked for} StackOverflow: {testing} Rx ← {0 -} SubovFXP, L2 ← 0{NotInCall}, GOTO[PuntFor2], c1; {************************************************** PuntFor: {Punt without Back up} {Rx=FXP#}{L2 odd => set InCall bit} **************************************************} {to finish an opcode simulate the fetch for the next one} {i.e. ibEmpty and PC=0 then updatepc by PCCrossL←true} { PCCrossL and PC#FF then updatepc} PuntFor: Noop, c1; PuntFor2: Ybus ← PC - PC16, PgCarryBr, c2; TT ← 30{ibPtrMask}, Cin ← pc16, BRANCH[pcZero, pcNZero], c3; pcNZero: Noop, GOTO[pntC2], c1; pcZero: Ybus ← TT and ~ ErrnIBnStkp, ZeroBr{empty}, c1; pntC2: Noop, BRANCH[$, setCross], c2; Noop, GOTO[PUNT], c3; setCross: uPCCrossL ← TT xor ~TT, GOTO[PUNT], c3; {**************************************************} PUNT: {L2 odd => set InCall bit ELSE set NoPush bit} {**************************************************} MAR ← S ← [rhS, S + 1], GOTO[RetCont9], c1; RetCont9: MDR ← TOSH, BRANCH[$, RetCar9, 1], c2; Noop, c3; MAR ← S ← [rhS, S + 1], c1; MDR ← TOS, CANCELBR[$, 2], WriteOK, c2; PV ← PV - 0A{flags-pvar}, c3; pntNP:{Set NoPushReturn bit} MAR ← PV ← [rhPV, PV + 0], c1; Noop, c2; Q{flags} ← MD{flags}, L2Disp, c3; pntNP1: MAR ← PV ← [rhPV, PV + 0], BRANCH[$, pntInC, 0E], c1; MDR ← Q{flags} or uFxNoPushReturn, GOTO[pntJ], c2; pntInC: MDR ← Q{flags} or uFxInCall, GOTO[pntJ], c2; pntJ: TT ← PC and 0FF, c3; pntPC:{Store relative byte PC = 2*[UvPCpageL-UvCL+(PC and 0FF)]+PC16} Q ← UvCL, c1; TT{PC-UvCL-1} ← TT - Q - 1, Xbus ← uPCCrossL, XRefBr, c2; UnCross: Q ← UvPCpageL, BRANCH[pntNC, $], c3; pntC:{Optional click: uPCCross is true, so check for PC#FF} {option} Ybus ← PC + 2, PgCarryBr{LastWord?}, c1; {option} Q{bytePC} ← Q + 0FF + 1, BRANCH[$, UnCross], c2; {option} uPCCrossL ← 0, {UvPCpageL corrected} c3; pntNC: TT{PC-UvCL+UvPCpageL} ← TT + Q + 1, c1; TT{bytePC} ← TT + TT + PC16, CarryBr, c2; PV ← PV + 5{FxPc - FxFlags}, BRANCH[$, PcNegError], c3; MAR ← PV ← [rhPV, PV + 0], c1; MDR{bytePC} ← TT{bytePC}, c2; TT{ESP} ← uStkLimO, c3; pntN:{store Next} MAR ← PV ← [rhPV, PV - 1], {pc = next or 1} c1; MDR{next} ← S ← S + 1, CANCELBR[$, 2], WriteOK, c2; PV ← PV - 04{0 - next}, {restore PV} c3; pntF:{make remaining stack Free} MAR ← S ← [rhS, S + 0], c1; MDR{next} ← uFreeStackBlock, c2; TT{size} ← TT - S, c3; MAR ← S ← [rhS, S + 1], c1; MDR{next} ← TT + nStkLimOffset, CANCELBR[$, 2], WriteOK, c2; Noop{@@} {rhTT ← INTERFACEspace}, c3; {pntP:}{swap PV with memory in interface page} {make subroutine %%%}{MidPunt called by RTN2 when stack overflow} pntP: TT ← INTERFACEbasePage, GOTO[MidPunt2], c1; MidPunt: TT ← INTERFACEbasePage, GOTO[MidPunt2], c1; MidPunt2: TT ← TT LRot8, c2; TT ← TT + Rx{punt}, rhTT ← INTERFACEspace, c3; Map ← Q ← [rhTT,TT], c1; Rx ← Rx -1, c2; uuPV ← PV, TT ← rhTT ← MD,{ XRefBr,} c3; {%M MAR ← [rhTT, Q + 0], c1; MDR{next} ← PV, Rx ← Rx{punt}-1, ZeroBr{KeyFXP}, c2; PV ← MD, BRANCH[RTN2, RTN2K], c3; %M} MAR ← [rhTT, Q + 0], c1; , c2; Rx ← MD, c3; MAR ← [rhTT, Q + 0], c1; MDR{next} ← PV, c2; PV ← Rx, GOTO[RTN2], c3; {exceptions:} RetCar9: S ← S +0FF + 1, CANCELBR[$, 1], c3; MAR ← [rhS, S + 0], GOTO[RetCont9], c1; PcNegError: Q ← 126'd, GOTO[sink2], c1;{MP9126} {**************************************************} RETURN: {3% 8 clicks} {**************************************************} MAR ← Q{pAlink} ← [rhPV, PV - 9{alink-pvar}], CANCELBR[$, 0F], c1, opcode[20'b];{10} RetCont0: TT{ivar} ← uIVar, BRANCH[$, RetCar0{smash PV}, 1], c2; PV ← MD{aLink}, XLDisp, L1 ← 1{TT{S}}, c3; rtI:{IVar}{if aLink is odd then the next fetch hits Flags instead of ivar} MAR ← [rhPV, PV - 0B{IVar}], BRANCH[FastRet2, SlowRet, 2], c1; SlowRet: Rx{alinkFlags} ← PV - 0B{flags-(pvar+1)}, CANCELBR[$, 2], c2; STK{alinkFlags} ← Rx, PV{pClink} ← Q{pAlink} + 7+1{clink-alink}, c3; {************ HARD RETURN is necessary? **************} { hardRet1 if self.alink#self.clink } { hardRet2 if caller.usecnt>0 } { hardRet3 if caller.next is busy } { unless caller.next=ivar & self.blink.cnt=0 } {*****************************************************} { hardRet3a if caller.next#ivar & caller.next#free } { hardRet3b if self.blink.cnt>0 & caller.next#free } {*****************************************************} rthC:{clink - 1} {uuPV{pClink} ←} MAR ← PV ← [rhPV, PV + 0], c1; Q{alink} ← Rx{alinkFlags} + 0A{pvar-flags}, c2; TT{clink} ← MD{clink}, c3; rthF:{flags.usecnt - 2} rhRx ← nRhS, c1; , c2; , c3; MAR ← [rhRx, Rx{alinkFlags}+0], c1; {RetCont4:} Ybus ← Q{alink} xor TT{clink}, NZeroBr, rhTT ← nRhS, c2; TT{flags} ← MD{flags}, BRANCH[$, hardRet1], c3; rthN:{next - 3} MAR ← Rx ← [rhRx, Rx + 4{next-flags}], c1; RetCont5: Ybus← TT{flags} - 1, PgCarryBr{cnt>0?}, rhRx ← nRhS, BRANCH[$, RetCar5, 1], c2; Rx{next} ← MD{next}, BRANCH[$, hardRet2], c3; rthT:{next stack block type free?} MAR ← Q{next} ← [rhRx, Rx{next} + 0], c1; Noop, c2; Rx{block} ← MD{block}, c3; rthBL:{blink} sav0: MAR ← PV{pBlink} ← [rhPV, PV - 1], c1; Ybus ← Rx{block} xor uFreeStackBlock, ZeroBr{free}, CANCELBR[$, 2], c2; TT{t3:blink} ← MD{blink}, L1{free}←0, BRANCH[free0, free1], c3; rthBLF:{blinkFlags} free0: MAR ← [rhTT, TT{t3:blink} + 0], GOTO[free2], c1; free1: MAR ← [rhTT, TT{t3:blink} + 0], GOTO[free2], c1; free2: Ybus ← uIVar xor Q{next}, ZeroBr, L1Disp{free}, c2; Q{t4:blinkFlags} ← MD{blinkFlags}, BRANCH[hardRet3a,$], c3; rthBF:{get bflags} MAR ← PV ← [rhPV, PV - 0A{bflags - blink}], c1; RetCont6: Ybus ← 0 - Q{t4:blinkFlags}, PgCarryBr{cnt=0?}, L1Disp{free}, BRANCH[$, RetCar6, 1], c2; Rx{bflags} ← MD{bflags}, BRANCH[hardRet3b, $], c3; {************ FREE FRAMES (basic and extension) ************} rtfM:{misc} Ybus ← Rx{bflags} and uBfResidualRhmask, ZeroBr, c1; Ybus ← 0 - Q{t4:blinkFlags}, PgCarryBr{cnt=0?}, BRANCH[rtSkip, $], c2; PV ← uIVar,{treat BF as part of FX} CANCELBR[freeFx, 1], c3; rtSkip: Rx{ivar} ← uIVar, BRANCH[$, freeBf], c3; nqnz: MAR ← [rhTT, TT{t3:blink} + 0], c1; MDR ← Q{blinkFlags} - 1, c2; Noop, GOTO[freeFx], c3; {rtfBF: free basic frame} freeBf: MAR ← [rhRx, Rx{ivar} + 0], c1; MDR ← uFreeStackBlock, c2; TT{t3:blink} ← TT + 2, c3; MAR ← [rhRx, Rx{ivar}+1], c1; MDR ← TT{t3:blink} - Rx{uIVar}, CANCELBR[$, 2],WriteOK, c2; Noop, c3; {rtfFX: free frame extension}{free from PV to ESP, then return to uuPV{alink}} freeFx: MAR ← PV ← [rhPV, PV + 0{bflags - bflags}], c1; MDR ← uFreeStackBlock, c2; TT{ESP} ← uESP, c3; MAR ← [rhPV, PV + 1], c1; MDR ← TT{ESP} - PV, CANCELBR[$, 2],WriteOK, c2; PV{destFX} ← STK{alinkFlags}{uRx{alinkFlags}}, GOTO[RTN2], c3; {************ Keyboard context switch ************} RTN2K: MAR ← [rhPV, PV + 4{FxNext}], L1 ← 1, GOTO[rtn22], c1; {************ RESTORE STATE of frame ************} RTN2: {return to frame pointed to by PV{points to flags}}{context switch here} {************ ***********************************} MAR ← [rhPV, PV + 4{FxNext}], L1 ← 1, c1; rtn22: rhTT ← nRhS, BRANCH[$, RetCar8, 1], c2; RetCont8: TT{ESP} ← MD{next}, L1Disp{1}, c3; {rtrS: check free stack block} extend: MAR ← [rhTT, TT{ESP} + 0], BRANCH[$, rtrFirst], c1; uStkLimO ← Q{uStkLimO}, {skip on first iteration} c2; extend3: Rx{block} ← MD{block}, c3; MAR ← [rhTT, TT{ESP} + 1], c1; Ybus ← Rx{block} xor uFreeStackBlock, NZeroBr, CANCELBR[$, 2], c2; Rx{size} ← MD{size}, BRANCH[$, notFree], c3; {uESP ←} TT{ESP} ← TT{ESP} + Rx{size}, L1 ← 0, c1; uESP ← TT, c2; Q{uStkLimO} ← TT{ESP} - nStkLimOffset, GOTO[extend] c3; rtrFirst: S ← TT{ESP}, GOTO[extend3], c2; {{rtrF: flags}} {sufficient stack?} notFree: Noop, {PV unchanged, ready to overflow punt} c1; Ybus ← S - Q{uStkLimO}, CarryBr{S >= limit}, c2; Rx ← SubovFXP, BRANCH[$, MidPunt], c3; MAR ← PV ← [rhPV, PV + 0], L1Disp, c1; Rx{pFlags} ← PV, rhRx ← nRhS, BRANCH[$, notFreeTrap], c2; TT{flags} ← MD{flags}, c3; Xbus ← TT{flags} LRot8, XDisp, c1; UvCL ← 0, L1 ← 0, DISP4[rtf, 0A], c2; PV ← PV + 0A{pvar - flags}, GOTO[FastRet], c3, at[0A, 10, rtf]; rtrNoP: {Other cases: turn off special bit, discard TOS, TOSH} Q{flagMask} ← ~ uFxNoPushReturn, GOTO[rtrFix], c3, at[0B, 10, rtf]; Q{flagMask} ← ~ uFxInCall, GOTO[rtrFix], c3, at[0E, 10, rtf]; Q{flagMask} ← ~ uFxInCall, GOTO[rtrFix], c3, at[0F, 10, rtf]; rtrFix: MAR ← [rhRx, Rx{pFlags} + 0], c1; MDR ← TT{flags} and Q{flagMask}, c2; S ← S - 1, c3; MAR ← [rhS, S], S ← S - 1, c1; PV ← PV + 5{pc-flags}, CANCELBR[$, 2], c2; TOS ← MD, L1Disp, c3; MAR ← [rhS, S + 0], BRANCH[$, InCall, 0B], c1; PV ← PV + 5{pvar-pc}, c2; TOSH ← MD, GOTO[FastRet], c3; InCall: S ← S -1, c2; TOSH ← MD, c3; {(PC) get byte PC into PC and UvPCpageL for immediate storing}{UvCL = 0} MAR ← [rhPV, PV+0], Xbus ← 0, XC2npcDisp, c1; PV ← PV + 5{pvar-pc}, BRANCH[ICwasO, ICwasE, 2], c2; ICwasE: PC{pc} ← MD{pc}, GOTO[ICnowO], Cin ← pc16, c3; ICwasO: PC{pc} ← MD{pc}, GOTO[ICnowO], c3; ICnowO: PC ← (PC{bytePC} - 1{apply incs}) RShift1, SE ← 0, YDisp, c1; Q ← PC{pc} and ~0FF, BRANCH[pcEv, pcOdd, 0E], c2; pcEv: UvPCpageL ← Q, Cin←pc16, GOTO[preAPPLY], c3; pcOdd: UvPCpageL ← Q, GOTO[preAPPLY], c3; preAPPLY: IBPtr ← 1, c1; uPCCrossL ← 0, c2; Xbus ← ib, GOTO[APPLY], c3; {************ Slow Exceptions ************} hardRet1: PV{pPvar} ← PV{pClink} +1, GOTO[hdRet], c1; hardRet2: PV{pPvar} ← PV{pClink} +1, GOTO[hdRet], c1; hardRet3a: PV{pPvar} ← PV{pBlink} +2, GOTO[hdRet], c1; hardRet3b: PV{pPvar} ← PV{pBflags} +0C, GOTO[hdRet], c1; hdRet: Rx ← 20'b, GOTO[ufn3], c2; { Noop, c3; hardRet: Noop, GOTO[ufn2], {cycle one break point} c1;} notFreeTrap: Q ← 16'd, GOTO[sink1], c3;{MP9016} RetCar5: Rx ← Rx +0FF + 1, CANCELBR[$, 1], c3; MAR ← [rhRx, Rx + 0], GOTO[RetCont5], c1; RetCar6: PV ← PV - 0FF - 1, CANCELBR[$, 1], c3; MAR ← [rhPV, PV + 0], GOTO[RetCont6], c1; RetCar8: PV ← PV +4{FxNext}, c3; MAR ← [rhPV, PV + 0], c1; PV ← PV - 4, GOTO[RetCont8], c2; {************************************ FAST RETURN: PV{PVars}, S{next} if L1:2 TT{next} if L1:1 *************************************} {(A) get IVar} FastRet: MAR ← [rhPV, PV - 0B{pvar-IVar}], L1 ← 2{S:next}, c1; FastRet2: PV ← PV - 5{pvar-pc}, BRANCH[$, RetCar2, 1], c2; RetCont2: STK ← TOSH, TOSH ← MD{ivar}, L1Disp, c3; {(PC) get byte PC (relative to code base)} rtPC: MAR ← [rhPV, PV+0], Xbus ← 0, XC2npcDisp, BRANCH[rtS, rtTT, 2], c1; rtS: S ← S -1, BRANCH[wasO, wasE, 2], IB ← 6{constant used later}, c2; rtTT: S ← TT -1, BRANCH[wasO, wasE, 2], IB ← 6{constant used later}, c2; wasE: PC{PC} ← MD{PC}, GOTO[nowO], Cin ← pc16, c3; wasO: PC{PC} ← MD{PC}, GOTO[nowO], c3; {(C) get UvCL, code base} nowO: MAR ← PV ← [rhPV, PV- 3{fn lo}], L0 ← L0.RetRedo, c1; Ybus ← PC, PC ← PC RShift1, SE ← 0, YDisp, IBPtr ← 1, BRANCH[$, RetCar7, 1], c2; RetCont7: TT{UvCL} ← MD{UvCL}, L3 ← 0E, BRANCH[beEven, beOdd, 0E], c3; {(C) get UvChighL, calulate virtual PC in TT} beEven: MAR ← Q ← [rhPV, PV + PC16{=1}], L1 ← L1.Ret, GOTO[jnRet], c1; beOdd: MAR ← Q ← [rhPV, PV + 1], L1 ← L1.Ret, GOTO[jnRet], c1; jnRet: UvCL ← TT, PV ← Q + ibNA{6} + 1{fn hi}, CANCELBR[$, 2], c2; rhTT ← MD{UvChighL}, TT ← TT + PC, c3; {(MF) map and fetch with restored PC} rtMF: Map ← Q ← [rhTT, TT], L0 ← L0.RetRedo, c1; TT ← TT and ~0FF, L2 ← L2.0, c2; UvPCpageL ← TT, rhPC ← PC ← MD, ReadXRefBr, c3; {(F) fetch instructions with restored PC} MAR ← Q ← [rhPC, Q + 0], ReadBRANCH[RetMapX,$], c1, at[L0.RetRedo,10,RMapFixCaller]; uIVar ← TOSH, TT ← rhTT, L3Disp, c2; IB ← MD, PC ← Q, UvChighL ← TT, BRANCH[rptr0, rptr1, 0E], c3; rptr0: MAR ← [rhPC, PC + 1], IBPtr←0, L0←L0.NERefill, GOTO[retjoin], c1; rptr1: MAR ← [rhPC, PC + 1], IBPtr←1, L0←L0.NERefill, GOTO[retjoin], c1; retjoin: TOSH ← STK, AlwaysIBDisp, DISP2[NoRCross], c2; {exceptions:} RetMapX: Rx ← PC, GOTO[RLMapFix], c2; RetFix: uIVar ← TOSH, TT ← rhTT, c1, at[L1.Ret,10,Fix]; UvChighL ← TT, PC ← Q, c2; TOSH ← STK, c3; uPCCrossL ← 0, GOTO[NoMoreFix], c1; RetCar0: PV ← PV - 9{alink-pvar}, c3; MAR ← Q ← [rhPV, PV + 0], GOTO[RetCont0], c1; RetCar2: PV ← PV -6, c3; MAR ← [rhPV, PV + 0], c1; PV ← PV +6, GOTO[RetCont2], c2; RetCar7: PV ← PV -0FF - 1, L3 ← 0E, BRANCH[rc7e, rc7o, 0E], c3; rc7e: MAR ← [rhPV, PV + 0], GOTO[rc7], c1; rc7o: MAR ← [rhPV, PV + 0], GOTO[rc7], c1; rc7: L3Disp, GOTO[RetCont7], c2; { E N D }