*-----------------------------------------------------------
Title[Jump.mc...November 7, 1982  3:32 PM...Taft];
* Jump instructions (PrincOps, chapter 6)
*-----------------------------------------------------------

%

	CONTENTS, by order of occurence

Unconditional jumps
	Jn		Jump n
	JB		Jump Byte
	JW		Jump Word
	JS		Jump Stack
	CATCH		Catch

Equality jumps
	JZn		Jump Zero n
	JNZn		Jump Not Zero n
	JZB		Jump Zero Byte
	JNZB		Jump Not Zero Byte
	JEB		Jump Equal Byte
	JNEB		Jump Not Equal Byte
	JEP		Jump Equal Pair
	JNEP		Jump Not Equal Pair
	JEBB		Jump Equal Byte Byte
	JNEBB		Jump Not Equal Byte Byte

Signed jumps
	JLB		Jump Less Byte
	JLEB		Jump Less Equal Byte
	JGB		Jump Greater Byte
	JGEB		Jump Greater Equal Byte

Unsigned jumps
	JULB		Jump Unsigned Less Byte
	JULEB		Jump Unsigned Less Equal Byte
	JUGB		Jump Unsigned Greater Byte
	JUGEB		Jump Unsigned Greater Equal Byte

Indexed jumps
	JIB		Jump Indexed Byte
	JIW		Jump Indexed Word

Commonly-used exit sequences
	JumpRelativeT	Jump T bytes relative to the current PC
	SetPCAndJump	Restart IFU with new PC in T

Subroutines
	StackPopMinusT	Executes PD← (Stack&-1)-T
%

TopLevel;

*-----------------------------------------------------------
IFUR[J2, 2];	* (regular opcodes are faster than jumps)
IFUJ[J3, 1, Disp[3]];			* Jump n
IFUJ[J4, 1, Disp[4]];
IFUJ[J6, 1, Disp[6]];
IFUJ[J8, 1, Disp[10]];
* PC ← savedPC + n;

IFUJ[JB, 2, SignExtend];		* Jump Byte
* PC ← savedPC + SignExtend[GetCodeByte[]];

IFUR[CATCH, 2];				* Catch
* [] ← GetCodeByte[];
*-----------------------------------------------------------

	NextOpcode;


*-----------------------------------------------------------
IFUP[JW, 3];				* Jump Word
* PC ← savedPC + GetCodeWord[];
*-----------------------------------------------------------

	T← ShiftRMask[RTemp0], RisID;	* LSH[ID, 10]
	T← (ID) OR T, Branch[JumpRelativeT]; * T← alpha,,beta


*-----------------------------------------------------------
NewOp; ESCEntry[JS];			* Jump Stack
* PC ← Pop[];
*-----------------------------------------------------------

	PCF← Stack&-1, Branch[ExitJump];


*-----------------------------------------------------------
IFUR[JZ3, 1, N[3]];		 	* Jump Zero n
IFUR[JZ4, 1, N[4]];
* data: UNSPECIFIED ← Pop[]; IF data=0 THEN PC ← savedPC + n;

IFUR[JZB, 2, SignExtend]; 		* Jump Zero Byte
* data: UNSPECIFIED ← Pop[]; disp: BYTE ← GetCodeByte[];
* IF data=0 THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	PD← Stack&-1, Branch[JETest];


*-----------------------------------------------------------
IFUR[JNZ3, 1, N[3]];		 	* Jump Not Zero n
IFUR[JNZ4, 1, N[4]];
* data: UNSPECIFIED ← Pop[]; IF data#0 THEN PC ← savedPC + n;

IFUR[JNZB, 2, SignExtend]; 		* Jump Not Zero Byte
* data: UNSPECIFIED ← Pop[]; disp: BYTE ← GetCodeByte[];
* IF data#0 THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	PD← Stack&-1, Branch[JNETest];

