{File name LispUnboxed.mc
Description:  DandeLion InterLisp Emulator Unboxed Floating Point OpCodes
Author: Charnley
Last modified: Charnley               5-Jun-84 16:23:45
Created:   1-Jun-84 11:02:56
}

{	@UNBOX2	two byte opcode = 354
	Two argument opcodes
	Alpha byte defines one of the following operations:
	{14 clicks}	0  UFADD  unboxed floating add
	{14 clicks}	1  UFSUB  unboxed floating subtract {1st minus 2nd}
	{14 clicks}	2  UFISUB  unboxed floating subtract {2nd minus 1st}
	{14 clicks}	3  UFMULT  unboxed floating multiply
	{~84 clicks}	4  UFDIV  unboxed floating divide
	{12 clicks}	5  UGREAT  unboxed floating compare {returns T or NIL}
	{13 clicks}	6  UMAX  unboxed floating maximum 
	{13 clicks}	7  UMIN  unboxed floating minimum 

	@UNBOX1	two byte opcode = 355
	Single argument opcodes
	Alpha byte defines one of the following operations:
	{~39 clicks}	0  UTOB  convert unboxed to boxed {always returns boxed floating point number}
	{sm 10, fl 13, fxs 18 fxl 22} 1  BTOU  convert boxed to unboxed {will coerce fixed point numbers}
	{ 4 clicks}	2  UABS  unboxed floating absolute value
	{ 4 clicks}	3  UNEG  unboxed floating negative value
	{ 11 clicks}	4  UFIX  unboxed floating to small integer
}

{
Set[ib.UF2.add, 0],
Set[ib.UF2.sub, 1],
Set[ib.UF2.isub, 2],
Set[ib.UF2.mult, 3],
Set[ib.UF2.div, 4],
Set[ib.UF2.great, 5],
Set[ib.UF2.max, 6],
Set[ib.UF2.min, 7],

Set[ib.UF1.utob, 0],
Set[ib.UF1.btou, 1],
Set[ib.UF1.abs, 2],
Set[ib.UF1.neg, 3];
Set[ib.UF1.fix, 4];
}


