*-----------------------------------------------------------
Title[DMesaJumps...March 8, 1981 7:14 PM...Taft];
*-----------------------------------------------------------

%

CONTENTS, by order of occurence

The term "byte" refers to alpha operand which is sign-extended and
used as an offset.

Unconditional jumps
JnJump .+n
JBJump Byte
JWJump Word

Conditional equality jumps
JEQnJump IF Equal
JEQBJump If Equal Byte
JZEQBJump Equal Zero Byte
JNEnJump If Not equal
JNEBJump If not equal Byte
JZNEBJump Not Equal Zero Byte

Conditional signed jumps
JLBJump Less
JGEBJump Greater or EQual Byte
JGBJump Greater Byte
JLEBJump Less or Equal Byte

Conditional unsigned jumps
JULBJump Unsigned Less Byte
JUGEBJump Unsigned Greater or EQual Byte
JULEBJump Unsigned Less or Equal Byte

Indexed jumps
JIBJump Indexed Byte
JIWJump Indexed Word

%

TopLevel;

*-----------------------------------------------------------
SetPCAndJump0:
* Common exit sequence:
* Effectively, execute PCF← T followed by IFUNext0.
* Actually, adjust TOS to a more favorable configuration (if possible)
* during the dead time between PCF← and IFUJump.
*-----------------------------------------------------------
Global, PCF← T;
:IfMEP;
ExitJump0:
T← TIOA&StkP;
PD← T AND (377C);
Branch[.+2, ALU#0];
IFUNext0;* Stack empty, must exit in state 0
T← Stack&-1, IFUNext2;* Non-empty, adjust to state 2
:Else;
ExitJump0:
Branch[@J2];* Nop; IFUNext0;
:EndIf;

*-----------------------------------------------------------
IFUR[J2, 2, L];
* Define J2 as 2-byte regular because it’s faster that way
IFUJ[J3, 1, L, Disp[3]];
* Jump n (unconditional): PC ← savePC+n
IFUJ[J4, 1, L, Disp[4]];
IFUJ[J5, 1, L, Disp[5]];
IFUJ[J6, 1, L, Disp[6]];
IFUJ[J7, 1, L, Disp[7]];
IFUJ[J8, 1, L, Disp[10]];
IFUJ[J9, 1, L, Disp[11]];
:If[Not[AltoMode]];
******** PrincOps version ********
IFUJ[JB, 2, L, SignExtend];
* Jump Byte (unconditional)
* PC ← savePC + SignExtend[alpha];
:EndIf;
**********************************
*-----------------------------------------------------------

IFUNext0;
:IfMEP;
T← Stack&-1← MD, IFUNext2;
IFUNext2;
:EndIf;

:If[AltoMode];
********** Alto version **********
*-----------------------------------------------------------
IFUP[JB, 2, L, SignExtend];
* Jump Byte (unconditional)
* Alto Mesa: the offset is relative to the PC of the last byte.
* Defined as a Pause opcode because the IFU can’t do the jump.
*-----------------------------------------------------------

T← (ID)-(PCX’), Branch[SetPCAndJump0];
:IfMEP;
T← (ID)-(PCX’), Stack← MD, Branch[SetPCAndJump0];
T← (ID)-(PCX’), StkP+1, Branch[SetPCAndJump0];
:EndIf;
:EndIf;
**********************************


:If[AltoMode];
********** Alto version **********
*-----------------------------------------------------------
IFUP[JW, 3, Code, N[1]];
* Jump Word (unconditional)
* Alto Mesa: this is an aligned 3-byte instruction, and the offset
* is relative to the PC of the last byte.
*-----------------------------------------------------------

T← (ID)-(PCX’), Branch[JWM1];* T← PCX+2
:IfMEP;
T← (ID)-(PCX’), Stack← MD, Branch[JWM1];
T← (ID)-(PCX’), StkP+1, Branch[JWM1];
:EndIf;

JWM1:
T← T RSH 1;
T← (Fetch← T)+T+1;
T← T+MD, Branch[SetPCAndJump0];

:Else;
******** PrincOps version ********
*-----------------------------------------------------------
IFUP[JW, 3, L];
* Jump Word (unconditional)
* disp ← 256*alpha + beta; PC ← savePC+disp;
*-----------------------------------------------------------

T← ID, Branch[JWM1];
:IfMEP;
T← ID, Stack← MD, Branch[JWM1];
T← ID, StkP+1, Branch[JWM1];
:EndIf;

JWM1:
T← LSH[T, 10];
T← (ID) OR T;* T← alpha,,beta
T← T-(PCX’)-1, Branch[SetPCAndJump0];
:EndIf;
**********************************

*-----------------------------------------------------------
IFUR[JEQ2, 1, L, N[IfE[AltoMode, 0, 2, 1]]];
* Jump Equal n:
IFUR[JEQ3, 1, L, N[IfE[AltoMode, 0, 3, 2]]];
IFUR[JEQ4, 1, L, N[IfE[AltoMode, 0, 4, 3]]];
IFUR[JEQ5, 1, L, N[IfE[AltoMode, 0, 5, 4]]];
IFUR[JEQ6, 1, L, N[IfE[AltoMode, 0, 6, 5]]];
IFUR[JEQ7, 1, L, N[IfE[AltoMode, 0, 7, 6]]];
IFUR[JEQ8, 1, L, N[IfE[AltoMode, 0, 10, 7]]];
IFUR[JEQ9, 1, L, N[IfE[AltoMode, 0, 11, 10]]];
* u ← Pop[]; v ← Pop[]; IF u=v THEN PC ← savePC + n;

IFUR[JEQB, 2, L, SignExtend];
* Jump Equal Byte:
* u ← Pop[]; v ← Pop[]; IF u=v THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JEQM2];
:IfMEP;
PD← T#MD, Stack&-2← MD, Branch[JEQM1];
:EndIf;
JEQM2:
PD← T#(Stack&-1), Branch[JEQM1];