*-----------------------------------------------------------
IFUR[JEB, 2, SignExtend];		* Jump Equal Byte
* v: UNSPECIFIED ← Pop[]; u: UNSPECIFIED ← Pop[]; disp: BYTE ← GetCodeByte[];
* IF u=v THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	T← Stack&-1, Call[StackPopMinusT];
JETest:
	T← (ID)-(PCX')-1, DblBranch[JNewT, JContF, ALU=0];

JNewT:
	PCF← T, Branch[ExitJump];
JContF:
	NextOpcode;


*-----------------------------------------------------------
IFUR[JNEB, 2, SignExtend];		* Jump Not Equal Byte
* v: UNSPECIFIED ← Pop[]; u: UNSPECIFIED ← Pop[]; disp: BYTE ← GetCodeByte[];
* IF u#v THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	T← Stack&-1, Call[StackPopMinusT];
JNETest:
	T← (ID)-(PCX')-1, DblBranch[JNewF, JContT, ALU#0];

JNewF:
	PCF← T, Branch[ExitJump];
JContT:
	NextOpcode;


*-----------------------------------------------------------
IFUR[JEP, 2, PackedAlpha];		* Jump Equal Pair
* data: UNSPECIFIED ← Pop[]; pair: NibblePair ← GetCodeByte[];
* IF data=pair.left THEN PC ← savedPC + pair.right + 4;
*-----------------------------------------------------------

	PD← (ID)#(Stack&-1);
	T← (ID)-(PCX')-1, Branch[.+2, ALU=0];
	NextOpcode;
	T← T+(4C), Branch[SetPCAndJump];


*-----------------------------------------------------------
IFUR[JNEP, 2, PackedAlpha];		* Jump Not Equal Pair
* data: UNSPECIFIED ← Pop[]; pair: NibblePair ← GetCodeByte[];
* IF data#pair.left THEN PC ← savedPC + pair.right + 4;
*-----------------------------------------------------------

	PD← (ID)#(Stack&-1);
	T← (ID)-(PCX')-1, Branch[.+2, ALU#0];
	NextOpcode;
	T← T+(4C), Branch[SetPCAndJump];

*-----------------------------------------------------------
IFUR[JEBB, 3];				* Jump Equal Byte Byte
* data: UNSPECIFIED ← Pop[]; byte: UNSPECIFIED ← GetCodeByte[];
* disp: UNSPECIFIED ← GetCodeByte[];
* IF data=byte THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	PD← (ID)#(Stack&-1);
	T← (ID)-(200C), Branch[.+2, ALU=0];
	NextOpcode;

* Note: must SignExtend[disp] manually, as disp is the beta byte and the
* hardware sign-extension works only on the alpha byte.
	T← T XOR (177600C), Branch[JumpRelativeT];


*-----------------------------------------------------------
IFUR[JNEBB, 3];				* Jump Not Equal Byte Byte
* data: UNSPECIFIED ← Pop[]; byte: UNSPECIFIED ← GetCodeByte[];
* disp: UNSPECIFIED ← GetCodeByte[];
* IF data#byte THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	PD← (ID)#(Stack&-1);
	T← (ID)-(200C), Branch[.+2, ALU#0];
	NextOpcode;

* Note: must SignExtend[disp] manually, as disp is the beta byte and the
* hardware sign-extension works only on the alpha byte.
	T← T XOR (177600C), Branch[JumpRelativeT];

*-----------------------------------------------------------
IFUR[JLB, 2, SignExtend];		* Jump Less Byte
* disp: BYTE ← GetCodeByte[];
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j<k THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	T← (Stack&-1)-(0C), Branch[JLEBTail]; * Carry← 1


*-----------------------------------------------------------
IFUR[JLEB, 2, SignExtend];		* Jump Less Equal Byte
* disp: BYTE ← GetCodeByte[];
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j<=k THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	T← A← Stack&-1;			* Carry← 0
JLEBTail:
	PD← T-(Stack&-1), XorSavedCarry, Branch[SignedIneqTest];


*-----------------------------------------------------------
IFUR[JGB, 2, SignExtend, N[1]];		* Jump Greater Byte
* disp: BYTE ← GetCodeByte[];
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j>k THEN PC ← savedPC + SignExtend[disp];

IFUR[JGEB, 2, SignExtend, N[0]];	* Jump Greater Equal Byte
* disp: BYTE ← GetCodeByte[];
* k: INTEGER ← Pop[]; j: INTEGER ← Pop[];
* IF j>=k THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	PD← (ID)-1, Q← Stack&-1;	* Carry← 1 for JGB, 0 for JGEB
	PD← (Stack&-1)-Q, XorSavedCarry;
SignedIneqTest:
	Q← PCX', Branch[.+2, ALU<0];
	T← (ID)-Q-1, DblBranch[JNewT, JContF, Overflow'];
	T← (ID)-Q-1, DblBranch[JContT, JNewF, Overflow'];

*-----------------------------------------------------------
IFUR[JULB, 2, SignExtend];		* Jump Unsigned Less Byte
* disp: BYTE ← GetCodeByte[];
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u<v THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	T← (Stack&-1)-(0C), Branch[JULEBTail]; * Carry← 1


*-----------------------------------------------------------
IFUR[JULEB, 2, SignExtend];		* Jump Unsigned Less Equal Byte
* disp: BYTE ← GetCodeByte[];
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u<v THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	T← A← Stack&-1;			* Carry← 0
JULEBTail:
	PD← T-(Stack&-1), XorSavedCarry, Branch[UnsignedIneqTest];


*-----------------------------------------------------------
IFUR[JUGB, 2, SignExtend, N[1]];	* Jump Unsigned Greater Byte
* disp: BYTE ← GetCodeByte[];
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u<v THEN PC ← savedPC + SignExtend[disp];

IFUR[JUGEB, 2, SignExtend, N[0]];	* Jump Unsigned Greater Equal Byte
* disp: BYTE ← GetCodeByte[];
* v: CARDINAL ← Pop[]; u: CARDINAL ← Pop[];
* IF u<v THEN PC ← savedPC + SignExtend[disp];
*-----------------------------------------------------------

	PD← (ID)-1, Q← Stack&-1;	* Carry← 1 for JUGB, 0 for JUGEB
	PD← (Stack&-1)-Q, XorSavedCarry;
UnsignedIneqTest:
	T← (ID)-(PCX')-1, DblBranch[JContT, JNewF, Carry'];

*-----------------------------------------------------------
IFUR[JIB, 3, MemBase[CB], N[0]];	* Jump Indexed Byte
* base: CARDINAL ← GetCodeWord[];
* limit: CARDINAL ← Pop[]; index: CARDINAL ← Pop[];
* IF index<limit THEN {
*   disp: BytePair ← ReadCode[base+index/2];
*   PC ← savedPC + (IF (index MOD 2)=0 THEN disp.left ELSE disp.right)};

IFUR[JIW, 3, MemBase[CB], N[1]];	* Jump Indexed Word
* base: CARDINAL ← GetCodeWord[];
* limit: CARDINAL ← Pop[]; index: CARDINAL ← Pop[];
* IF index<limit THEN {
*   disp: CARDINAL ← ReadCode[base+index];
*   PC ← savedPC + disp};
*-----------------------------------------------------------

	T← Stack&-1, Call[StackPopMinusT];

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

* Out of range, fall through to the next opcode.
	A← ID, Branch[JContF];		* Consume alpha before IFUJump

* In range, evaluate the indexed jump.
JIBWInRange:
	T← ShiftRMask[StackNoUfl&+1], RIsID; * LSH[ID, 10]
	T← RTemp0← (ID) OR T,		* T← alpha,,beta
		DblBranch[JIWFetch, JIBFetch, R odd];

JIBFetch:
	T← (Stack) RSH 1;
	T← (RTemp0)+T, Call[FetchGetsT]; * T← base + index/2
	T← MD, Stack&-1, Branch[.+2, R odd];
	T← RSH[T, 10], Branch[JumpRelativeT]; * Left (even) byte
	T← T AND (377C), Branch[JumpRelativeT]; * Right (odd) byte

JIWFetch:
	T← T+(Stack&-1), Call[FetchGetsT]; * T← base+index
	T← MD, Branch[JumpRelativeT];


*-----------------------------------------------------------
JumpRelativeT:				* Jump T bytes relative to the current PC
*-----------------------------------------------------------

	T← T-(PCX')-1, Branch[SetPCAndJump];


*-----------------------------------------------------------
SetPCAndJump:				* Restart IFU with new PC in T
*-----------------------------------------------------------

	PCF← T, Global;
ExitJump:
	Branch[@J2];			* Nop required by hardware


*-----------------------------------------------------------
StackPopMinusT:				* Executes PD← (Stack&-1)-T
*-----------------------------------------------------------
Subroutine;

	PD← (Stack&-1)-T, Return;