{	in bank 1
@UNBOX2:	opcode[354'b],
	Bank ← LUBank, L0 ← L0.UnBoxed,	c1;
	uTOS ← TOS,	c2;
	uTOSH ← TOSH, CROSS[UB2Start],	c3;
	end in bank 1 }

	at[UB2Start],
	Xbus ← ibNA, XDisp, L3 ← L3.UB2Q2,	c1;
	Q ← 0FF, DISP4[ub2op],	c2;

	L2 ← L2.Fplus,	c3, at[ib.UF2.add, 10, ub2op];
	MAR ← [rhS, S - 1], GOTO[ub2cont],	c1;

	L2 ← L2.Fdiff,	c3, at[ib.UF2.sub, 10, ub2op];
	MAR ← [rhS, S - 1], GOTO[ub2cont],	c1;

	L2 ← L2.Fidiff,	c3, at[ib.UF2.isub, 10, ub2op];
	MAR ← [rhS, S - 1], GOTO[ub2cont],	c1;

	L2 ← L2.Ftimes,	c3, at[ib.UF2.mult, 10, ub2op];
	MAR ← [rhS, S - 1], GOTO[ub2cont],	c1;

	TT ← TOSH LRot1, L2 ← L2.Fquot,	c3, at[ib.UF2.div, 10, ub2op];
	Rx ← TT LRot8 and Q, {exponent}, GOTO[ub2Qcont2],	c1;

	L2 ← L2.Fgreat,	c3, at[ib.UF2.great, 10, ub2op];
	MAR ← [rhS, S - 1], GOTO[ub2cont],	c1;

	L2 ← L2.Fmax,	c3, at[ib.UF2.max, 10, ub2op];
	MAR ← [rhS, S - 1], GOTO[ub2cont],	c1;

	L2 ← L2.Fmin,	c3, at[ib.UF2.min, 10, ub2op];
	MAR ← [rhS, S - 1], GOTO[ub2cont],	c1;

{	MAR ← [rhS, S - 1],	c1; }
ub2cont:
	uArg2Hi ← TOSH, CANCELBR[$, 2],	c2;
	TOSH ← MD,	c3;

	MAR ← [rhS, S + 0], L0 ← L0.UnBoxed,	c1;
	uArg2Lo ← TOS, CANCELBR[$, 2],	c2;
	TOS ← MD,	c3;

	Rx ← 0FF + 1, GOTO[fptprep],	c1;

	{ quotient stuff }
		at[L3.UB2Q2, 10, fptQdone],
	Xbus ← ib,	c3;

	S ← S - 2,	c1;
	,	c2;
	GOTO[c1.pc2B2],	c3;

{	in bank 1
@UNBOX1:	opcode[355'b],
	Bank ← LUBank, L0 ← L0.UnBoxed,	c1;
	uTOS ← TOS,	c2;
	uTOSH ← TOSH, CROSS[UB1Start],	c3;
	end bank 1 }

	at[UB1Start],
	Xbus ← ibNA, XDisp,	c1;
	DISP4[UB1fn], FloatNop,	c2;

{**		unboxed to boxed}
	at[ib.UF1.utob, 10, UB1fn],
	uNewValLo ← TOS, L1 ← L1.fixFV,	c3;

	Bank ← EmuBank,	c1;
	uNewValHi ← TOSH, L3 ← L3.utob,	c2;
	Q ← LS4FptType, CROSS[CCEntry],	c3;

{**		abs of unboxed}
	at[ib.UF1.abs, 10, UB1fn],
	Rx ← RShift1 Rx xor ~Rx, SE ← 0,	c3;

	TOSH ← TOSH and Rx,	c1;
UBSend:
	Xbus ← ib,	c2;
	GOTO[c1.pc2B2],	c3;

{**		neg of unboxed}
	at[ib.UF1.neg, 10, UB1fn],
	Rx ← RShift1 0, SE ← 1,	c3;

	TOSH ← TOSH xor Rx, GOTO[UBSend],	c1;
 
{**		boxed to unboxed}
	at[ib.UF1.btou, 10, UB1fn],
	L3 ← L3.btou, FloatNop,	c3;

	FloatNop,	c1;
	CALL[FloatIt],	c2;

	at[L3.btou, 10, FloatItRet],
	Xbus ← ib,	c1;
	,	c2;
	GOTO[c1.pc2B2],	c3;

{**		unboxed to fixed small}
	at[ib.UF1.fix, 10, UB1fn],
	,	c3;

	FloatNop,	c1;
	FloatNop,	c2;
	FloatMode.RZ.AI.FAST{mode must be RZ for FLFixA},	c3;

	TT ← 0FF + 1,		 	c1;	{set PPort to read}
	Q ← uPPsave,			c2;
	PPort ← Q and ~TT,		c3;

	uFix ← TOSH,	c1;
	FloatA ← uFix, FLFixA,	c2;
	FloatA ← TOS LRot0,	c3;

	FloatStartFlow,	c1;
	Noop,	c2;
	Noop,	c3;

	Noop,	c1;
	FloatUnloadS, Float.M,	c2;
	FloatUnloadS, Float.L,	c3;

	TOSH ← FloatResult,	c1;
	Xbus ← PPort, XDisp,	c2;
	TOS ← FloatResult, DISP4[fixres, 3],	c3;

	GOTO[ufnZ2],	c1, at[03, 10, fixres];{invalid operands/denormalized operand}
	GOTO[ufnZ2],	c1, at[07, 10, fixres];{unused/exponent overflow and inexact}
	GOTO[ufnZ2],	c1, at[0B, 10, fixres];{exponent underflow/exponent underflow and inexact}

	Ybus ← TOSH, ZeroBr,	c1, at[0F, 10, fixres];{no exceptions/inexact}
	Ybus ← TOSH + 1, ZeroBr, BRANCH[$, fixanssmp],	c2;
	BRANCH[$, fixanssmn],	c3;

	GOTO[ufnZ2],	c1;

fixanssmp:
	CANCELBR[$],	c3;

	TOSH ← smallpl, GOTO[fixanssm],	c1;

fixanssmn:
	TOSH ← smallneg, GOTO[fixanssm],	c1;

fixanssm:
	Xbus ← ib,	c2;
	GOTO[c1.pc2B2],	c3;

	{ E N D }