{file: Jump.mc last edit 21-Feb-84 17:51:10 } SetTask[0]; {************************* JUMP 1% 2 clicks **************************} @JUMP: opcode[200'b], MAR _ PC _ [rhPC, PC+1], GOTO[JnPos], c1; MAR _ PC _ [rhPC, PC+1+PC16], GOTO[JnPos], c1,opcode[201'b]; MAR _ PC _ [rhPC, PC+2], GOTO[JnPos], c1,opcode[202'b]; MAR _ PC _ [rhPC, PC+2+PC16], GOTO[JnPos], c1,opcode[203'b]; MAR _ PC _ [rhPC, PC+3], GOTO[JnPos], c1,opcode[204'b]; MAR _ PC _ [rhPC, PC+3+PC16], GOTO[JnPos], c1,opcode[205'b]; MAR _ PC _ [rhPC, PC+4], GOTO[JnPos], c1,opcode[206'b]; MAR _ PC _ [rhPC, PC+4+PC16], GOTO[JnPos], c1,opcode[207'b]; MAR _ PC _ [rhPC, PC+5], GOTO[JnPos], c1,opcode[210'b];{88} MAR _ PC _ [rhPC, PC+5+PC16], GOTO[JnPos], c1,opcode[211'b]; MAR _ PC _ [rhPC, PC+6], GOTO[JnPos], c1,opcode[212'b]; MAR _ PC _ [rhPC, PC+6+PC16], GOTO[JnPos], c1,opcode[213'b]; MAR _ PC _ [rhPC, PC+7], GOTO[JnPos], c1,opcode[214'b]; MAR _ PC _ [rhPC, PC+7+PC16], GOTO[JnPos], c1,opcode[215'b]; MAR _ PC _ [rhPC, PC+8], GOTO[JnPos], c1,opcode[216'b]; MAR _ PC _ [rhPC, PC+8+PC16], GOTO[JnPos], c1,opcode[217'b]; JnPos: Xbus _ 0, XC2npcDisp, BRANCH[$, JnCross, 1], c2; IB _ MD, BRANCH[ptr1, ptr0, 0E], c3; JnCross: Q _ 0FF + 1, L0 _ L0.JRemap, CANCELBR[UpdatePC, 0F], c3; @JUMPX: opcode[260'b], S _ S + 1, Xbus _ ibNA, XLDisp, L2 _ L2.ok, c1; Rx _ ib RShift1, XLDisp, SE _ 0, BRANCH[jxp, jxn, 1], c2; jxp: BRANCH[jpe, jpo, 2], c3; jxn: Rx _ 7F - Rx, BRANCH[jne, jno, 2], c3; {************************* FJUMP, TJUMP 4% 4 clicks **************************} @FJUMP: opcode[220'b], MAR _ [rhS, S], S _ S -1, L2 _ 0, c1; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 1, c1, opcode[221'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 2, c1, opcode[222'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 3, c1, opcode[223'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 4, c1, opcode[224'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 5, c1, opcode[225'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 6, c1, opcode[226'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 7, c1, opcode[227'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 8, c1, opcode[230'b];{98} Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 9, c1, opcode[231'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 0A, c1, opcode[232'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 0B, c1, opcode[233'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 0C, c1, opcode[234'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 0D, c1, opcode[235'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 0E, c1, opcode[236'b]; Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; MAR _ [rhS, S], S _ S -1, L2 _ 0F, c1, opcode[237'b]; fj: Ybus _ TOSH or TOS, NZeroBr, CANCELBR[jmp, 2], c2; @TJUMP: opcode[240'b], MAR _ [rhS, S], S _ S -1, GOTO[tj], c1; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[241'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[242'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[243'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[244'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[245'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[246'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[247'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[250'b];{A8} MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[251'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[252'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[253'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[254'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[255'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[256'b]; MAR _ [rhS, S], S _ S -1, GOTO[tj], c1, opcode[257'b]; tj: Ybus _ TOSH or TOS, ZeroBr, CANCELBR[jmp, 2], c2; jmp: TOS _ MD, BRANCH[$, NoJump], L2Disp, c3; MAR _ [rhS, S + 0], DISP4[TgetsL,1], c1; TgetsL: Rx _ 1, L2Disp, GOTO[jjoin], c2, at[1, 10, TgetsL]; Rx _ 2, L2Disp, GOTO[jjoin], c2, at[3, 10, TgetsL]; Rx _ 3, L2Disp, GOTO[jjoin], c2, at[5, 10, TgetsL]; Rx _ 4, L2Disp, GOTO[jjoin], c2, at[7, 10, TgetsL]; Rx _ 5, L2Disp, GOTO[jjoin], c2, at[9, 10, TgetsL]; Rx _ 6, L2Disp, GOTO[jjoin], c2, at[0B, 10, TgetsL]; Rx _ 7, L2Disp, GOTO[jjoin], c2, at[0D, 10, TgetsL]; Rx _ 8, L2Disp, GOTO[jjoin], c2, at[0F, 10, TgetsL]; NoJump: MAR _ [rhS, S], S _ S -1, CANCELBR[$, 0F], c1; PC _ PC+PC16, L2 _ L2.0, IBDisp, DISP2[njNoCar], c2; S _ S - 0FF, c3, at[2, 10, njNoCar]; MAR _ [rhS, S+0], c1; S _ S -1, L2 _ L2.0, IBDisp, c2; njNoCar: TOSH _ MD, L2 _ L2.0, DISPNI[OpTable], c3, at[0, 10, njNoCar]; {************************* FJUMPX, TJUMPX **************************} {based on the stack pointer conventions:} {Q: does MAR_ interfere with XLDisp when no pagecarry?} @FJUMPX: opcode[262'b], MAR _ [rhS, S], S _ S - 1, Xbus _ ibNA, XLDisp, c1; Ybus _ TOSH or TOS, NZeroBr, BRANCH[pos, neg, 1], c2; @TJUMPX: opcode[263'b], MAR _ [rhS, S], S _ S -1, Xbus_ ibNA, XLDisp, c1; Ybus _ TOSH or TOS, ZeroBr, BRANCH[pos, neg, 1], c2; {************************* NFJUMPX, NTJUMPX 2% 4 clicks **************************} @NFJUMPX: opcode[264'b], {different on jump: don't pop} MAR _ [rhS, S], S _ S - 1, Xbus _ ibNA, XLDisp, c1; Ybus _ TOSH or TOS, NZeroBr, BRANCH[Npos, Nneg, 1], c2; @NTJUMPX: opcode[265'b], MAR _ [rhS, S], S _ S - 1, Xbus _ ibNA, XLDisp, c1; Ybus _ TOSH or TOS, ZeroBr, BRANCH[Npos, Nneg, 1], c2; Npos: uTOS _ TOS, TOS _ MD, BRANCH[$, NoJumpP], c3; TOS _ uTOS, c1; Rx _ ib RShift1, XLDisp, SE _ 0, c2; S _ S + 2, BRANCH[jpe, jpo, 2], c3; Nneg: uTOS _ TOS, TOS _ MD, BRANCH[$, NoJumpF], c3; Rx _ 0FF, c1; , c2; , c3; TOS _ uTOS, c1; Rx _ (ib xor Rx) RShift1, XLDisp, SE _ 0, c2; S _ S + 2, BRANCH[jne, jno, 2], c3; {************************* JUMPXX **************************} @JUMPXX: opcode[261'b], Rx _ ib, XLDisp, c1; jw: Rx _ Rx LRot8, BRANCH[jwPos, jwNeg, 1], c2; jwPos: Rx _ RShift1 (Rx or ib), SE_0, XLDisp, GOTO[jwtos], c3; jwNeg: Rx _ RShift1 (Rx or ib), SE_1, XLDisp, GOTO[jwtos], c3; jwtos: PC _ PC and 0FF, BRANCH[jwEven, jwOdd, 2], c1; {PC,,pc16_location in page} jwEven: PC _ PC + Rx, GOTO[jwCross], c2; jwOdd: PC _ PC + Rx + PC16, GOTO[jwCross], c2; jwCross: uPCCrossL _ 0, c3; , c1; , c2; Q _ PC and ~0FF, L0 _ L0.JRemap, GOTO[UpdatePC], c3; {************************* Common Jump Code **************************} pos: TOS _ MD, BRANCH[$, NoJumpX], c3; MAR _ [rhS, S+0], c1; Rx _ ib RShift1, XLDisp, SE _ 0, c2; jjoin: TOSH _ MD, BRANCH[jpe, jpo, 0E], c3; jpe: MAR _ PC _ [rhPC, PC + Rx], GOTO[jp], MesaIntBr, c1; jpo: MAR _ PC _ [rhPC, PC + Rx + PC16], MesaIntBr, c1; jp: S _ S - 1, Xbus _ 0, XC2npcDisp, DISP2[JumpPX], c2; jp3: IB _ MD, BRANCH[ptr1, ptr0, 0E], c3, at[0, 4, JumpPX]; ptr0: MAR _ [rhPC, PC + 1], IBPtr _ 0, L2 _ L2.0, GOTO[RefillNE2], c1; ptr1: MAR _ [rhPC, PC + 1], IBPtr _ 1, L2 _ L2.0, GOTO[RefillNE2], c1; NoJumpP: MAR _ [rhS, S], S _ S - 1, Xbus _ ib, GOTO[nj], c1; NoJumpF: MAR _ [rhS, S], S _ S - 1, Xbus _ ib, GOTO[nj], c1; NoJumpN: MAR _ [rhS, S], S _ S - 1, Xbus _ ib, GOTO[nj], c1; NoJumpX: MAR _ [rhS, S], S _ S - 1, Xbus _ ib, GOTO[nj], c1; nj: PC _ PC+1, IBDisp, L2 _ L2.0, DISP4[njxNoCar], c2; S _ S - 0FF, c3, at[2, 10, njxNoCar]; MAR _ [rhS, S+0], c1; S _ S - 1, IBDisp, L2 _ L2.0, c2; njxNoCar: TOSH _ MD, L2 _ L2.0, DISPNI[OpTable], c3, at[0, 10, njxNoCar]; Q _ 0FF + 1, L0 _ L0.JRemap, CANCELBR[UpdatePC, 0F], c3, at[2, 4, JumpPX]; Q _ ~0FF, L0 _ L0.JRemap, CANCELBR[UpdatePC, 0F], c3, at[2, 4, JumpNX]; Q _ 0FF + 1, L0 _ L0.JRemap, CANCELBR[UpdatePC, 0F], c3, at[3, 4, JumpPX]; Q _ ~0FF, L0 _ L0.JRemap, CANCELBR[UpdatePC, 0F], c3, at[3, 4, JumpNX]; IB _ MD, uPCCrossL _ 0, BRANCH[ptrJ1, ptrJ0, 0E], c3, at[1, 4, JumpPX]; IB _ MD, uPCCrossL _ 0, BRANCH[ptrJ1, ptrJ0, 0E], c3, at[1, 4, JumpNX]; ptrJ0: IBPtr_0, GOTO[MInt], c1; ptrJ1: IBPtr_1, GOTO[MInt], c1; neg: TOS _ MD, BRANCH[$, NoJumpN], c3; TT _ 0FF, c1; , c2; , c3; STK _ MAR _ [rhS, S], c1; Rx _ (ib xor TT) RShift1, SE _ 0, XLDisp, CANCELBR[$, 2], c2; TOSH _ MD, BRANCH[jne, jno, 2], c3; jne: MAR _ PC _ [rhPC, PC - Rx -1], GOTO[jn], MesaIntBr, c1; jno: MAR _ PC _ [rhPC, PC - Rx - PC16], GOTO[jn], MesaIntBr, c1; jn: S _ S - 1, Xbus _ 0, XC2npcDisp, DISP2[JumpNX], c2; jn3: IB _ MD, BRANCH[ptr1, ptr0, 0E], c3, at[0, 4, JumpNX]; {*************************} { Jump.dfn comments on PC, IFU, page crossing and control transfer The DLion Interlisp-D Instruction Fetch Unit (IFU) is implemented in hardware and microcode. Code arrays cannot cross segments. Name tables cannot cross pages. The IFU state variables and their values AT OPCODE ENTRY are: STATE CONCEPTUALLY STORED IN THE LOCAL FRAME codeB UvCL + UvChighL*2^16 fn header tPC 2*[UvPCpageL-UvCL+(PC and 0FF)]+PC16 true byte PC ADDITIONAL IFU STATE IBCnt=IBPtr number of valid bytes in IFU (must correlate even/odd with pc16 in puntFor? elsewhere ErrnIBnStkp?) CACHED IFU STATE : UvChighL (codeB)/(2^16) code base high UvCL (0FFFF and codeB) UvPCpageL (0FF00 and (codeB + tPC/2) rhPC upper Map(codeB + tPC/2)) PC real segment and flags PC (0FF and tPC/2)+(0FF00 and Map(codeB + tPC/2)) PC real word address pc16 (tPC and 1) PC byte flip flop uPCCrossL ((tPC and 1FE)=1FE) = (PC = (FF mod 100)) MInt interrupt or uPCCrossL IFU STATE AT OPCODE ENTRY A1) OPCODE ENTRY STANDARD A2) OPCODE ENTRY abort to Pfault PUNT uPCCrossL and (PC and FE)#FE has special meaning (for puntFor? for 4 byte ops?) => tPC _ tPC + 200 L2 has special meaning B1) OPCODE EXIT to refill (1b) (Mint) if (uPCCrossL and (PC and FF)#FF) then UpdatePC + 100; {uPCCrossL _ 0} (2) (RefillE) if ~uPCCrossL and IBCnt=0 and (tPC and 1FF)=0 then UpdatePC + 100 (1a) (RefilNE) uPCCrossL _ (PC and FF)=FF B2) OPCODE EXIT to "punt forward" (1b) if uPCCrossL and (PC and FE)#FE then UpdatePC + 100 (2) if {~uPCCrossL and} IBCnt=0 and (tPC and 1FF)=0 then UpdatePC + 100 PAGE CROSS PRINCIPLE: Notice page cross by (1a+1b)IFU containing bytes from 2 pages or (2) by IFU exhausted at exactly page boundry. PAGE CROSS PRINCIPLE for 4 bytes (i) still valid (ii): {c) going to PCUpdate tPC _ tPC + 2*Q} f) at fmMD of function call L3 } {Buffer Empty Refill. Control goes from NoRCross to RefillNE since RefillE+1 does not contain an IBDisp.} RefillE: MAR _ [rhPC, PC], PC _ PC - PC16, L0 _ L0.ERefill, c1, at[400]; PC _ PC+PC16 {restore}, DISP2[NoRCross], c2; {Buffer Not Empty Refill.} {"Noop" location of Instruction Dispatch table} OpTable: RefillNE: at[OpTable], Refil: MAR _ [rhPC, PC + 1], L2 _ L2.0, c1; RefillNE2: AlwaysIBDisp, L0 _ L0.NERefill.Set, DISP2[NoRCross], c2; NoRCross: IB _ MD, uPCCrossL _ 0, L2 _ L2.0, DISPNI[OpTable], c3, at[0,4,NoRCross]; RCross: Q _ 0FF + 1, GOTO[UpdatePC], c3, at[2,4,NoRCross]; {************************ Refill Remap Routines *******************************} { Entry: T old real PC Q[0-7] page displacement to be added to virtual PC Q[8-15] ignored PC[0-7] ignored PC[8-15] valid location within new page pc16 must be valid Exit: UvPCpageL new virtual PC page TT new virtual PC page rhTT UvChighL PC new real PC value Q new real PC value } {L0.ERefill & uPCCrossL indicate remap and fetch (NE) PC+1} UpdatePC: TT _ UvPCpageL, L1 _ L1.Refill{for fault trap}, c1, at[0F,10]; UpdatePC2: TT _ TT + Q, rhTT _ UvChighL, c2; UpdatePC3: Q{lowPC} _ PC, c3; Map _ MAR _ TT _ [rhTT, 0+0], L0Disp, c1; DISP4[ECross], c2; PC _ Q{lowPC}, GOTO[NoMoreFix], c1, at[L1.Refill,10,Fix]; {Buffer Empty Refill page cross OR PCCross flag true. Remap the PC (which points to 1st or 2nd word of page). If we are doing an empty refill, return to the Empty Refill code at NoRCross. If we are updating the PC because PCCross is true, return to Refill-interrupt code.} {Even if we fault, have UvPCpageL updated.} ECross: UvPCpageL _ TT, PC _ MD, rhPC _ MD, XRefBr, c3, at[L0.ERefill,10,ECross]; ERedo: MAR _ Q _ [rhPC, Q+0], Xbus _ uPCCrossL, XRefBr, BRANCH[EMapUD, $], c1, at[L0.ERefill,10,RMapFixCaller]; PC _ Q, BRANCH[NoRCross, PageCrossed], c2; EMapUD: Rx _ PC, CANCELBR[RLMapFix] {returns at ERedo}, c2; {Buffer Not Empty Refill page cross. Fetch the first word of the next page and do NOT Remap PC. Set PCCross true and the Refill-Interrupt hardware bit. Dispatch on the IB (as in the RefillNE code).} NECross: Rx _ MD, rhRx _ MD, XRefBr, c3, at[L0.NERefill,10,ECross]; NERedo: MAR _ [rhRx, 0+0], MesaIntRq, BRANCH[NEMapUD, $], c1, at[L0.NERefill,10,RMapFixCaller]; AlwaysIBDisp, L2 _ L2.0, c2; IB _ MD, uPCCrossL _ (~TT xor TT), L2 _ L2.0, DISPNI[OpTable], c3; NEMapUD: uPCCrossL _ (~TT xor TT), CALL[RLMapFix] {returns at NERedo}, c2; {Jump Cross Remap. Remap the PC (which can point to any word of a page). uPCCrossL should remain unaltered in case the page cross test at Jgo is true.} {Even if we fault, have UvPCpageL updated.} JCross: UvPCpageL _ TT, PC _ MD, rhPC _ MD, XRefBr, c3, at[L0.JRemap,10,ECross]; JRedo: MAR _ Q _ [rhPC, Q+0], BRANCH[JMapUD, $], c1, at[L0.JRemap,10,RMapFixCaller]; PC _ Q, Xbus_0, XC2npcDisp, c2; IB _ MD, BRANCH[ptr1, ptr0, 0E], c3; JMapUD: Rx _ PC, CALL[RLMapFix] {returns at JRedo}, c2; {************************* Interrupt Processing **************************} MInt0: at[600], TT _ 0{buffer empty}, Xbus _ uPCCrossL, XRefBr, GOTO[MInt], c1; MInt1: at[700], TT _ TT xor ~TT{not empty}, Xbus _ uPCCrossL, XRefBr, GOTO[MInt], c1; MInt: Ybus _ uWDC, NZeroBr, BRANCH[$, Crossing], c2; TT _ uWP, ClrIntErr, BRANCH[Interuption, IgnoreInt], c3; IgnoreInt: Noop, c1; IBDispOnlyL: IBDisp, L2 _ L2.0, GOTO[DISPNIonly], c2; DISPNIonly: L2 _ L2.0, DISPNI[OpTable], c3; Interuption: Ybus _ TT, ZeroBr, c1; BRANCH[Wakeups, NoWakeups], c2; NoWakeups: GOTO[IgnoreInt], c3; Wakeups: uWP _ 0, c3; Rx _ 1, c1; uWDC _ Rx,{off interrupts} c2; Rx _ KbdFXP, L2 _ 0{NotInCall}, GOTO[PuntFor], c3; {uPCCrossL is true. Check if we are still on last word of page. If not, go update the PC to point to the next page. T contains 0 if buffer is empty, -1 otherwise. This is put back into uPCCrossL. If buffer is not empty control goes from ECross to PageCross which ignores the first word fetched.} Crossing: Ybus _ PC + 1, PgCarryBr, CANCELBR[$], c3; L0 _ L0.ERefill, BRANCH[$, NotAcross], c1; uPCCrossL _ TT, GOTO[RCross], c2; {We haven't crossed the boundary yet. Save state again, keep uPCCrossL true.} NotAcross: AlwaysIBDisp, L2 _ L2.0, GOTO[DNI.nop], c2; {We've crossed the page boundary & updated the PC to point to the next page. Zero uPCCrossL. We know the buffer is not empty, but we also know it is not full so we exit through RefillNE.} PageCrossed: uPCCrossL _ 0, GOTO[RefillNE], c3, at[1,4,NoRCross]; { E N D }