{File name NewLisp.mc } SetTask[0]; {****************************************************************** 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 _ 60, L2 _ L2.0, c2; TOS _ MD and TOS, XRefBr, c3; TOS _ TOS LRot8, BRANCH[rmNoRef, rmRef], c1; rmNoRef: TOS _ TOS RShift1, SE_0, IBDisp, GOTO[DNI.pc1], c2; rmRef: TOS _ TOS RShift1, SE_1, IBDisp, GOTO[DNI.pc1], c2; rdfUfn: Rx _ 161'b, GOTO[ufn1], c3; {****************************************************************** READRP *******************************************************************} READRP: Xbus _ TOSH xor smallpl, NZeroBr, c1, opcode[162'b]; {72} rhTT _ TT _ TOS LRot8, BRANCH[$, rdrpUfn], c2; TOSH _ smallpl, c3; Map _ [rhTT, TT], c1; TOS _ ~0F0, L2 _ L2.0, c2; TOS _ MD and TOS, XDirtyDisp, c3; PC _ PC + PC16, BRANCH[$, rrpi, 1], c1; IBDisp, GOTO[rrpj], c2; rrpi: TOS _ TOS + 0F + 1, IBDisp, GOTO[rrpj], c2; rrpj: 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; 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, XRefBr{>2mb}, c2; Q _ MD{vpH}, BRANCH[$, wmi], c3; Noop, GOTO[wmj], c1; wmi: Rx _ Rx or 80, GOTO[wmj], c1; wmj: Ybus _ Q xor smallpl, NZeroBr, c2; rhTT _ TT _ TT LRot8, BRANCH[$, ufnWM2], c3; S _ S -1, Xbus _ TOS LRot4, XDisp, c1; Rx _ Rx and ~070, DISP4[wmf, 4], c2; Rx _ Rx or 0, GOTO[wMap], c3, at[4, 10, wmf]; Rx _ Rx or 10, GOTO[wMap], c3, at[0C,10,wmf]; Rx _ Rx or 0{A}20, GOTO[wMap], c3, at[5, 10, wmf]; Rx _ Rx or 0{B}30, GOTO[wMap], c3, at[0D,10,wmf]; Rx _ Rx or 40, GOTO[wMap], c3, at[6, 10, wmf]; Rx _ Rx or 50, GOTO[wMap], c3, at[0E,10,wmf]; Rx _ Rx or 60, GOTO[wMap], c3, at[7, 10, wmf]; Rx _ Rx or 70, GOTO[wMap], {reserved} c3, at[0F,10,wmf]; 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, c3; RLMapFix1: Map _ [rhTT,TT], DISP2[RFixRFlags], c1; RFixRFlags: MDR _ Rx or 10, L0Disp, GOTO[ReRead], c2, at[0,4]; MDR _ Rx or 10, L0Disp, GOTO[ReRead], c2, at[1,4,RFixRFlags]; MDR _ Rx or 10, L0Disp, GOTO[ReRead], c2, at[2,4,RFixRFlags]; GOTO[RWTrap], c2, at[3,4,RFixRFlags]; ReRead: Xbus _ 1, XDisp, RET[RMapFixCaller], c3; RWTrap: 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 10, L0Disp, GOTO[RexRead], c2, at[0,4]; MDR _ Rx or 10, L0Disp, GOTO[RexRead], c2, at[1,4,RxFixRFlags]; MDR _ Rx or 10, L0Disp, GOTO[RexRead], c2, at[2,4,RxFixRFlags]; GOTO[RWTrap], c2, at[3,4,RxFixRFlags]; RexRead: Xbus _ 1, 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], DISP2[FixWFlags, 1], c1; FixWFlags: MDR _ Rx or 030, L0Disp, GOTO[ReWrite], c2, at[1,4,FixWFlags]; GOTO[RWTrap], c2, at[3,4,FixWFlags]; ReWrite: Rx _ Rx, Xbus _ 1, 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} PFault: , at[BBFault], 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; , 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: TOSH _ 0, 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: 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: , c1; PuntFor2: Ybus _ PC - PC16, PgCarryBr, c2; TT _ 30{ibPtrMask}, Cin _ pc16, BRANCH[pcZero, pcNZero], c3; pcNZero: GOTO[pntC2], c1; pcZero: Ybus _ TT and ~ ErrnIBnStkp, ZeroBr{empty}, c1; pntC2: BRANCH[$, setCross], c2; 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; , 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; , 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} {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; MAR _ [rhTT, Q + 0], c1; MDR{next} _ PV, Rx _ Rx{punt}-1, ZeroBr{KeyFXP}, c2; PV _ MD, BRANCH[RTN2, RTN2K], 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} 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; 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, XRefBr, c3; {(F) fetch instructions with restored PC} RetRedo: MAR _ Q _ [rhPC, Q + 0], BRANCH[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 }