:If[AltoMode];
********** Alto version **********
* For 1-byte opcodes in Alto mode, ID = displacement-1.
JEQM1:
T← (ID)-(PCX’), DblBranch[JNewT, JContF, ALU=0]; * T← PCX+alpha+1
:Else;
******** PrincOps version ********
JEQM1:
T← (ID)-(PCX’)-1, DblBranch[JNewT, JContF, ALU=0]; * T← PCX+alpha
:EndIf;
**********************************

JNewT:
PCF← T, Branch[ExitJump0];
JContF:
IFUNext0;


*-----------------------------------------------------------
IFUR[JZEQB, 2, L, SignExtend];
* Jump Zero Equal Byte
* u ← Pop[]; IF u=0 THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

PD← Stack&-1, Branch[JEQM1];
:IfMEP;
Stack&-1← PD← MD, Branch[JEQM1];
PD← T, Branch[JEQM1];
:EndIf;

*-----------------------------------------------------------
IFUR[JNE2, 1, L, N[IfE[AltoMode, 0, 2, 1]]];
* Jump Not Equal n:
IFUR[JNE3, 1, L, N[IfE[AltoMode, 0, 3, 2]]];
IFUR[JNE4, 1, L, N[IfE[AltoMode, 0, 4, 3]]];
IFUR[JNE5, 1, L, N[IfE[AltoMode, 0, 5, 4]]];
IFUR[JNE6, 1, L, N[IfE[AltoMode, 0, 6, 5]]];
IFUR[JNE7, 1, L, N[IfE[AltoMode, 0, 7, 6]]];
IFUR[JNE8, 1, L, N[IfE[AltoMode, 0, 10, 7]]];
IFUR[JNE9, 1, L, N[IfE[AltoMode, 0, 11, 10]]];
* u ← Pop[]; v ← Pop[]; IF u#v THEN PC ← savePC + n;

IFUR[JNEB, 2, L, SignExtend];
* Jump Not Equal Byte:
* u ← Pop[]; v ← Pop[]; IF u#v THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JNEM2];
:IfMEP;
PD← T#MD, Stack&-2← MD, Branch[JNEM1];
:EndIf;
JNEM2:
PD← T#(Stack&-1), Branch[JNEM1];

