{File name: Jump.mc
Last edited by Jim August 20, 1981 2:20 PM: Fix for new assembler.
Last Edited: R. Garner, April 11, 1980 6:56 PM,
Last Edited: Johnsson, August 27, 1980 4:49 PM
Description: PrincOps version 3.0 Jump microcode for Dandelion,
Author: R. Garner (Based on Wildflower microcode by R. Levin),
Created: April 10, 1979,
}
{The Jump mesa op-codes consist of the following. "time" includes instruction buffer refill.
OPvalbytesstktime (Jump/NoJump)
Jn200’b102
JB210’b203
JW211’b306
JEQn212’b1—23/2
JEQB222’b2—23/2
JNEn223’b1—23/2
JNEB233’b2—23/2
JEQBBxxxx3—13/2
JNEBBxxxx3—13/2
JZEQB244’b3—13/2
JZNEB245’b3—13/2
JLB234’b2—24/3
JGEB235’b2—24/3
JGB236’b2—24/3
JLEB237’b2—24/3
JULB240’b2—24/3
JUGEB241’b2—24/3
JUGB242’b2—24/3
JULEB243’b2—24/3
JIB246’b3—28/3
JIW247’b3—211/3
}
{Note: Update of the Map flag bits (which occurs first time page is touched) adds 2 clicks to the pagecross times given below}
{——————————————————————————————————————————————————————
Overview:
The jump code is written assuming the jump will be taken and a page boundary will not be crossed. It also assumes the PC (in particular, the real page part) is always correct (see comments at Refill microcode).
The jump instructions increment the PC before testing for any page faults. If the page we’re jumping to is mapped out, then, after the page fault trap, we should execute the byte code we’re jumping to instead of restarting the Jump instruction.
Register Useage:
L2[0-1]number of pops required
L2[1-2]PC increment
L2[3]0
L2 should be examined at the PageFault location (if L0=JRemap) to determine how to fixup the stack pointer.
Note that the PC increment field is not used for Jn, JB, &JW since they always jump.
——————————————————————————————————————————————————————}
{Stack for jump instructions with one stack operand u:
entry:exit:
TOS =| u|| b|
STK =| ~|| u|
-->| b|| b|
| a| -->| a|}
{Stack for jump instructions with two stack operands u & v:
entry:exit:
TOS =| v|| b|
STK =| ~|| v|
-->| u|| u|
| b|| b|
| a| -->| a|}
{TOS is saved into STK for all jump instructions.}
{L2 codes used to indicate stackP and PC fixups}
Set[L2.Pop0Incr1or2, 0 {00xx}]; {will be 2 with Jn cross}{Jn, JB, JW}
Set[L2.Pop1Incr2, 4 {0100}];{JZEQB, JZNEB}
{Set[L2.Pop1Incr3, 6 {0110}];{JEQBB, JNEBB}}
Set[L2.Pop2Incr1, 8 {1000}];{JEQn, JNEn}
Set[L2.Pop2Incr2, 0A {1010}]; {JEQB,JNEB,JLB,JLEB,JGB,JGEB,JULB,JULEB,JUGB,JUGEB}
Set[L2.Pop2Incr3, 0E {1110}];{JIB, JIW}
{6.1 Unconditional Jumps}
{——————————————————————————————————————————————————————
Jn, n=2-9
——————————————————————————————————————————————————————}
{Timing:2 clicks - jump within page, no map update,
5 clicks - jump to different page, no map update,
5 clicks - jump to last word within page, no map update}
@J2:MAR ← PC ← [rhPC, PC+1], push, GOTO[JnPos],c1,opcode[200’b];
@J3:MAR ← PC ← [rhPC, PC+1+PC16], push, GOTO[JnPos],c1,opcode[201’b];
@J4:MAR ← PC ← [rhPC, PC+2], push, GOTO[JnPos],c1,opcode[202’b];
@J5:MAR ← PC ← [rhPC, PC+2+PC16], push, GOTO[JnPos],c1,opcode[203’b];
@J6:MAR ← PC ← [rhPC, PC+3], push, GOTO[JnPos],c1,opcode[204’b];
@J7:MAR ← PC ← [rhPC, PC+3+PC16], push, GOTO[JnPos],c1,opcode[205’b];
@J8:MAR ← PC ← [rhPC, PC+4], push, GOTO[JnPos],c1,opcode[206’b];
@J9:MAR ← PC ← [rhPC, PC+4+PC16], push, GOTO[JnPos],c1,opcode[207’b];
{——————————————————————————————————————————————————————
JB
——————————————————————————————————————————————————————}
{Timing:3 clicks - jump within page, no map update,
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JB:L2 ← L2.Pop0Incr1or2,,c1,opcode[210’b];
jb:T ← ib RShift1, XLDisp, GOTO[jT],c2;
{——————————————————————————————————————————————————————
JW
——————————————————————————————————————————————————————}
{Timing:6 clicks - jump to arbitrary page, no map update
9 clicks - jump to last word of an arbitrary page, no map update}
@JW:T ← ib, XLDisp, L2 ← L2.Pop0Incr1or2,c1,opcode[211’b];
jw:T ← T LRot8, push, BRANCH[jwPos, jwNeg, 1],c2;
jwPos:T ← RShift1 (T or ib), SE←0, XLDisp, GOTO[jwtos],c3;
jwNeg:T ← RShift1 (T or ib), SE←1, XLDisp, GOTO[jwtos],c3;
jwtos:PC ← PC and 0FF, BRANCH[jwEven, jwOdd, 2],c1;
{PC,,pc16←location in page}
jwEven:Q ← PC + T, GOTO[jwCross],c2;
jwOdd:Q ← PC + T + PC16, GOTO[jwCross],c2;
jwCross:PC ← Q, STK ← TOS, L0 ← L0.JRemap, GOTO[UpdatePC],c3;
{6.2 Equality Jumps}
{——————————————————————————————————————————————————————
JEQn, n=2-9
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JEQ2:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[212’b];
j2:T ← 2 RShift1, XLDisp, BRANCH[jT, jF],c2;
@JEQ3:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[213’b];
j3:T ← 3 RShift1, XLDisp, BRANCH[jT, jF],c2;
@JEQ4:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[214’b];
j4:T ← 4 RShift1, XLDisp, BRANCH[jT, jF],c2;
@JEQ5:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[215’b];
j5:T ← 5 RShift1, XLDisp, BRANCH[jT, jF],c2;
@JEQ6:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[216’b];
j6:T ← 6 RShift1, XLDisp, BRANCH[jT, jF],c2;
@JEQ7:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[217’b];
j7:T ← 7 RShift1, XLDisp, BRANCH[jT, jF],c2;
@JEQ8:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[220’b];
j8:T ← 8 RShift1, XLDisp, BRANCH[jT, jF],c2;
@JEQ9:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr1,c1,opcode[221’b];
j9:T ← 9 RShift1, XLDisp, BRANCH[jT, jF],c2;
{——————————————————————————————————————————————————————
JEQB
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JEQB:[] ← STK xor TOS, NZeroBr, L2 ← L2.Pop2Incr2,c1,opcode[222’b];
jc22:T ← ib RShift1, XLDisp, BRANCH[jT, jF],c2;
{——————————————————————————————————————————————————————
JNEn, n=2-9
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JNE2:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j2],c1, opcode[223’b];
@JNE3:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j3],c1, opcode[224’b];
@JNE4:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j4],c1, opcode[225’b];
@JNE5:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j5],c1, opcode[226’b];
@JNE6:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j6],c1, opcode[227’b];
@JNE7:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j7],c1, opcode[230’b];
@JNE8:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j8],c1, opcode[231’b];
@JNE9:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr1, GOTO[j9],c1, opcode[232’b];
{——————————————————————————————————————————————————————
JNEB
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JNEB:[] ← STK xor TOS, ZeroBr, L2 ← L2.Pop2Incr2, GOTO[jc22],c1, opcode[233’b];
{Not in Mesa 5.0
{——————————————————————————————————————————————————————
JEQBB
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JEQBB:[] ← ib xor TOS, NZeroBr, L2 ← L2.Pop1Incr3,c1,opcode[400’b];
jc13:T ← ib RShift1, XLDisp, BRANCH[jT, jF],c2;
{——————————————————————————————————————————————————————
JNEBB
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JNEBB:[] ← ib xor TOS, ZeroBr, L2 ← L2.Pop1Incr3, GOTO[jc13],c1,opcode[401’b];
}
{——————————————————————————————————————————————————————
JZEQB
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JZEQB:[] ← TOS, NZeroBr, L2 ← L2.Pop1Incr2,c1,opcode[244’b];
jc12:T ← ib RShift1, XLDisp, BRANCH[jT, jF],c2;
{——————————————————————————————————————————————————————
JZNEB
——————————————————————————————————————————————————————}
{Timing:2 clicks - no jump
3 clicks - jump within page, no map update
6 clicks - jump to different page, no map update,
6 clicks - jump to last word within page, no map update}
@JZNEB:[] ← TOS, ZeroBr, L2 ← L2.Pop1Incr2, GOTO[jc12],c1,opcode[245’b];
{6.3 Signed Jumps}
{Timing for all signed jumps:
3 clicks - no jump
4 clicks - jump within page, no map update
7 clicks - jump to different page, no map update,
7 clicks - jump to last word within page, no map update}
{——————————————————————————————————————————————————————
JLB
——————————————————————————————————————————————————————}
{Jump if j<k : j-k is neg & no overflow OR j-k is pos & overflow}
@JLB:T ← STK {T←j},c1,opcode[234’b];
T ← T ̄ TOS {T←j-k}, PgCrOvDisp, GOTO[Jg],c2;
{——————————————————————————————————————————————————————
JGB
——————————————————————————————————————————————————————}
{Jump if j>k : k-j is neg & no overflow OR k-j is pos & overflow}
@JGB:T ← STK {T←j},c1,opcode[236’b];
T ← TOS ̄ T {T←k-j}, PgCrOvDisp,c2;
Jg:T ← ~T, BRANCH[jNoOv, jOv, 2],c3;
{——————————————————————————————————————————————————————
JGEB
——————————————————————————————————————————————————————}
{Jump if j>=k : j-k is pos & no overflow OR j-k is neg & overflow}
@JGEB:T ← STK {T←j},c1,opcode[235’b];
T ← T ̄ TOS {T←j-k}, PgCrOvDisp, GOTO[Jle],c2;
{——————————————————————————————————————————————————————
JLEB
——————————————————————————————————————————————————————}
{Jump if j<=k : k-j is pos & no overflow OR k-j is neg & overflow}
@JLEB:T ← STK {T←j},c1,opcode[237’b];
T ← TOS ̄ T {T←k-j}, PgCrOvDisp,c2;
Jle:BRANCH[jNoOv, jOv, 2],c3;
jNoOv:[] ← T, NegBr, L2 ← L2.Pop2Incr2, GOTO[jc22],c1;
jOv:[] ← ~T, NegBr, L2 ← L2.Pop2Incr2, GOTO[jc22],c1;
{6.4 Unsigned Jumps}
{Timing for all unsigned jumps:
3 clicks - no jump
4 clicks - jump within page, no map update
7 clicks - jump to different page, no map update,
7 clicks - jump to last word within page, no map update}
{The Unsigned jumps place Carry into the sign bit and share the signed jump code}
{——————————————————————————————————————————————————————
JULB
——————————————————————————————————————————————————————}
{Jump if u<v : no carry from u-v}
@JULB:T ← STK,c1,opcode[240’b];
T ← DARShift1 (T ̄ TOS), GOTO[Jle],c2;
{——————————————————————————————————————————————————————
JUGB
——————————————————————————————————————————————————————}
{Jump if v>u : no carry from v-u}
@JUGB:T ← STK,c1,opcode[242’b];
T ← DARShift1 (TOS ̄ T), GOTO[Jle],c2;
{——————————————————————————————————————————————————————
JUGEB
——————————————————————————————————————————————————————}
{Jump if u>=v : carry from u-v}
@JUGEB:T ← STK,c1,opcode[241’b];
T ← DARShift1 (T ̄ TOS), GOTO[Jg],c2;
{——————————————————————————————————————————————————————
JULEB
——————————————————————————————————————————————————————}
{Jump if u<=v : carry from v-u}
@JULEB:T ← STK,c1,opcode[243’b];
T ← DARShift1 (TOS ̄ T), GOTO[Jg],c2;
{6.5 Indexed Jumps}
{——————————————————————————————————————————————————————
JIB
——————————————————————————————————————————————————————}
{Timing:3 clicks - no jump,
8 clicks - jump within page, no map update
11 clicks - jump to different page, no map update,
11 clicks - jump to last word within page, no map update}
Set[L2.JIB, 0];
Set[L2.JIW, 4];
@JIB:T ← STK{index}, L2 ← L2.JIB,c1,opcode[246’b];
TT ← RShift1 T{index/2}, GOTO[jiCom],c2;
{——————————————————————————————————————————————————————
JIW
——————————————————————————————————————————————————————}
{Timing:3 clicks - no jump,
11 clicks - jump to arbitrary page, no map update
14 clicks - jump to last word of an arbitrary page, no map update}
@JIW:T ← STK{index}, L2 ← L2.JIW,c1,opcode[247’b];
TT ← T{index}, GOTO[jiCom],c2;
jiCom:[] ← T ̄ TOS {index-limit}, CarryBr,c3;
T ← ib, BRANCH[$, jiNoJump],c1;
T ← T LRot8, L0 ← L0.ji,c2;
T ← T or ib {base}, L1 ← L1r.NoFixes,c3;
T ← T + TT,c1;
Q ← UvC{code base},c2;
rhTT ← UvChigh,c3;
{Set the ibPtr to empty}
Map ← Q ← [rhTT, Q + T], IBPtr←1,c1;
Xbus ← ib,c2;
Rx ← rhRx ← MD, XRefBr,c3;
jiRedo:MAR ← [rhRx, Q+0], BRANCH[jiMapUD, $],c1, at[L0.ji,10,RxMapFixCaller];
Xbus ← STK, XLDisp, L2Disp,c2;
IB ← MD {ibFront←disp}, DISP3[jibLeft, 2],c3;
jibLeft:T ← 0, L2 ← L2.Pop2Incr3, GOTO[ji] {ibFront has disp.left},c1, at[2,8,jibLeft];
jibRight:T ← 0, Xbus ← ib, L2 ← L2.Pop2Incr3 {ibFront←disp.right}, GOTO[ji],c1, at[3,8,jibLeft];
jiwL:T ← ib, XLDisp, L2 ← L2.Pop2Incr3, GOTO[ji],c1, at[6,8,jibLeft];
jiwR:T ← ib, XLDisp, L2 ← L2.Pop2Incr3, GOTO[ji],c1, at[7,8,jibLeft];
ji:T ← T LRot8, push, BRANCH[jwPos, jwNeg, 1],c2;
jiMapUD:CALL[RLxMapFix] {will return to jiRedo},c2;
jiNoJump:Xbus ← ib, PC ← PC+PC16,c2;
Xbus ← L2.Pop2Incr3, XDisp, push {point to u}, GOTO[NoJump],c3;
{——————————————————————————————————————————————————————
jump common code
——————————————————————————————————————————————————————}
{The abscence of a pending branch at jT causes a jump and the prescence causes the jump to be aborted. T contains the word offset and TT the word offset for backwards jumps + 1.}
jT:TT ← 7F - T, DISP2[JPosEven],c3;
jF:L2Disp, push {point to u}, CANCELBR[NoJump, 3],c3;
{Fetch the first destination word, check for a page crossing, and prepare to save TOS into STK.}
JPosEven:MAR ← PC ← [rhPC, PC + T], push, GOTO[JPos],c1, at[0,4,JPosEven];
JPosOdd:MAR ← PC ← [rhPC, PC + T + PC16], push, GOTO[JPos],c1, at[1,4,JPosEven];
JNegEven:MAR ← PC ← [rhPC, PC - TT - 1], push, GOTO[JNeg],c1, at[2,4,JPosEven];
JNegOdd:MAR ← PC ← [rhPC, PC - TT - PC16], push, GOTO[JNeg],c1, at[3,4,JPosEven];
{Dispatch on the stackP fixup (L2[0-1]) and the new value of pc16. Also save TOS into STK. Place the first destination word into IB, or in the case of a page cross, prepare to remap the PC as in a "Buffer Empty" refill. (see Refill.mc). If the jump doesn’t page fault, reset uPCCross.}
JPos:STK ← TOS, Xbus←0, L2Disp, XC2npcDisp, BRANCH[jPNoCross, jP1Cross, 1],c2;
JNeg:STK ← TOS, Xbus←0, L2Disp, XC2npcDisp, BRANCH[jNNoCross, jN1Cross, 1],c2;
JnPos:STK ← TOS, L2 ← L2.Pop0Incr1or2, Xbus←0, XC2npcDisp, DISP2[jnPNoCross],c2;
jnPNoCross:IB ← MD, pop, DISP4[JPtr1Pop0, 2],c3, at[0,4,jnPNoCross];
jPNoCross:IB ← MD, pop, DISP4[JPtr1Pop0, 2],c3;
jNNoCross:IB ← MD, pop, DISP4[JPtr1Pop0, 2],c3;
{A page cross ocurred on the first destination word: goto the Refill page cross code. If a page fault occurs L2 encodes the required stack pointer fixup.
The high half of Q contains the page displacement. The low half of PC points to the word of the destination page. pc16 is correct. Note that for all the jump "byte" instructions and Jn the page displacement in Q is either +1 or -1. For JW, Q is arbitrary. (See Refill.mc.)
Control for no Map update will go: UpdatePCx (in Refill.mc), JCross (in Refill.mc), JRedo, JPtr1Pop0....}
jnP1Cross:Q ← 0FF + 1, L0 ← L0.JRemap, CANCELBR[UpdatePC, 0F],c3, at[2,4,jnPNoCross];
jP1Cross:Q ← 0FF + 1, L0 ← L0.JRemap, CANCELBR[UpdatePC, 0F],c3;
jN1Cross:Q ← ~0FF, L0 ← L0.JRemap, CANCELBR[UpdatePC, 0F],c3;
{Fetch the second destination word, set the instruction buffer pointer, and prepare to load TOS. If a PageCross occurs, treat it like the "Buffer Not Empty" refill case.
The Stack fixup code assumes that TOS has been saved into TOS for jumps which have no stack arguments (Jn, JB, JW).
Note that the Stack at JPtr1Pop0 (etc..) should be identical to the Stack at entry to the particular Jump instruction, execpt TOS has been saved into STK. When control reaches RCross or NoRCross (in Refill.mc) the stack appears as if the jump instruction has finished. If there is a page fault (via RCross), there will be no stack fixup.}
JPtr1Pop0:MAR ← [rhPC, PC + 1], IBPtr←1, push, GOTO[Jgo],c1, at[2,10,JPtr1Pop0];
JPtr1Pop1:MAR ← [rhPC, PC + 1], IBPtr←1, GOTO[Jgo],c1, at[6,10,JPtr1Pop0];
JPtr1Pop2:MAR ← [rhPC, PC + 1], IBPtr←1, pop, GOTO[Jgo],c1, at[0A,10,JPtr1Pop0];
JPtr1Pop2x:MAR ← [rhPC, PC + 1], IBPtr←1, pop, GOTO[Jgo],c1, at[0E,10,JPtr1Pop0];
JPtr0Pop0:MAR ← [rhPC, PC + 1], IBPtr←0, push, GOTO[Jgo],c1, at[3,10,JPtr1Pop0];
JPtr0Pop1:MAR ← [rhPC, PC + 1], IBPtr←0, GOTO[Jgo],c1, at[7,10,JPtr1Pop0];
JPtr0Pop2:MAR ← [rhPC, PC + 1], IBPtr←0, pop, GOTO[Jgo],c1, at[0B,10,JPtr1Pop0];
JPtr0Pop2x:MAR ← [rhPC, PC + 1], IBPtr←0, pop, GOTO[Jgo],c1, at[0F,10,JPtr1Pop0];
Jgo:TOS ← STK, AlwaysIBDisp, L0 ← L0.NERefill.Set, DISP2[NoRCross],c2;
{Don’t jump: Save TOS into STK and increment the PC and prepare to load TOS according to the Jump instruction which is encoded in L2. Note that Jn, JB, or JW do not come through NoJump since they always jump.}
NoJump:STK ← TOS, pop, DISP4[jPop1Incr2, 1],c1;
jPop1Incr2:PC ← PC+1, IBDisp, GOTO[JNI],c2, at[5,10,jPop1Incr2];
{jPop1Incr3:PC ← PC+1+PC16, IBDisp, GOTO[JNI],c2, at[7,10,jPop1Incr2];}
jPop2Incr1:PC ← PC+PC16, IBDisp, pop, GOTO[JNI],c2, at[9,10,jPop1Incr2];
jPop2Incr2:PC ← PC+1, IBDisp, pop, GOTO[JNI],c2, at[0B,10,jPop1Incr2];
jPop2Incr3:PC ← PC+1{+PC16 done at jiNoJump}, IBDisp, pop, GOTO[JNI],c2, at[0F,10,jPop1Incr2];
JNI:TOS ← STK, pop, DISPNI[OpTable],c3;