{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 = 355
Two argument opcodes
Alpha byte defines one of the following operations:
{10 clicks} 0 UFADD unboxed floating add
{10 clicks} 1 UFSUB unboxed floating subtract {1st minus 2nd}
{10 clicks} 2 UFISUB unboxed floating subtract {2nd minus 1st}
{10 clicks} 3 UFMULT unboxed floating multiply
{ufn} 4 UFDIV unboxed floating divide
{11 clicks} 5 UGREAT unboxed floating compare {returns T or NIL}
{11 clicks} 6 UMAX unboxed floating maximum
{11 clicks} 7 UMIN unboxed floating minimum
@UNBOX1 two byte opcode = 354
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 8, fl 12, fx ??} 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
}
Set[UF2.add, 0],
Set[UF2.sub, 1],
Set[UF2.isub, 2],
Set[UF2.mult, 3],
Set[UF2.div, 4],
Set[UF2.great, 5],
Set[UF2.max, 6],
Set[UF2.min, 7],
Set[UF1.utob, 0],
Set[UF1.btou, 1],
Set[UF1.abs, 2],
Set[UF1.neg, 3];
{Set[L3.utob, 7];{for CreateCell}}
{@UNBOX2: opcode[355'b],
Bank ← LUBank, c1;
uTOS ← TOS, c2;
uTOSH ← TOSH, CROSS[UB2Start], c3;
}
FloatNop, c1, at[UB2Start];{clear pending unloads}
FloatNop, c2;
, c3;
FloatMode.RN.AI.FAST, FloatFLOW, c1;
FloatAB ← TOSH LRot0, c2;
Xbus ← ibNA, XDisp, L2 ← 0, c3;
MAR ← [rhS, S - 1], DISP4[FOP2op], c1;
FloatAB ← TOS LRot0, CANCELBR[$, 2], c2, at[UF2.add, 10, FOP2op];
TT ← FloatA ← MD, FLPlus, GOTO[FOPtail], c3;
FloatAB ← TOS LRot0, CANCELBR[$, 2], c2, at[UF2.sub, 10, FOP2op];
TT ← FloatA ← MD, FLAMinusB, GOTO[FOPtail], c3;
FloatAB ← TOS LRot0, CANCELBR[$, 2], c2, at[UF2.isub, 10, FOP2op];
TT ← FloatA ← MD, FLBMinusA, GOTO[FOPtail], c3;
FOPtail:
MAR ← [rhS, S + 0], c1;
, c2;
Rx ← FloatA ← MD, c3;
FloatStartFlow, c1;
, c2;
, c3;
PC ← PC + 1, c1;
FloatUnloadS, Float.M, c2;
FloatUnloadS, Float.M, c3;
{Q ← PPort, }GOTO[FOPend], c1;
FOPend:
{Ybus ← Q, YDisp}, c2;
S ← S - 2, DISP4[illegal?, 9], L2Disp, c3;
Xbus ← ib, DISP4[FOP2end], c1, at[9, 10, illegal?];
TOSH ← FloatResult, GOTO[FOP2normend], c2, at[UF2.add, 10, FOP2end];
TOSH ← FloatResult, GOTO[FOP2normend], c2, at[UF2.sub, 10, FOP2end];
TOSH ← FloatResult, GOTO[FOP2normend], c2, at[UF2.isub, 10, FOP2end];
FOP2normend:
TOS ← FloatResult, c3;
FOP2Exit:
Bank ← EmuBank, c1;
IBDisp, L2 ← L2.0, c2;
DISPNI[OpTable], L2 ← L2.0, c3;
S ← S + 2, CANCELBR[dataerr, 0F], c1, at[0B, 10, illegal?];
S ← S + 2, CANCELBR[dataerr, 0F], c1, at[0D, 10, illegal?];
S ← S + 2, CANCELBR[dataerr, 0F], c1, at[0F, 10, illegal?];
dataerr:
PC ← PC - 1, GOTO[ufnX3], c2;
FloatAB ← TOS LRot0, CANCELBR[$, 2], c2, at[UF2.mult, 10, FOP2op];
TT ← FloatA ← MD, FLTimes.A.B, c3;
MAR ← [rhS, S + 0], c1;
, c2;
Rx ← FloatA ← MD, c3;
FloatStartFlow, c1;
, c2;
, c3;
PC ← PC + 1, c1;
FloatUnloadP, Float.M, c2;
FloatUnloadP, Float.M, c3;
{Q ← PPort, }GOTO[FOPend], c1;
CANCELBR[ufnX3, 3], c2, at[UF2.div, 10, FOP2op];
FloatAB ← TOS LRot0, CANCELBR[$, 2], c2, at[UF2.max, 10, FOP2op];
TT ← FloatA ← MD, FLBMinusA, GOTO[FOPtail], c3;
FloatAB ← TOS LRot0, CANCELBR[$, 2], c2, at[UF2.min, 10, FOP2op];
TT ← FloatA ← MD, FLAMinusB, GOTO[FOPtail], c3;
Q ← FloatResult, GOTO[FOP2maxend], c2, at[UF2.max, 10, FOP2end];
Q ← FloatResult, GOTO[FOP2maxend], c2, at[UF2.min, 10, FOP2end];
FOP2maxend:
Ybus ← Q, NegBr, c3;
BRANCH[FOP2noswap, FOP2swap], c1;
FOP2swap:
TOSH ← TT, c2;
TOS ← Rx, GOTO[FOP2Exit], c3;
FOP2noswap:
, c2;
GOTO[FOP2Exit], c3;
FloatAB ← TOS LRot0, CANCELBR[$, 2], c2, at[UF2.great, 10, FOP2op];
TT ← FloatA ← MD, FLAMinusB, GOTO[FOPtail], c3;
Q ← FloatResult, GOTO[FOP2greatend], c2, at[UF2.great, 10, FOP2end];
FOP2greatend:
Ybus ← Q, NegBr, c3;
BRANCH[FOP2NIL, FOP2T], c1;
FOP2NIL:
TOS ← 0, GOTO[FOP2GExit], c2;
FOP2T:
TOS ← KTval, c2;
FOP2GExit:
TOSH ← 0, GOTO[FOP2Exit], c3;
{@UNBOX1: opcode[354'b],
Bank ← LUBank, c1;
uTOS ← TOS, c2;
uTOSH ← TOSH, CROSS[UB1Start], c3;
}
at[UB1Start],
Xbus ← ibNA, XDisp, c1;
DISP4[UB1fn], FloatNop, c2;
{unboxed to boxed}
at[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[UF1.abs, 10, UB1fn],
Rx ← RShift1 Rx xor ~Rx, SE ← 0, c3;
TOSH ← TOSH and Rx, c1;
UBSend:
Xbus ← ib, c2;
PC ← PC + 1, GOTO[FOP2Exit], c3;
{neg of unboxed}
at[UF1.neg, 10, UB1fn],
Rx ← RShift1 0, SE ← 1, c3;
TOSH ← TOSH xor Rx, GOTO[UBSend], c1;
{boxed to unboxed}
at[UF1.btou, 10, UB1fn],
{ GOTO[ufnX1], c3;}
Ybus ← TOSH xor smallpl, ZeroBr, L2 ← L2.btou, c3;
Ybus ← TOSH xor smallpl, ZeroBr, BRANCH[$, btouSP], c1;
TT ← TOS, BRANCH[$, btouSN], c2;
Rx ← TOSH, GOTO[GetFPT], c3;
PC ← PC + 1, c1, at[L2.btou, 10, FptGetRet];
Xbus ← ib, c2;
GOTO[FOP2Exit], c3;
{convert small integers to floating point}
btouSP:
CANCELBR[$], c2;
ufloat ← 0, GOTO[smallconv], c3;
btouSN:
ufloat ← S xor ~S, GOTO[smallconv], c3;
smallconv:
FloatMode.RN.AI.FAST, FloatFLOW, c1;
FloatAB ← ufloat, FLFloatA, c2;
FloatAB ← uTOS, c3;
FloatStartFlow, c1;
, c2;
, c3;
PC ← PC + 1, c1;
FloatUnloadS, Float.M, c2;
FloatUnloadS, Float.L, c3;
Xbus ← ib, c1;
TOSH ← FloatResult, GOTO[FOP2normend], c2;
{ GET FLOATING POINT NUMBER
setup:
argument in Rx,,TT
TOS and TOSH saved in uTOS and uTOSH
L2 has return value
returns:
TOSH,,TOS contain the floating point number
TT contains LRot1 (TOSH)
L0 and L1 are trashed
Q, Rx and TT are trashed
ufnZ if argument not a number
will page fault if value cell not resident
rounds up
}
GetFPT:
MAR ← Q ← [TT, Rx + 0], c1, at[GetFPT];{not mem ref, byte merge}
rhTT ← Rx LRot0, c2;
Rx ← Q, rhRx ← MDSTYPEspaceReal, c3;
Rx ← Rx LRot8, c1;
Rx ← Rx RShift1, SE←1, c2;
, c3;
MAR ← [rhRx, Rx + 0], c1;
Q ← 0FF, c2;
Q ← MD and Q, c3;
Ybus ← Q xor FloatpType, ZeroBr, c1;
Ybus ← Q xor FixpType, ZeroBr, BRANCH[GetnonFpt, $], c2;
CANCELBR[$], c3;
Map ← [rhTT,TT], L0 ← L0.RedofptGet, c1;
Q ← 0FF, L1 ← L1.RestoreTosB2, c2;
Rx ← rhRx ← MD, XRefBr, c3;
MAR ← [rhRx, TT + 0], BRANCH[FptRemap, $], c1, at[L0.RedofptGet, 10, RMapFixCallerB2];
, c2;
TOSH ← MD, c3;
MAR ← [rhRx, TT + 1], c1;
TT ← LRot1 TOSH, CANCELBR[$, 2], L2Disp, c2;
TOS ← MD, RET[FptGetRet], c3;
FptRemap:
CALL[RLMapFixB2], c2;
GetnonFpt: {non-FloatType arg}
CANCELBR[ufnX1], c3;
{
Ybus ← Q xor smallpl, ZeroBr, BRANCH[$, ArgisFixp], c3;
Ybus ← Q xor smallneg, ZeroBr, BRANCH[$, ArgisSmallp], c1;
TOSH ← 0 - 1, BRANCH[ArgNotNumber, ArgisSmallneg], c2;
ArgisFixp:
Map ← [rhTT,TT], L0 ← L0.fxptGet, CANCELBR[$], c1;
L1 ← L1.tosandtosh, c2;
Rx ← rhRx ← MD, XRefBr, c3;
MAR ← [rhRx, TT + 0], BRANCH[FxptRemap, $], c1, at[L0.fxptGet, 10, RxMapFixCaller];
, c2;
TOSH ← MD, c3;
MAR ← [rhRx, TT + 1], c1;
CANCELBR[$, 2], c2;
TOS ← MD, GOTO[ChipConvFixp], c3;
ArgisSmallp:
TOSH ← 0, CANCELBR[$], c2;
TOS ← TT, GOTO[ChipConvSmallC1], c3;
ArgisSmallneg:
TOS ← TT, GOTO[ChipConvSmallC1], c3;
{ to convert using the floating point chip set }
{ small pos and negs will be directly converted in one step using FLOAT
Fixp numbers of less than 25 bits will be directly converted in one step using FLOAT
Fixp numbers of more than 24 bits will have their high and low parts converted separately,
then 16 is added to the exponent of the high part,
and then the two numbers are added
}
ChipConvSmallC3:
, c3;
ChipConvSmallC1:
{number is in TOSH,,TOS}
FloatMode.RN.AI.FAST, FloatULS{flow}, c1;
FloatA ← RRot0 TOSH, FLFloatA, GOTO[ccend], c2;
ccend:
FloatA ← RRot0 TOS, c3;
FloatNop, c1;
Noop, c2;
Noop, c3;
Noop, c1;
FloatUMS, c2;
FloatULS, c3;
TOSH ← FloatResult, c1;
TOS ← FloatResult, L3Disp, c2;
TT ← LRot1 TOSH, RET[FptGetRet], c3;
ChipConvFixp:
{number is in TOSH,,TOS}
{test if number < 24 bits}
Ybus ← TOSH and uFF00, ZeroBr, c2;
Q ← TOSH + 0FF + 1, BRANCH[$, ChipConvSmallC1], c3;
Ybus ← Q and uFF00, ZeroBr, c1;
Ybus ← TOSH, NegBr, BRANCH[$, ChipConvSmallC3], c2;
{if so then GOTO ChipConvSmall}
{else begin}
{SIGN ← 0 or -1}
BRANCH[pos, neg], c3;
pos: uRx{SIGN} ← 0, GOTO[ChipConvLong], c1;
neg: uRx{SIGN} ← Rx xor ~Rx, GOTO[ChipConvLong], c1;
ChipConvLong:
FloatMode.RN.AI.FAST, FloatUMS{pipe}, c2;
FloatA ← uRx{SIGN}, FLFloatA, c3;
FloatA ← FRot0 TOS, c1;
FloatA ← FRot0 Rx, FLFloatA, c2;
FloatA ← FRot0 TOSH, c3;
FloatA ← 08{FloatPump}, Rx ← 08, c1;
FloatA ← FRot0 Rx{FloatPump}, c2;
FloatA ← FRot0 Rx{FloatPump}, c3;
FloatA ← FRot0 Rx{FloatPump}, c1;
FloatA ← FRot0 Rx{FloatPump}, c2;
FloatA ← FRot0 Rx{FloatPump}, c3;
FloatUMS, Rx ← Rx LRot8, c1;
FloatULS, c2;
TOSH ← FloatResult, FloatUMS, c3;
TOS ← FloatResult, FloatULS, c1;
TT ← FloatResult, c2;
Q ← FloatResult, c3;
Rx ← Rx + Q, c1;
FloatMode.RN.AI.FAST, FloatULS{flow}, c2;
FloatAB ← FRot0 Rx, c3;
FloatAB ← FRot0 TT, c1;
FloatA ← FRot0 TOSH, FLPlus, GOTO[ccend], c2;
ccend:
FloatA ← FRot0 TOS, c3;
FloatNop, c1;
Noop, c2;
Noop, c3;
Noop, c1;
FloatUMS, c2;
FloatULS, c3;
TOSH ← FloatResult, c1;
TOS ← FloatResult, L3Disp, c2;
{end}
TT ← LRot1 TOSH, RET[FptGetRet], c3;
ArgNotNumber:
, c3;
}
{ E N D }