:If[AltoMode];
********** Alto version **********
* For 1-byte opcodes in Alto mode, ID = displacement-1.
JNEM1:
T← (ID)-(PCX’), DblBranch[JNewF, JContT, ALU#0]; * T← PCX+alpha+1
:Else;
******** PrincOps version ********
JNEM1:
T← (ID)-(PCX’)-1, DblBranch[JNewF, JContT, ALU#0]; * T← PCX+alpha
:EndIf;
**********************************

JNewF:
PCF← T, Branch[ExitJump0];
JContT:
IFUNext0;


*-----------------------------------------------------------
IFUR[JZNEB, 2, L, SignExtend];
* Jump Zero Not Equal Byte
* u ← Pop[]; IF u#0 THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

PD← Stack&-1, Branch[JNEM1];
:IfMEP;
Stack&-1← PD← MD, Branch[JNEM1];
PD← T, Branch[JNEM1];
:EndIf;

* Signed jumps

*-----------------------------------------------------------
IFUR[JLB, 2, L, SignExtend];
* Jump Less Byte:
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j<k THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JLBM2];
:IfMEP;
PD← MD-T-1, Stack&-2← MD, Branch[JineqM1];
:EndIf;
JLBM2:
PD← T-(Stack&-1)-1, Branch[JineqM1];

JineqM1:
Q← PCX’, Branch[.+2, ALU<0];
:If[AltoMode];
********** Alto version **********
T← (ID)-Q, DblBranch[JNewT, JContF, Overflow’]; * T← PCX+alpha+1
T← (ID)-Q, DblBranch[JContT, JNewF, Overflow’];
:Else;
******** PrincOps version ********
T← (ID)-Q-1, DblBranch[JNewT, JContF, Overflow’]; * T← PCX+alpha
T← (ID)-Q-1, DblBranch[JContT, JNewF, Overflow’];
:EndIf;
**********************************


*-----------------------------------------------------------
IFUR[JGEB, 2, L, SignExtend];
* Jump Greater Equal Byte:
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j>=k THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JGEBM2];
:IfMEP;
PD← T-MD, Stack&-2← MD, Branch[JineqM1];
:EndIf;
JGEBM2:
PD← (Stack&-1)-T, Branch[JineqM1];


*-----------------------------------------------------------
IFUR[JGB, 2, L, SignExtend];
* Jump Greater Byte:
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j>k THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JGBM2];
:IfMEP;
PD← T-MD-1, Stack&-2← MD, Branch[JineqM1];
:EndIf;
JGBM2:
PD← (Stack&-1)-T-1, Branch[JineqM1];


*-----------------------------------------------------------
IFUR[JLEB, 2, L, SignExtend];
* Jump Less Equal Byte:
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j<=k THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JLEBM2];
:IfMEP;
PD← MD-T, Stack&-2← MD, Branch[JineqM1];
:EndIf;
JLEBM2:
PD← T-(Stack&-1), Branch[JineqM1];

* Unsigned jumps

*-----------------------------------------------------------
IFUR[JULB, 2, L, SignExtend];
* Jump Unsigned Less Byte:
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u<v THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JULBM2];
:IfMEP;
PD← MD-T-1, Stack&-2← MD, Branch[JUineqM1];
:EndIf;
JULBM2:
PD← T-(Stack&-1)-1, Branch[JUineqM1];

:If[AltoMode];
********** Alto version **********
JUineqM1:
T← (ID)-(PCX’), DblBranch[JContT, JNewF, Carry’]; * T← PCX+alpha+1
:Else;
******** PrincOps version ********
JUineqM1:
T← (ID)-(PCX’)-1, DblBranch[JContT, JNewF, Carry’]; * T← PCX+alpha
:EndIf;
**********************************


*-----------------------------------------------------------
IFUR[JUGEB, 2, L, SignExtend];
* Jump Unsigned Greater Equal Byte:
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u>=v THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JUGEBM2];
:IfMEP;
PD← T-MD, Stack&-2← MD, Branch[JUineqM1];
:EndIf;
JUGEBM2: PD← (Stack&-1)-T, Branch[JUineqM1];


