{File: <>*>*>FloatPrimitives.mc
Created by Toru Tokunaga 25-Feb-85 19:45:19
This file includes all primitves concerning with floating point operation.
Edit History:
Toru Tokunaga 26-Jun-85 14:23:02
Toru Tokunaga 25-Apr-85 21:44:52 Correct the timesTwoPower Primitive
Toru Tokunaga 9-Apr-85 10:25:48 return linkage change for otMap1Bank0
Toru Tokunaga 9-Apr-85 8:50:08 finish debugging( truncate, fractionPart, exponent, timesTwoPower)
Toru Tokunaga 8-Apr-85 21:18:11 finish the all coding(truncate, fractionPart, exponent, timesTwoPower)
Toru Tokunaga 5-Apr-85 20:03:43 add the table for primitive No.52 ~ 54
Toru Tokunaga 5-Apr-85 15:02:01 add floatTruncated primitive
Toru Tokunaga 2-Apr-85 16:07:55 If FPP status = ~OK or ~InExact --> primitive fail
Toru Tokunaga 1-Apr-85 16:50:22 add float division primitive
Toru Tokunaga 21-Mar-85 14:18:56 modification for moving this microcode from bank1 to bank0
Toru Tokunaga 8-Mar-85 14:30:36 correct stack ACCESS, stackLow + 1 --> stackLow - 1;
Toru Tokunaga 7-Mar-85 17:51:57 if SmallInt > 0 --> Q ←0, otherwise Q ← 0FFFF in primitiveAsFloat
Toru Tokunaga 7-Mar-85 15:06:03 make base of bank2 and bank3 in this file
Toru Tokunaga 5-Mar-85 20:41:52 add the Floating comparison Primitive
Toru Tokunaga 26-Feb-85 16:55:13 Add Asfloat Primitve
}
L4 ← unaryMessage, GOTO[primitiveAsFloat], c3, at[ 8, 10, bank2InBank0];{AsFloat }
temp1Low ← floatAdd, GOTO[floatBinaryMessage], c3, at[ 9, 10, bank2InBank0];{floatAdd}
temp1Low ← floatSub, GOTO[floatBinaryMessage], c3, at[0A, 10, bank2InBank0];{floatSubtract}
temp1Low ← floatLessThan, GOTO[floatBinaryMessage], c3, at[0b, 10, bank2InBank0];{floatLessThan}
temp1Low ← floatGreaterThan, GOTO[floatBinaryMessage], c3, at[0c, 10, bank2InBank0];{floatGreaterThan}
temp1Low ← floatLessOrEqual, GOTO[floatBinaryMessage], c3, at[0d, 10, bank2InBank0];{floatLessOrEqual}
temp1Low ← floatGreaterOrEqual, GOTO[floatBinaryMessage], c3, at[0e, 10, bank2InBank0];{floatGreaterOrEqual}
temp1Low ← floatEqual, GOTO[floatBinaryMessage], c3, at[0f, 10, bank2InBank0];{floatEqual}
temp1Low ← floatNotEqual, GOTO[floatBinaryMessage], c3, at[ 0, 10, bank3InBank0];{floatEqual}
temp1Low ← floatMultiply, GOTO[floatBinaryMessage], c3, at[ 1, 10, bank3InBank0];{floatMultiply}
temp1Low ← floatDivide, GOTO[floatBinaryMessage], c3, at[ 2, 10, bank3InBank0];{float divide}
temp1Low ← floatTruncated, GOTO[floatUnaryMessage], c3, at[ 3, 10, bank3InBank0];{float Truncated}
temp1Low ← floatFractional, GOTO[floatUnaryMessage], c3, at[ 4, 10, bank3InBank0];{fractional part}
temp1Low ← floatExponent, GOTO[floatUnaryMessage], c3, at[ 5, 10, bank3InBank0];{exponent }
L4 ← binaryMessage, GOTO[primitiveTimesTwoPower], c3, at[ 6, 10, bank3InBank0];{ floatTwotimes }
{ L4 indicates that the message is binary message or unary message }
floatUnaryMessage:
MAR ← [stackHigh, stackLow + 0], L1 ← getUnaryFloatReceiver, c1;
uPPsave ← temp1Low, c2; { save the indicator for what kind of primitive }
otLow ← MD, CALL[otMapBank0], c3; { get Oop & to get the real address of Object }
temp1Low ← temp1Low + firstFieldOfObject, c1, at[getUnaryFloatReceiver, 10, otMapBank0-return];
L4 ← unaryMessage, c2; { indicate this primitive = unarymessage }
Q ← 0FF + 1, c3; { preparation for float truncated Primitive }
MAR ← [temp1High, temp1Low + 0], c1;
temp1Low ← temp1Low + 1,CANCELBR[$,2], c2;
temp2Low ← MD, c3; { get the high half of floating point }
MAR ← [temp1High, temp1Low + 0], c1;
Xbus ← uPPsave, XDisp, CANCELBR[$,2], c2; { dispatching for what kind of primitive in unarymessage }
temp3Low ← MD, DISP4[whatKindOfUnaryPrimitive, 0C], c3; { get the low half of flaoting point }
floatBinaryMessage:
L4 ← binaryMessage, c1;
uPPsave ← temp1Low, c2; { save temp1Low indicating the actual operation (i.e. + - / * etc}
GOTO[floatBinary], c3; { }
{
Since floating operation needs two number(receiver,argument),the routine described below common for operation for floating arithmetic , etc
At entry point, L4 has indicator of distinguishing the message pattern (ie: 0 -> UnaryMessage, 1 -> BinaryMessage)
and temp1Low has what kind of primitive we execute
}
floatBinary:
MAR ← [stackHigh, stackLow + 0] , L2 ← getFloatClass c1; { read argument }
temp2Low ← classFloatPointer, c2; { temp2Low has Oop of the FloatCalss to check whether argument's class is floatClass}
otLow ← MD, XDisp, CALL[getClassBank0], c3; { to check the smallinteger or Oop -- commonroutines.mc}
[] ← temp3Low - temp2Low, ZeroBr, c1, at[getFloatClass, 10, getClassBank0-return]; { Class is Float ??}
temp1Low ← temp1Low + firstFieldOfObject, BRANCH[notFloatClass,$], c2; { Point the receiver of real object area -- no header }
Noop, c3; { temp1High,,temp1Low has the address of object }
MAR ← [temp1High, temp1Low + 0], c1; { get the Floating number -- Argument }
temp1Low ← temp1Low + 1, c2;
temp2Low ← MD, c3; { High half of Floaitng number}
MAR ← [temp1High, temp1Low + 0], c1;
stackLow ← stackLow - 1, c2; { to get Receiver's Oop }
temp3Low ← MD, L1 ← getFloatReceiver, c3; { Low half of Floating number }
MAR ← [stackHigh, stackLow + 0], c1; { to get Oop of receiver}
uArg2Hi ← temp2Low, c2; { save high half of argument }
otLow ← MD, CALL[otMapBank0], c3;
temp1Low ← temp1Low + firstFieldOfObject, c1, at[getFloatReceiver, 10, otMapBank0-return];
stackLow ← stackLow + 1, c2; { reset the stack pointer }
Q ← 0FF, c3; { prepare for Float Divide operation }
getFloatNumberHigh:
MAR ← [temp1High, temp1Low + 0 ], c1; { get the Float number}
temp1Low ← temp1Low + 1, c2;
temp2Low ← MD, c3; { get high half (16bits) }
MAR ← [temp1High, temp1Low + 0], c1;
uArg2Lo ← temp3Low, CANCELBR[$,2], c2; { save lowhalf of argument }
temp3Low ← MD, c3; { get low half (16 bits) }
Xbus ← uPPsave, XDisp, c1;
DISP4[whatKindOfBinaryPrimitive], c2;
GOTO[startFloatOperation], c3, at[ 0, 10, whatKindOfBinaryPrimitive]; { FloatAdd }
GOTO[startFloatOperation], c3, at[ 1, 10, whatKindOfBinaryPrimitive]; { FloatSubtract }
{ at[ 2, 10, whatKindOfBinaryPrimitive]; { FloatLessThan }
at[ 3, 10, whatKindOfBinaryPrimitive]; { FloatGreaterThan }
at[ 4, 10, whatKindOfBinaryPrimitive]; { FloatLessThanOrEqual }
at[ 5, 10, whatKindOfBinaryPrimitive]; { FloatGreaterThanOrEqual }
at[ 6, 10, whatKindOfBinaryPrimitive]; { FloatEqual }
at[ 7, 10, whatKindOfBinaryPrimitive]; { FloatNotEqual } }
GOTO[startFloatOperation], c3, at[ 8, 10, whatKindOfBinaryPrimitive]; { FloatMultiply }
{ at[ 9, 10, whatKindOfBinaryPrimitive]; } { FloatDivide }
{ So far, we do not use }
{ at[ 0A, 10, whatKindOfBinaryPrimitive];
at[ 0B, 10, whatKindOfBinaryPrimitive];
at[ 0C, 10, whatKindOfBinaryPrimitive];
at[ 0D, 10, whatKindOfBinaryPrimitive];
at[ 0E, 10, whatKindOfBinaryPrimitive];
at[ 0F, 10, whatKindOfBinaryPrimitive]; }
startFloatOperation:
Q ← 0FF + 1, c1; { to get the FPP status }
PPort ← ~Q, c2; { bus direction = input mode }
Noop,{Q ← uFloatMode,} c3; {}
Xbus ← uPPsave, XDisp, c1; { }
FloatMode.RN.PI.IEEE, FloatFLOW, DISP4[FloatOp], c2; { Dispatch to prepare something for each float primitive operation,
and If operation is Arithmetic(+ - *) Come back to FloatArithCommon --- see below}
FloatArithCommon:
FloatA ← temp3Low LRot0, c1;
FloatStartFlow, c2;
temp3Low ← classFloatPointer, c3; {wait}
uClassToInstantiate ← temp3Low, c1;
temp3Low ← 2, c2; { Object size except header }
FloatUnloadS, Float.M, c3; { to get the result of high half(16 bits)}
FloatUnloadS, Float.L, c1; { to get the result of low half(16 bits)}
nowGetResult:
Q ← PPort, c2; { Get the Status : note -- real state is complemented }
uNewValHi ← FloatResult, c3; { actually get the result of highhalf}
uNewValLo ← FloatResult c1; { actually get the result of lowhalf }
uFloatComResult ← Q, YDisp, c2; { Check status }
Q ← temp1Low xor ~temp1Low, DISP4[FPPStatus, 1], c3; {Q = all 1}
{ You may think that it is waste of the control store, if you think so, please delete this dipatch table. I think it is very useful to debug the microcode. }
ok:
PPort ← Q, GOTO[FPOK], c1, at[0F, 10, FPPStatus]; { Status OK!! Bus direction is BXbus <-- Xbus :: DEFAULT}
inexact:
PPort ← Q, GOTO[FPOK], c1, at[0D, 10, FPPStatus]; { Inexact occur }
unf:
PPort ← Q, GOTO[floatPrimitiveFail2], c1, at[0B, 10, FPPStatus]; { Underflow }
unfinex:
PPort ← Q, GOTO[floatPrimitiveFail2], c1, at[09, 10, FPPStatus]; { Underflow + Inexact }
unused:
PPort ← Q, GOTO[floatPrimitiveFail2], c1, at[07, 10, FPPStatus]; { Unused }
ovf:
PPort ← Q, GOTO[floatPrimitiveFail2], c1, at[05, 10, FPPStatus]; { Overflow }
invalid:
PPort ← Q, GOTO[floatPrimitiveFail2], c1, at[03, 10, FPPStatus]; { Invalid operand }
denormal:
PPort ← Q, GOTO[FPOK], c1, at[01, 10, FPPStatus]; { Denormalized operand }
FPOK:
temp3High ← creatingFloatInstance, c2; {the return link for creating the instance in temp3High}
CALL[createInstanceWithWordsInBank0], c3;
{ Now, we have the object body pointed by temp1High,,temp1Low and new Oop stored in otLow}
retrunFromCreate:
L1 ← floatReturn, c1, at[creatingFloatInstance, 10, createInstanceInBank0-return];
Noop, c2;
{ otLow must have the Oop and temp1High,temp1Low will have the first address of object }
CALL[otMapBank0], c3;
returnFromCreate2:
temp1Low ← temp1Low + firstFieldOfObject, c1,at[floatReturn, 10, otMapBank0-return];
Noop, c2;
Noop, c3;
MAR ← [temp1High,temp1Low + 0], c1; { store the highhalf of the Float number }
MDR ← uNewValHi, CANCELBR[$,2], LOOPHOLE[wok], c2;
temp1Low ← temp1Low + 1, c3;
MAR ← [temp1High, temp1Low + 0], c1; { store the lowhalf of the float number }
MDR ← uNewValLo, CANCELBR[$,2], LOOPHOLE[wok], L4Disp, c2; { L4 has unary or binary }
temp1Low ← nilPointer, BRANCH[unaryMessageReturn,binaryMessageReturn, 0E], c3; {floatTemp has already have the same value as uNewObject}
compareReturn:
Noop, c2;
temp1Low ← nilPointer,GOTO[binaryMessageReturn], c3;
unaryMessageReturn:
MAR ← [stackHigh, stackLow + 0], c1; { store the Oop of the float number to stack}
MDR ← floatTemp, c2;
GOTO[nextByteCodeInBank0], c3; { go to bank1 & dispatch to next bytecode }
binaryMessageReturn:
MAR ← [stackHigh, stackLow + 0], c1;
MDR ← temp1Low, c2; {floatTemp must have nilPointer}
stackLow ← stackLow - 1, GOTO[unaryMessageReturn], c3;
notFloatClass:
CANCELBR[floatPrimitiveFail1], c3; { since stackLow will increase by 1 at destination }
{ Floationg primitive fail }
floatPrimitiveFail1:
Noop, c1;
floatPrimitiveFail2:
Noop, c2;
floatPrimitiveFail3:
temp1Low ← 1, GOTO[saveSmalltalkStateBank0],{GOTO[activateNewMethodInBank0],} c3;
{=== begin: primitive 40 - AsFloat ===}
primitiveAsFloat:
MAR ← [stackHigh, stackLow + 0] , c1; {start read receiver}
Q ← 0, c2; {used for High 8 bit of smallinteger}
temp1Low ← MD, XDisp, c3; {get and check the receiver is smallInteger}
primitiveAsFloat1:
[] ← temp1Low LRot0, XHDisp, { Determine sign of Receiver} BRANCH[PrimFailAsFloat,$,0E], c1;
temp3High ← creatingFloatInstance, BRANCH[positiveInteger,negativeInteger, 2], c2; { return link for createInstanceWithWords}
positiveInteger:
uFloat ← Q, { since positive, high 16bits = all 0} c3;
temp1Low ← RShift1 temp1Low, SE ← 0, GOTO[startFloat], c1; { adjust to real positive smallinteger }
negativeInteger:
uFloat ← ~Q, { since negative, high 16bits = all 1} c3;
temp1Low ← RShift1 temp1Low, SE ← 1, GOTO[startFloat] c1; { adjust to real negative smallinteger }
startFloat:
{ In this routine, I never check the status of Floating point Processor }
FloatMode.RN.PI.IEEE, FloatFLOW, c2;{ Round to nearest, Projective mode, IEEE }
FloatA ← uFloat, FLFloatA, c3;{ high half }
FloatA ← temp1Low LRot0, c1;{ Low 16bits }
FloatStartFlow, c2;
temp3Low ← classFloatPointer, c3;
uClassToInstantiate ← temp3Low, c1;
temp3Low ← 2, c2; { number of needed words for Floating point object }
FloatUnloadS, Float.M, c3; { to Load High half of the floating point and set the retrun address for creating the instance in temp3High}
FloatUnloadS, Float.L, c1; { to load low half of the floaing point}
uNewValHi ← FloatResult, c2; { load the high result }
uNewValLo ← FloatResult, CALL[createInstanceWithWordsInBank0], c3; { load the Low result & GO!! Create Floating Point Instance -- Memorymanglement.mc }
{ At return, otLow and uNewObject have the Oop of new created instance, and uNewValHi,,uNewValLo have the 32bits Floating point number}
PrimFailAsFloat:
CANCELBR[floatPrimitiveFail3], c2; { primitive fail and since stackLow will increase by 1 at destination }
{=== end: primitive 40 - AsFloat ===}
{=== begin: primitive 41 - FloatAdd ===}
primitiveFloatAdd:
uFloatPlus ← temp2Low , c3, at[floatAdd, 10, FloatOp];{ use ufloatPlus, why? -- see MI format for floating point processor}
FloatAB ← uArg2Hi, c1;
FloatAB ← uArg2Lo, c2;
FloatA ← uFloatPlus, FLPlus, GOTO[FloatArithCommon], c3;
{=== end: primitive 41 - FloatAdd ===}
{=== begin: primitive 42 - FloatSubtract ===}
primitiveFloatSubtract:
uFloatMinus ← temp2Low, c3, at[floatSub, 10, FloatOp]; { use ufloatMinus, why ? -- see MI format for floating point processor}
FloatAB ← uArg2Hi, c1;
FloatAB ← uArg2Lo, c2;
FloatA ← uFloatMinus, FLAMinusB, GOTO[FloatArithCommon], c3;
{=== end: primitive 42 - FloatSubtract ===}
{=== begin: primitive 43 - FloatLessThan ===}
primitiveFloatLessThan:
L2 ← L2.floatLessThan, c3, at[floatLessThan, 10, whatKindOfBinaryPrimitive];
CALL[floatCompare], c1;
[] ← floatTemp, NegBr, c2, at[L2.floatLessThan, 10, floatCompare-ret];
BRANCH[lessThanFalse, lessThanTrue], c3;
lessThanFalse:
floatTemp ← falsePointer, GOTO[compareReturn], c1;
lessThanTrue:
floatTemp ← truePointer, GOTO[compareReturn], c1;
{=== end: primitive 43 - FloatLessThan ===}
{=== begin: primitive 44 - FloatGreaterThan ===}
primitiveFloatGreaterThan:
L2 ← L2.floatGreaterThan, c3, at[floatGreaterThan, 10, whatKindOfBinaryPrimitive];
CALL[floatCompare], c1;
[] ← floatTemp xor 1, ZeroBr, c2, at[ L2.floatGreaterThan, 10, floatCompare-ret];
BRANCH[greaterThanFalse, greaterThanTrue], c3;
greaterThanTrue:
floatTemp ← truePointer, GOTO[compareReturn], c1;
greaterThanFalse:
floatTemp ← falsePointer, GOTO[compareReturn] , c1;
{=== end: primitive 44 - FloatGreaterThan ===}
{=== begin: primitive 45 - FloatLessOrEqual ===}
primitiveFloatLessOrEqual:
L2 ← L2.floatLessOrEqual, c3, at[floatLessOrEqual, 10, whatKindOfBinaryPrimitive];
CALL[floatCompare], c1;
[] ← floatTemp xor 1, ZeroBr, c2, at[ L2.floatLessOrEqual, 10, floatCompare-ret];
BRANCH[lessOrEqualTrue, lessOrEqualFalse], c3;
lessOrEqualTrue:
floatTemp ← truePointer, GOTO[compareReturn], c1;
lessOrEqualFalse:
floatTemp ← falsePointer, GOTO[compareReturn], c1;
{=== end: primitive 45 - FloatLessOrEqual ===}
{=== begin: primitive 46 - FloatGreaterOrEqual ===}
primitiveFloatGreaterOrEqual:
L2 ← L2.floatGreaterOrEqual, c3, at[floatGreaterOrEqual, 10, whatKindOfBinaryPrimitive];
CALL[floatCompare], c1;
[] ← floatTemp, NegBr, c2, at[L2.floatGreaterOrEqual, 10, floatCompare-ret];
BRANCH[greaterOrEqualTrue, greaterOrEqualFalse], c3;
greaterOrEqualTrue:
floatTemp ← truePointer, GOTO[compareReturn], c1;
greaterOrEqualFalse:
floatTemp ← falsePointer, GOTO[compareReturn], c1;
{=== end: primitive 46 - FloatGreaterOrEqual ===}
{=== begin: primitive 47 - FloatEqual ===}
primitiveFloatEqual:
L2 ← L2.floatEqual, c3, at[floatEqual, 10, whatKindOfBinaryPrimitive];
CALL[floatCompare], c1;
[] ← floatTemp, ZeroBr, c2, at[L2.floatEqual, 10, floatCompare-ret];
BRANCH[equalFalse, equalTrue], c3;
equalTrue:
floatTemp ← truePointer, GOTO[compareReturn], c1;
equalFalse:
floatTemp ← falsePointer, GOTO[compareReturn], c1;
{=== end: primitive 47 - FloatEqual ===}
{=== begin: primitive 48 - FloatNotEqual ===}
primitiveFloatNotEqual:
L2 ← L2.floatNotEqual, c3, at[floatNotEqual, 10, whatKindOfBinaryPrimitive];
CALL[floatCompare], c1;
[] ← floatTemp, ZeroBr, c2, at[L2.floatNotEqual, 10, floatCompare-ret];
BRANCH[notEqualTrue, notEqualFalse], c3;
notEqualTrue:
floatTemp ← truePointer, GOTO[compareReturn], c1;
notEqualFalse:
floatTemp ← falsePointer, GOTO[compareReturn], c1;
{=== end: primitive 48 - FloatNotEqual ===}
{=== begin: primitive 49 - FloatMultiply ===}
primitiveFloatMultiply:
uFloatMultiply ← temp2Low, c3, at[floatMultiply, 10, FloatOp];
FloatAB ← uArg2Hi, c1;
FloatAB ← uArg2Lo, c2;
FloatA ← uFloatMultiply, FLTimes.A.B, c3;
FloatA ← temp3Low LRot0, c1;
FloatStartFlow, c2;
temp3Low ← classFloatPointer, c3;
uClassToInstantiate ← temp3Low, c1;
temp3Low ← 2, c2;
FloatUnloadP, Float.M, c3;
FloatUnloadP, Float.L, GOTO[nowGetResult], c1;
{=== end: pimitive 49 - FloatMultiply ===}
{=== begin: primitive 50 - FloatDivide ===}
primitiveFloatDivide:
{at this point, Q = 0FF, temp2Low,,temp3Low have the receiver's value, and uArg2Hi,uArg2Lo havethe argument value}
uArg1Hi ← temp2Low, c3, at[ 9, 10, whatKindOfBinaryPrimitive]; { FloatDivide }
uArg1Lo ← temp3Low, c1; { uArg1High,,uArg1Low have Receiver }
L1 ← L1.checkReceiver, c2;
CALL[checkFloatType], c3;
{
Retrun point: floatTemp has the value respectively
Zero : 0
Normal or denormalized number: 1
Infinity: 2
NAN: 3
Also, the component of floating number is stored in temp1Low,temp2Low,temp3Low separately.
** in fixed pitch, -- font: Gatch,system **
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
temp1Low: E E E E E E E E - - - - - - - S
temp2Low: - - - - - - - - - F F F F F F F
temp3Low: F F F F F F F F F F F F F F F F
}
Go1:
Ybus ← floatTemp xor floatNan, ZeroBr, c1, at[ L1.checkReceiver, 10, checkFloatType-return]; { to check if receiver = NAN }
uFloatComResult ← floatTemp, BRANCH[$, receiverIsNan], c2;
floatTemp ← temp1Low and 1, c3;
uSign1 ← floatTemp, c1; { uSign1 = receiver's sign }
Q ← 0FF, c2;
temp1Low ← (temp1Low LRot8) and Q, c3; { receiver's Exponent }
uExp1 ← temp1Low, c1;
temp2Low ← temp2Low LRot8, c2;
floatTemp ← (temp3Low LRot8) and Q, c3;
floatTemp ← temp2Low or floatTemp, c1; { High 16 bit of fractional part -- except leading bit }
uHighHalf1 ← floatTemp, c2;
floatTemp ← temp3Low LRot8, c3;
Q ← ~Q, c1;
floatTemp ← floatTemp and Q, c2;
uLowHalf1 ← floatTemp, c3; { Low 8 bit of fractional part }
temp2Low ← uArg2Hi, c1;
temp3Low ← uArg2Lo, L1 ← L1.checkArgument, c2;
CALL[checkFloatType], c3; { check argument TYPE}
Go8:
Ybus ← floatTemp xor floatNan, ZeroBr, c1, at[L1.checkArgument, 10, checkFloatType-return];
floatTemp ← (LShift1 floatTemp),SE ← 0, BRANCH[$, argumentIsNan], c2;
floatTemp ← LShift1 floatTemp , SE ← 0, c3;
floatTemp ← floatTemp or uFloatComResult, c1;
[] ← floatTemp, YDisp, c2;
Q ← 0FF,DISP4[floatDivideType], c3; { Q : to make NAN }
{According to IEEE standard, NAN must be returned in case of 0.0 / 0.0 operation, but Mesa coded primitive create the ZERO Division }
GOTO[zeroDivision], c1,at[ 0, 10, floatDivideType]; { 0.0 / 0.0 }{primitive Fail - Zero Division }
GOTO[zeroDivision], c1,at[ 1, 10, floatDivideType]; { W / 0.0 }{primitive Fail - Zero Division }
temp1Low ← temp1Low and 1, GOTO[returnInf1], c1,at[ 2, 10, floatDivideType]; { INF / 0.0 }{return INF(receiver:check sign)}
{ at[ 3, 10, floatDivideType];} { NAN / 0.0 }{return NAN}
temp3Low ← uSign1, GOTO[returnZero], c1,at[ 4, 10, floatDivideType]; { 0.0 / W }{return Zero(check sign)}
floatTemp ← temp1Low LRot8,GOTO[prepareDivide], c1,at[ 5, 10, floatDivideType]; { W / W }{to check exponent of argument }
temp1Low ← temp1Low and 1,GOTO[returnInf1], c1,at[ 6, 10, floatDivideType]; { INF / W }{return INF(receiver:check sign)}
{ at[ 7, 10, floatDivideType];} { NAN / W }{return NAN}
temp3Low ← uSign1, GOTO[returnZero], c1,at[ 8, 10, floatDivideType]; { 0.0 / INF }{return Zero(check sign)}
temp3Low ← uSign1, GOTO[returnZero], c1,at[ 9, 10, floatDivideType]; { W / INF }{return Zero(check sign)}
floatTemp ← floatNan,GOTO[returnNan], c1,at[0A, 10, floatDivideType]; { INF / INF }{return NAN}
{ at[0B, 10, floatDivideType];} { NAN / INF }{return NAN}
{ at[0C, 10, floatDivideType];} { 0.0 / NAN }{return NAN}
{ at[0D, 10, floatDivideType];} { W / NAN }{return NAN}
{ at[0E, 10, floatDivideType];} { INF / NAN }{return NAN}
{ at[0F, 10, floatDivideType];} { NAN / NAN }{return NAN}
{------ preparing for returning Nan -----------}
receiverIsNan:
floatTemp ← floatNan,GOTO[returnNan1], c3; { to make a Nan : fractional high part}
argumentIsNan:
floatTemp ← floatNan, c3; { to make a Nan : fractional high part}
returnNan1:
Q ← 0FF,GOTO[returnNan], c1; { to make a Nan : exponent }
returnNan:
{floatTemp = floatNan, Q = 0FF }
temp1Low ← Q, c2; { exponent part = 0FF }
temp3Low ← uSign1, GOTO[finalPack], c3; { packing to make 32 bit floating point format }
zeroDivision:
GOTO[floatPrimitiveFail3], c2;
returnInf1:
{ floatTemp has the argument's sign xor receiver's sign,and Q = 0FF }
temp3Low ← floatTemp, c2; { store the new sign }
temp1Low ← Q, c3; { exponent for infinity }
floatTemp ← floatTemp xor floatTemp, c1; { make high half of fractional part ZERO }
Q ← floatTemp, c2; { make low half of fractional part }
GOTO[finalPack], c3;
returnZero:
temp3Low ← temp1Low xor temp3Low, c2;
temp3Low ← temp3Low and 1, c3; { new Sign }
temp1Low ← 0, c1; { clear exponent }
floatTemp ← 0, c2; { clear high half of fractional part }
Q ← 0,GOTO[finalPack], c3; { clear low half of fractional part }
{dePack the floating point number uSign2,uExp2, uHighHalf2, uLowhalf2 }
prepareDivide:
floatTemp ← floatTemp and Q, ZeroBr, c2; {check argument's exponent = 0 , Q = 0FF}
uExp2 ← floatTemp, BRANCH[argNormal, $], c3; { store exponent part }
{According to IEEE standards, return value must be NAN in this case. If I return the Nan,
it make system trouble, so I ask help to Molasses in this case }
GOTO[floatPrimitiveFail2], c1; { if argment = denormalized number then return the NAN }
argNormal:
floatTemp ← temp1Low and 1, c1; { Sign bit }
uSign2 ← floatTemp, c2; {sign of argument}
temp2Low ← temp2Low or 80, c3; {leading bit = 1 for argument}
argNormal1:
floatTemp ← ~Q, c1;
floatTemp ← temp3Low and floatTemp, c2;
floatTemp ← temp2Low or floatTemp, c3;
floatTemp ← floatTemp LRot8, c1; { high half of fractional part -- argument }
uHighHalf2 ← floatTemp, c2;
temp3Low ← temp3Low LRot8, c3;
temp3Low ← temp3Low and ~0FF, c1;
uLowHalf2 ← temp3Low, c2; { low half of fractional part -- argument : Low byte = 0 }
[] ← uExp1 and Q, ZeroBr, c3; { check receiver's exponent = 0 }
argNormal3:
temp1Low ← uHighHalf1, BRANCH[$, doDivide], c1;
temp2Low ← 80, c2; { to make leading bit =1 for receiver }
floatTemp ← temp2Low LRot8, c3;
argNormal6:
temp1Low ← temp1Low or floatTemp, c1; {receiver's leading bit = 1 }
uHighHalf1 ← temp1Low, GOTO[doDivide0], c2;
{ Now, Receiver = uSign1, uExp1, uHighHalf1,uLowHalf1 ... Argument = uSign2, uExp2, uHighHalf2,uLowHalf2 }
doDivide:
Noop, c2;
doDivide0:
uSaveHomeLow ← homeLow, c3; { to use the homeLow-register for dividing loop }
temp2Low ← uExp1, c1;
temp1Low ← uExp2, c2;
temp2Low ← temp2Low - temp1Low, c3;
temp2Low ← temp2Low + 127'd, c1; { re-bias }
uExp1 ← temp2Low, c2; { result of exponent is stored in uExp1 }
floatTemp ← uSign1, c3;
Q ← uSign2, c1;
uSign1 ← floatTemp xor Q, c2; { result of sign is stored in uSign1 }
divisorHigh ← uHighHalf2, c3;
Q ← ~uLowHalf2, c1;
divisorHigh ← DRShift1 divisorHigh, SE ← 0, c2; { loads the operand and 1 right shiftto allow room shift left during divide loop}
divisorLow ← ~Q, c3;
floatT ← uHighHalf1, c1;
Q ← ~uLowHalf1, c2; { loads the operand and 1 right shiftto allow room shift left during divide loop}
floatT ← DRShift1 floatT, SE ← 0, c3;
{As per Ed Tafts Drado codem we will fo a total 26 iterations, 24 for quatinent, 2 guards bit. They are done by first doing 16 iterations, then 10 iterations}
doDivide6:
Q ← ~Q, L3 ← L3.divide1, c1;
divCount ← 16'd, CALL[fptDivideLoopC3], c2; { 16 times loop }
uHighHalf1 ← divResult, c2, at[L3.divide1, 10, fptDivLoopRets];
floatT ← DLShift1 floatT, SE ← 1,{Q.15 ← 0} L3 ← L3.divide2, c3; {remainder did not get its last left shift}
doDivide7:
divCount ← 10'd, CALL[fptDivideLoopC2], c1; { 10 times loop }
divResult ← divResult LRot4, c2, at[L3.divide2, 10, fptDivLoopRets];
[] ← floatT or Q, NZeroBr, c3;
doDivide8:
divResult ← LShift1 (divResult), SE ← 0, BRANCH[fptDivD, fptDivE], c1;
{ Now, we install the correct sticky bit }
fptDivD:
divResult ← LShift1 (divResult), SE ← 0, GOTO[fptDivF], c2;
fptDivE:
divResult ← LShift1 (divResult), SE ← 1, GOTO[fptDivF], c2;
fptDivF:
uLowHalf1 ← divResult, GOTO[fptDivExit], c3;
fptDivExit:
homeLow ← uSaveHomeLow, c1; { restore the homeLow }
uStickyBit ← 0, c2;
rePackC3:
floatTemp ← uHighHalf1, c3;
Q ← uLowHalf1, c1;
{nominal value = (-1)↑uSighn1 * <floatTemp[0].floatTemp[1],,,Q[7]>*2↑(uExp1 - 127)}
temp1Low ← uExp1, c2;
temp1Low ← temp1Low - 2, c3;
Ybus ← temp1Low, NegBr, c1; { check exponent = 1}
{nominal value = (-1)↑uSign1* <floatTemp[0].floatTemp[1],,Q[7]> *2↑(temp1Low +2 -127)}
normLoop:
Ybus ← floatTemp, NegBr, BRANCH[$, lowExp], c2;
temp1Low ← temp1Low - 1,NegBr, BRANCH[$, normed], c3;
floatTemp ← DLShift1 floatTemp, SE ← 1, BRANCH[normLoop, smallNumber], c1;
{At normed: nominal value = (-1)↑uSign1*<floatTemp[0].floatTemp[1],,Q[7]>*2↑(temp1Low=3-127) and floatTemp[0]=1,
therefore nominal exponent = temp1Low + 2, and nominal fraction = floatTemp[1],,Q[7]}
{At smallNumber: nominal value = (-1)↑uSign1*<floatTemp[0].floatTemp[1],,Q[7]>*2↑(temp1Low+2-127) and floatTemp = -1,
therefore niminal fraction = floatTemp[1],,Q[7]. and nominal exponent= 1 if floatTemp[0]=1, else 0,
i.e. -- niminal exponent = floatTemp[0]}
{At LowExp: nominal value = (-1)↑uSign1*<floatTemp[0].floatTemp[1]..Q[7]>*2↑(temp1Low+2-127) and temp1Low < 0}
{we will shift right one bit , and add 1 to temp1Low, until temp1low = -1, then go to small number}
{Note: this cose is very painful for an exponent of 1, maybe I should avoid arriving here under those conditions?}
lowExp:
temp2Low ← 25'd, CANCELBR[$], c3;
Ybus ← temp1Low + temp2Low, NegBr, c1;
temp2Low ← 1, BRANCH[$, veryLowExp], c2;
Q ← ~Q, L3 ← L3.rePack1, c3; { to allow for complementing on right shifts }
temp1Low ← -temp1Low - 1, CALL[deNormC2], c1;
veryLowExp:
GOTO[floatPrimitiveFail1], c3;
smallNumberC1:
Noop, c1, at[L3.rePack1, 10, deNormRets];
smallNumber:
temp1Low ← RRot1 1, c2;
temp1Low ← LRot1 (temp1Low and floatTemp), c3;{ temp1Low ← nominal exponent = floatTemp[0]}
temp2Low ← RRot1 1, c1;
floatTemp ← floatTemp or temp2Low, c2;{ floatTemp[0] ← 1}
temp1Low ← temp1Low - 3, GOTO[normed], c3;{normed wants temp1Low to hold nominal exponent - 3}
{ nominal value = (-1)↑uSign1*<floatTemp[0].floatTemp[1],,..>*2↑(temp1Low+3-127) and floatTemp[0]=1,
therefore nominal exponent = temp1Low + 2, and nominal fraction = floatTemp[1]..Q[7]}
{also entered from smallnumber, arranged so that nominal Fracrion =<floatTemp[1]....>, floatTemp[0] = 1, and nominal exponent = temp1Low = 3}
normed:
CANCELBR[$], c1;
{******************************** rounding code **************************
enter with
L3 -- return link,
uSticky prepared
data <floatTemp,Q>
if inexact result , will generate trap, or set sticky register bit, depending on contents of sticky register
**************************************************************************}
round:
Ybus ← uStickyBit, NZeroBr, c2;
temp2Low ← 377'b, BRANCH[roundA, roundB], c3;
roundA:
GOTO[roundC], c1;
roundB:
Q ← Q or 1, GOTO[roundC], c1;
roundC:
Ybus ← Q and temp2Low, ZeroBr, c2;
temp2Low ← 200'b, BRANCH[inExact, roundExit1], c3;
{now We round to nearest }
inExact:
Q ← Q + temp2Low, CarryBr, c1;
temp2Low ← 177'b, BRANCH[$, inExact1], c2;
Ybus ← Q and temp2Low, ZeroBr, c3;
temp2Low ← LShift1 200'b, SE ← 0, BRANCH[roundExit2, $], c1;
Q ← Q and ~temp2Low, GOTO[roundExit], c2; {Q[7] ← 0}
{round off carried across word boundary }
inExact1:
floatTemp ← floatTemp + 1, CarryBr, c3; { overflow Branch since floatTemp[0]=1}
BRANCH[roundExit2A, $], c1;
temp1Low ← temp1Low + 1, GOTO[roundExit], c2; { round off overflowed, adjust exponent }
roundExit2A:
GOTO[roundExit], c2;
roundExit1:
Noop, c1;
roundExit2:
Noop, c2;
roundExit:
Noop, c3;
{Now, we check for overflow and underflow }
temp1Low ← temp1Low + 3, c1;
temp2Low ← 376'b, c2;
Ybus ← temp2Low - temp1Low, NegBr, c3; { branch if temp1Low >= 377'B}
Ybus ← temp1Low, ZeroBr,BRANCH[$, overFlowOccur], c1;
BRANCH[$, underFlowOccur], c2;
temp3Low ← uSign1,GOTO[finalPack], c3; { temp3Low has the final sign }
overFlowOccur:
CANCELBR[floatPrimitiveFail3], c2;
underFlowOccur:
GOTO[floatPrimitiveFail1], c3;
{sign = temp3Low, exponent = temp1Low, fractional part = floatTemp[1]...Q[7], floatTemp[0] = 1}
finalPack:
temp2Low ← 0FF, c1;
Q ← Q and ~ temp2Low, c2; { bottom 8 bits of final result }
temp2Low ← floatTemp and temp2Low, c3; { next 8 bits of final result }
temp2Low ← temp2Low or Q, c1;
temp2Low ← temp2Low LRot8, c2; { Low half of fractional part }
uNewValLo ← temp2Low, c3; { store }
temp1Low ← temp1Low LRot8, c1;
temp1Low ← RRot1(temp1Low or temp3Low), c2; { sign,exponent part}
floatTemp ← floatTemp LRot8, c3;
floatTemp ← floatTemp and 7F, c1; { create high 7 bits of fractinal part }
uNewValHi ← temp1Low or floatTemp, c2; { High half of fractional part }
Noop, c3;
finalPack5:
Noop, c1;
temp3Low ← classFloatPointer, c2;
uClassToInstantiate ← temp3Low, c3; { Oop of floatClass }
finalPack7:
temp3Low ← 2, c1; { object size = 2 }
temp3High ← creatingFloatInstance, c2; { return link for createInstance }
CALL[createInstanceWithWordsInBank0], c3; { Go ! }
{=== end: primitive 50 - FloatDivide ===}
{=== begin: primitive 51 - Truncated ===}
primitiveTruncated: { float Truncated primitive}
{Q = 100'x, temp2Low = high half, temp3Low = Low half }
uFloatFix ← temp2Low, c1, at[ 0D, 10, whatKindOfUnaryPrimitive];
PPort ← ~Q, c2; { to get the FPP status }
FloatMode.RZ.PI.IEEE, FloatFLOW, c3;
FloatA ← uFloatFix, FLFixA, c1; { High half & function }
FloatA ← temp3Low LRot0, c2; { low half }
FloatNop, c3;
temp1Low ← 0C0, c1;
temp1Low ← temp1Low LRot8, c2; { temp1Low ← 0C00 : to check the range}
floatTemp ← floatTemp xor ~floatTemp, c3; { floatTemp ← FFFF : to check the range}
FloatUnloadS, Float.M, c1; { to get high 8 bit of 24 bits integer }
FloatUnloadS, Float.L, c2; { to get Low 16 bit of 24 bits integer }
Q ← PPort, c3; { get the FPP status }
temp2Low ← FloatResult, c1;
temp3Low ← FloatResult, c2;
[] ← Q, YDisp, c3; { dispatching by FPP Status }
Q ← temp1Low xor ~ temp1Low, DISP4[FPPStatusFix,1], c1;
fixOk:
PPort ← Q, GOTO[checkRange], c2, at[0F, 10, FPPStatusFix]; { status OK }
PPort ← Q, GOTO[checkRange], c2, at[0D, 10, FPPStatusFix]; {inexact occur: this case is for truncating the denormalized number }
PPort ← Q, GOTO[floatPrimitiveFail3], c2, at[0B, 10, FPPStatusFix]; { Underflow }
PPort ← Q, GOTO[floatPrimitiveFail3], c2, at[09, 10, FPPStatusFix]; { Underflow + Inexact }
PPort ← Q, GOTO[floatPrimitiveFail3], c2, at[07, 10, FPPStatusFix]; { Unused }
PPort ← Q, GOTO[floatPrimitiveFail3], c2, at[05, 10, FPPStatusFix]; { Overflow }
PPort ← Q, GOTO[floatPrimitiveFail3], c2, at[03, 10, FPPStatusFix]; { Invalid operand }
PPort ← Q, GOTO[floatPrimitiveFail3], c2, at[01, 10, FPPStatusFix]; { Denormalized operand at multiply }
checkRange:
{ checking the fix number is in smallinteger's range }
[] ← temp2Low, NegBr, c3;
BRANCH[fixedNumberPlus, fixedNumberMinus], c1;
fixedNumberPlus:
[] ← temp2Low and floatTemp, ZeroBr, c2;
[] ← temp3Low and temp1Low, ZeroBr, BRANCH[outOfRange1, $], c3;
temp3Low ← LShift1 temp3Low, SE ← 1, BRANCH[outOfRange2, $], c1; { create the smallinteger }
GOTO[finishFix], c2;
fixedNumberMinus:
[] ← temp2Low xor floatTemp, ZeroBr, c2;
uSaveStackLow ← temp3Low and temp1Low, BRANCH[outOfRange3, $], c3;
[] ← temp1Low xor uSaveStackLow, ZeroBr, c1;
temp3Low ← LShift1 temp3Low, SE ← 1, BRANCH[outOfRange4, $], c2; { create the smallinteger }
finishFix:
floatTemp ← temp3Low, GOTO[unaryMessageReturn], c3;
outOfRange1:
CANCELBR[floatPrimitiveFail2], c1;
outOfRange2:
GOTO[floatPrimitiveFail3], c2;
outOfRange3:
CANCELBR[floatPrimitiveFail2], c1;
outOfRange4:
GOTO[floatPrimitiveFail1], c3;
{=== end: primitive 51 - Truncated ===}
{=== begin: primitive 52 - FractionalPart ===}
primitiveFractionPart:
{ temp2Low, temp3Low has the Floating Number }
temp1Low ← LRot1 temp2Low, c1, at[0E, 10, whatKindOfUnaryPrimitive];
floatTemp ← temp1Low and 1, c2; { sign }
uSign1 ← floatTemp, c3; { save sign }
fractionPart1:
temp1Low ← temp1Low and ~0FF, c1;
temp1Low ← temp1Low LRot8, c2; { Low byte = exponent}
floatTemp ← temp1Low xor 0FF, c3;
fractionPart2:
[] ← floatTemp, ZeroBr, c1; { check Nan or Inf }
floatTemp ← temp1Low, BRANCH[$, fractionPartNanOrInf], c2;
temp1Low ← temp1Low - 7F, c3;
fractionPart3:
[] ← temp1Low, NegBr, c1; { minus the bias it means count for shift }
Q ← temp3Low, BRANCH[$, returnJustReceiver], c2; { Q has low half of the fractional part}
temp3Low ← temp2Low and 7F, c3; { high 7 bit of the fractional part}
fractionPart4:
temp1Low ← temp1Low + 1, c1; { create the shift counter }
fractionPartShiftLoop:
temp3Low ← DLShift1 temp3Low, SE ← 1, {Q.15 ← 0}, c2; { Left shift the fractional part }
floatTemp ← floatTemp - 1, c3; { decrement the exponent }
fractionPartShiftLoop1:
temp1Low ← temp1Low - 1, ZeroBr, c1; { check shift counter }
temp2Low ← 0FF, BRANCH[$, finishShift], c2; { temp2Low isused after shift operation is finished}
Noop, c3;
fractionPartShiftLoop2:
GOTO[fractionPartShiftLoop], c1;
finishShift:
temp3Low ← temp3Low and temp2Low, c3;
finishShift1:
[] ← temp3Low or Q, ZeroBr, c1; { check fractional part = 0 }
temp1Low ← 80, BRANCH[$, returnValueZero], c2;
normalizeLoop:
[] ← temp3Low and temp1Low, ZeroBr, c3;
floatTemp ← floatTemp - 1, BRANCH[finishNormalize, $], c1;
temp3Low ← DLShift1 temp3Low, SE ← 1,{Q.15 ← 0}, GOTO[normalizeLoop], c2;
finishNormalize:
floatTemp ← floatTemp + 1, c2;
floatTemp ← floatTemp LRot8, c3; { expponent }
floatTemp ← floatTemp or uSign1, c1; { or the sign }
temp1Low ← RRot1 floatTemp, c2;
temp3Low ← temp3Low and 7F, c3; { implict leading bit = 0}
uNewValHi ← temp1Low or temp3Low, c1; { high half of the floating point number }
uNewValLo ← Q, GOTO[returnResult3], c2;
returnValueZero:
uNewValHi ← temp1Low xor temp1Low, c3;
uNewValLo ← temp1Low xor temp1Low, GOTO[returnResult2], c1; { creating the normal zero }
returnJustReceiver:
uNewValHi ← temp2Low, c3;
uNewValLo ← temp3Low, GOTO[returnResult2], c1;
returnResult2:
Noop, c2;
returnResult3:
temp3High ← creatingFloatInstance, c3;
temp3Low ← classFloatPointer, c1;
uClassToInstantiate ← temp3Low, c2;
temp3Low ← 2, CALL[createInstanceWithWordsInBank0], c3;
fractionPartNanOrInf:
CANCELBR[floatPrimitiveFail1], c3;
{=== end: primitive 52 - FractionalPart ===}
{=== begin: primitive 53 - Exponent ===}
{
definition: return the exponent value as a smallinteger.
floating point number = normal Zero then return the -1
If receiver = Infinity or Nan then PrimitiveFail
}
primitiveExponent:
floatTemp ← 7F, c1, at[0F, 10, whatKindOfUnaryPrimitive];
floatTemp ← floatTemp LRot8, c2; {7F00}
floatTemp ← floatTemp or 0FF, c3; {make 7FFF}
primitiveExponent1:
floatTemp ← temp2Low and floatTemp, c1; { ignore sign}
[] ← temp3Low or floatTemp, ZeroBr, c2; { check normal zero or not }
BRANCH[notNormalZero, normalZero], c3;
normalZero:
floatTemp ← floatTemp xor ~floatTemp , GOTO[exponentReturnResult1], c1; { make the smallinteger (-1) }
notNormalZero:
temp2Low ← LRot1 temp2Low, c1;
temp2Low ← temp2Low and ~0FF, c2; {high byte is exponent }
floatTemp ← temp2Low xor ~0FF, c3;
[] ← floatTemp, ZeroBr, c1; { check exponent = 0FF : Nan or Infinity }
temp2Low ← temp2Low LRot8, BRANCH[$, exponentNanOrInf], c2;
temp2Low ← temp2Low - 7F, c3; {NET = minus the bias from gross exponent }
exponentReturnResult:
floatTemp ← LShift1 temp2Low, SE ← 1, c1;
exponentReturnResult1:
Noop, c2;
GOTO[unaryMessageReturn], c3;
exponentNanOrInf:
GOTO[floatPrimitiveFail1], c3;
{=== endL Primitive 53 - Exponent ===}
{=== begin: primitive 54 - TimesTwoPower ===}
primitiveTimesTwoPower:
MAR ← [stackHigh, stackLow + 0], c1; { point the argument }
Noop, c2;
temp1Low ← MD, XDisp, c3; { get argument and check that argument = smallinteger }
[] ← temp1Low LRot0, XHDisp, {Determine the sign }BRANCH[primFailTimesTwoPower, $, 0E], c1;
stackLow ← stackLow - 1, BRANCH[positiveInteger1, negativeInteger1, 2], c2; { point the receiver }
positiveInteger1:
temp1Low ← RShift1 temp1Low, SE ← 0, GOTO[getReceiver], c3;
negativeInteger1:
temp1Low ← RShift1 temp1Low, SE ← 1, c3;
getReceiver:
MAR ← [stackHigh, stackLow + 0], L1 ← getTimesTwoPowerReceiver, c1;
uArg2Lo ← temp1Low, c2; { save the argument value }
otLow ← MD, CALL[otMap1Bank0], c3;
getReceiver1:
temp1Low ← temp1Low + firstFieldOfObject, c1, at[getTimesTwoPowerReceiver, 10, otMap1Bank0-return];
stackLow ← stackLow + 1, c2; { reset the stack pointer }
Q ← 0FF, c3;
getReceiver2:
MAR ← [temp1High, temp1Low + 0], c1;
temp1Low ← temp1Low + 1, c2;
temp2Low ← MD, c3; { get high half of the floating point number and check 0}
getReceiver3:
MAR ← [temp1High, temp1Low + 0], c1;
floatTemp ← uArg2Lo, c2; { load the value for adding the exponent }
temp3Low ← MD, c3; { get low half of the floating point number }
getReciever3X:
temp1Low ← 7F, c1;
temp1Low ← temp1Low LRot8, c2;
temp1Low ← temp1Low or 0FF, c3; { to neglect the sign }
getReceiver3XX:
[] ← temp1Low and temp2Low,ZeroBr, c1;
[] ← temp3Low,ZeroBr, BRANCH[hHalfNonZero, hHalfZero], c2;
hHalfZero:
uNewValLo ← temp1Low xor temp1Low, BRANCH[lHalfNonZero, resultZero], c3;
resultZero:
uNewValHi ← temp1Low xor temp1Low, GOTO[storeResult], c1;
hHalfNonZero:
CANCELBR[getReceiver4], c3;
lHalfNonZero:
temp1Low ← LRot1 temp2Low,GOTO[getReceiver4X], c1; { high byte is exponent }
getReceiver4:
temp1Low ← LRot1 temp2Low, c1; { high byte is exponent }
getReceiver4X:
temp1Low ← temp1Low LRot8, c2;
temp1Low ← temp1Low and Q, c3; { temp1Low has exponent }
getReceiver5:
[] ← temp1Low xor Q, ZeroBr, c1;{ chedk Nan or Inf }
temp1Low ← temp1Low + floatTemp,NegBr,BRANCH[$, timesTwoPowerNanOrInf], c2; { Add & check Low boundary}
Ybus ← temp1Low - Q,NegBr, BRANCH[$, exponentTooSmall], c3; { check high boundary }
getReceiver7:
uNewValLo ← temp3Low, BRANCH[exponentTooLarge, $], c1; { Low half of the floating point number }
temp1Low ← temp1Low LRot8, c2; { high byte is exponent }
temp2Low ← LRot1 temp2Low, c3;
getReceiver8:
temp2Low ← temp2Low and 0FF, c1; { clear the exponent part }
temp1Low ← temp1Low or temp2Low , c2; { new exponent value is ored }
temp1Low ← RRot1 temp1Low, c3; { finish the high half of the floating point }
getReceiver9:
uNewValHi ← temp1Low, c1; { get the high half of the result }
storeResult:
temp3High ← creatingFloatInstance, c2; { returnlink for createInstance }
temp3Low ← classFloatPointer, c3;
uClassToInstantiate ← temp3Low, c1; { class pointer for newly created object }
temp3Low ← 2, c2; { temp3Low has the actual size, to create the floating point object}
CALL[createInstanceWithWordsInBank0], c3;
primFailTimesTwoPower:
CANCELBR[floatPrimitiveFail3], c2;
timesTwoPowerNanOrInf:
CANCELBR[floatPrimitiveFail1], c3;
exponentTooSmall:
CANCELBR[floatPrimitiveFail2], c1;
exponentTooLarge:
GOTO[floatPrimitiveFail3], c2;
{=== end: primitive 54 - TimesTwoPower ===}