*-----------------------------------------------------------
IFUR[JUGB, 2, L, SignExtend];
* Jump Unsigned Greater Byte:
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u>v THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JUGBM2];
:IfMEP;
PD← T-MD-1, Stack&-2← MD, Branch[JUineqM1];
:EndIf;
JUGBM2:
PD← (Stack&-1)-T-1, Branch[JUineqM1];


*-----------------------------------------------------------
IFUR[JULEB, 2, L, SignExtend];
* Jump Unsigned Less Equal Byte:
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u<=v THEN PC ← savePC + SignExtend[alpha];
* Alto Mesa: the offset is relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JULEBM2];
:IfMEP;
PD← MD-T, Stack&-2← MD, Branch[JUineqM1];
:EndIf;
JULEBM2: PD← T-(Stack&-1), Branch[JUineqM1];

*-----------------------------------------------------------
IFUR[JIB, 3, Code, N[0]];
* Jump Indexed Byte
* base: CARDINAL ← 256*alpha + beta;
* limit: CARDINAL ← Pop[]; index: CARDINAL ← Pop[];
* IF index<limit then
* BEGIN disp: BytePair ← Fetch[C+LONG[base+index/2]]↑;
* PC ← savePC + (IF (index MOD 2)=0 THEN disp.left ELSE disp.right); END;

IFUR[JIW, 3, Code, N[1]];
* Jump Indexed Word
* base: CARDINAL ← 256*alpha + beta;
* limit: CARDINAL ← Pop[]; index: CARDINAL ← Pop[];
* IF index<limit then
* BEGIN disp: CARDINAL ← Fetch[C+LONG[base+index]]↑;
* PC ← savePC + disp; END;

* Alto Mesa: both JIB and JIW are aligned 3-byte opcodes and jump
* relative to the PC of the last byte.
*-----------------------------------------------------------

T← Stack&-1, Branch[JIBWM2];
:IfMEP;
T← Stack← MD, Branch[.+1];
:EndIf;
JIBWM2:
PD← (Stack)-T;

* Note that N will distinguish JIB (0) from JIW (1).
RTemp0← ID, Q← PCX’, Branch[JIBWInRange, Carry’]; * RTemp0← N

:If[AltoMode];
********** Alto version **********
* Out of range, fall through to the next opcode.
RTemp1← (4S)-Q-1;* RTemp1← PCX+4
A← ID, T← RTemp1, Branch[.+2, R even]; * Consume alpha; alignment ok?
StkP-1, IFUNext0;* Yes, exit normally
StkP-1, Branch[SetPCAndJump0];* No, restart IFU at PCX+4

* In range, evaluate the indexed jump.
JIBWInRange:
T← (NOT Q) RSH 1;* T← PCX/2
T← T+1, Q← Stack;* T← @(alpha,,beta), Q← index
RTemp1← (Fetch← T)+T+1;* RTemp1← PC of last byte
T← MD, Q RSH 1, RTemp0,* T← alpha,,beta, Q← index/2
DblBranch[JIWFetch, JIBFetch, R odd];

JIBWLast:
T← (RTemp1)+T, Branch[SetPCAndJump0];

:Else;
******** PrincOps version ********
* Out of range, fall through to the next opcode.
A← ID, StkP-1, Branch[JContF];* Consume alpha before IFUJump

* In range, evaluate the indexed jump.
JIBWInRange:
T← ID, Q← Stack;* T← alpha, Q← index
T← LSH[T, 10];
T← (ID) OR T, Q RSH 1, RTemp0,* T← alpha,,beta, Q← index/2
DblBranch[JIWFetch, JIBFetch, R odd];

JIBWLast:
T← T-(PCX’)-1, Branch[SetPCAndJump0];
:EndIf;
**********************************

JIBFetch:
* Common Alto/PrincOps code specific to JIB
T← T+Q;* T← base + index/2
Fetch← T;
T← MD, Stack&-1, Branch[.+2, R odd];
T← RSH[T, 10], Branch[JIBWLast]; * Left (even) byte
T← T AND (377C), Branch[JIBWLast]; * Right (odd) byte

JIWFetch:
* Common Alto/PrincOps code specific to JIW
T← T+(Stack&-1);* T← base+index
Fetch← T;
T← MD, Branch[JIBWLast];